// same as above, but moveresize instead of just move at the first step, // then resize to the provided w/h instead of a snapshotted one // this implementation differs from Move in that it makes no effort to be end-synchronous // This function waits only on the window's inner geometry resizing, not on actual movement occuring func MoveResize(win *xwindow.Window, x, y, width, height int) error { // snapshot window dimensions base, err := win.Geometry() if err != nil { return err } // move window then wait... err = win.WMMoveResize(x, y, width, height) if err != nil { return err } err = PollFor(win, GeometryDiffers(base)) if err != nil { return err } // check that the new geometry is what we requested // this may be inadvisable: what about window hints? geom, err := win.Geometry() if err != nil { return err } if geom.Width() != width || geom.Height() != height { // something derped! resize to make it right! // if window hints constrained us, this won't upset them log.Println("MoveResize: resizing again after incorrect new dimensions") err = win.WMResize(width, height) if err != nil { return err } } return nil }
func Geometries(win *xwindow.Window) (xrect.Rect, xrect.Rect, error) { decor, err := win.DecorGeometry() if err != nil { return nil, nil, err } base, err := win.Geometry() if err != nil { return nil, nil, err } return decor, base, nil }
// resize a window by a certain number of pixels in a given direction. // This function tries to prevent the window from moving func ResizeDirection(X *xgbutil.XUtil, win *xwindow.Window, dir wm.Direction, px int) error { // we resize around the decor_geometry of the window if px == 0 { // no need to resize return nil } geom, err := win.Geometry() if err != nil { return fmt.Errorf("Resize: coudn't get normal geometry: %v", err) } w, h := geom.Width(), geom.Height() log.Printf("ResizeDirection: pre_geom == %v\n", geom) if dir == wm.Left || dir == wm.Right { // horizontal resize w += px } else { h += px } // two-step resize -> move process, to compensate for WM peculiarities and window sizing hints // first save the initial position info pre_decor, err := win.DecorGeometry() if err != nil { return fmt.Errorf("Resize: coudn't get decorated geometry: %v", err) } // resize the window err = win.WMResize(w, h) if err != nil { return err } // wait for the geometry to change // we use a goroutine to query X a bunch while waiting for the window // to finish resizing err = wm.PollFor(win, wm.DecorDiffers(pre_decor), wm.GeometryDiffers(geom)) if err != nil { return fmt.Errorf("ResizeDirection: error waiting for window geometries to change: %v", err) } post_decor, post_geom, err := wm.Geometries(win) if err != nil { return err } log.Printf("ResizeDirection: post_decor == %v\n", post_decor) log.Printf("ResizeDirection: post_geom == %v\n", post_geom) // the opposite edge should stay in the same place op := dir.Opposite() pre_edge := EdgePos(pre_decor, op) post_edge := EdgePos(post_decor, op) delta := post_edge - pre_edge x, y := post_decor.X(), post_decor.Y() // move the window upwards by our height resize so that the bottom edge stays in the same place if dir == wm.Top || dir == wm.Bottom { y -= delta } // move the window right by our resize so that the right stays in the same place if dir == wm.Left || dir == wm.Right { x -= delta } // move to lock opposite edge return wm.Move(win, x, y) }