// find the EWHM window under the mouse cursor func FindManagedWindowUnderMouse(X *xgbutil.XUtil) (xproto.Window, error) { // construct a hashset of the managed windows clients, err := ewmh.ClientListGet(X) if err != nil { return 0, fmt.Errorf("FindUnderMouse: could not retrieve EWHM client list: %v", err) } managed := make(map[xproto.Window]bool, len(clients)) for _, win := range clients { managed[win] = true } cur_window := X.RootWin() // descend the QueryTree to the first child that is a EWMH managed window for { // return the parent if it is an EWHM window if _, ok := managed[cur_window]; ok { return cur_window, nil } cur_window, _, err = FindNextUnderMouse(X, cur_window) if err != nil { break } } // we didn't find the window :( return 0, errors.New("FindUnderMouse: no EWMH window found under mouse") }
//GetClients get windows list func GetClients() []Client { clients := []Client{} var err error X, err = xgbutil.NewConn() if err != nil { log.Fatal(err) } wids, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } a, _ := ewmh.ActiveWindowGet(X) for _, wid := range wids { name, err := ewmh.WmNameGet(X, wid) if name == "Shadow" { SHADOW = wid continue } if err != nil { // not a fatal error log.Println(err) name = "" } desk, _ := ewmh.WmDesktopGet(X, wid) class, _ := icccm.WmClassGet(X, wid) clients = append(clients, Client{ wid, name, desk, wid == a, class.Class, }) } return clients }
func (r *Region) getDockWindow() (xproto.Window, error) { windows, _ := ewmh.ClientListGet(XU) for _, xid := range windows { res, err := icccm.WmClassGet(XU, xid) if err == nil && res.Instance == "dde-dock" { return xid, nil } } return 0, errors.New("find dock window failed, it's not existed.") }
func (self *SessionModule) GetAllWindows() ([]SessionWindow, error) { clients, _ := ewmh.ClientListGet(self.X) // allocate window objects windows := make([]SessionWindow, len(clients)) // for each window... for i, id := range clients { windows[i], _ = self.GetWindow(strconv.Itoa(int(id))) } return windows, nil }
func walkClientList(pre func(xproto.Window) bool) bool { list, err := ewmh.ClientListGet(XU) if err != nil { logger.Warning("Can't get _NET_CLIENT_LIST", err) return false } for _, c := range list { if pre(c) { return true } } return false }
func (rs RunningSource) GetMatches(inp string, ct *CommandTray) []Command { cmds := make([]Command, 0) if ct.X == nil { return []Command{} } clis, err := ewmh.ClientListGet(ct.X) if err != nil { return cmds } for _, xwin := range clis { dt, err := ewmh.CurrentDesktopGet(ct.X) if err != nil { dt = 0xFFFFFFFF } wdt, err := ewmh.WmDesktopGet(ct.X, xwin) if err != nil { wdt = dt } if dt != wdt { continue } name, err := xprop.PropValStr(xprop.GetProperty(ct.X, xwin, "_NET_WM_NAME")) if err != nil { //print("Err1: ", err.Error(), "\n") name, err = xprop.PropValStr(xprop.GetProperty(ct.X, xwin, "WM_NAME")) if err != nil { //print("Err2: ", err.Error(), "\n") name = "Unnamed Window" } } if strings.Contains(strings.ToLower(name), inp) { cmds = append(cmds, RunningCommand{X: ct.X, win: xwin, name: name}) } } return cmds }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Get the list of window ids managed by the window manager. clients, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } // For each client, try to find its icon. If we find one, blend it with // a nice background color and show it in its own window. // Otherwise, skip it. for _, wid := range clients { // FindIcon will find an icon closest to the size specified. // If one can't be found, the resulting image will be scaled // automatically. // To avoid scaling the icon, specify '0' for both the width and height. // In this case, the largest icon found will be returned. xicon, err := xgraphics.FindIcon(X, wid, iconWidth, iconHeight) if err != nil { log.Printf("Could not find icon for window %d.", wid) continue } // Get the name of this client. (It will be set as the icon window's // name.) name, err := ewmh.WmNameGet(X, wid) if err != nil { // not a fatal error log.Println(err) name = "" } // Blend a pink background color so its easy to see that alpha blending // works. xgraphics.BlendBgColor(xicon, color.RGBA{0xff, 0x0, 0xff, 0xff}) xicon.XShowExtra(name, false) } // All we really need to do is block, so a 'select{}' would be sufficient. // But running the event loop will emit errors if anything went wrong. xevent.Main(X) }
func main() { X, _ := xgbutil.NewConn() heads, err := xinerama.PhysicalHeads(X) if err != nil { fmt.Printf("ERROR: %v\n", err) } // Test intersection r1 := xrect.New(0, 0, 100, 100) r2 := xrect.New(100, 100, 100, 100) fmt.Println(xrect.IntersectArea(r1, r2)) // Test largest overlap window := xrect.New(1800, 0, 300, 200) fmt.Println(xrect.LargestOverlap(window, heads)) // Test ApplyStrut rgeom, _ := xwindow.RawGeometry(X, xproto.Drawable(X.RootWin())) fmt.Println("---------------------------") for i, head := range heads { fmt.Printf("%d - %v\n", i, head) } // Let's actually apply struts to the current environment clients, _ := ewmh.ClientListGet(X) for _, client := range clients { strut, err := ewmh.WmStrutPartialGet(X, client) if err == nil { xrect.ApplyStrut(heads, rgeom.Width(), rgeom.Height(), strut.Left, strut.Right, strut.Top, strut.Bottom, strut.LeftStartY, strut.LeftEndY, strut.RightStartY, strut.RightEndY, strut.TopStartX, strut.TopEndX, strut.BottomStartX, strut.BottomEndX) } } fmt.Println("---------------------------") fmt.Println("After applying struts...") for i, head := range heads { fmt.Printf("%d - %v\n", i, head) } }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Get a list of all client ids. clientids, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } // Iterate through each client, find its name and find its size. for _, clientid := range clientids { name, err := ewmh.WmNameGet(X, clientid) // If there was a problem getting _NET_WM_NAME or if its empty, // try the old-school version. if err != nil || len(name) == 0 { name, err = icccm.WmNameGet(X, clientid) // If we still can't find anything, give up. if err != nil || len(name) == 0 { name = "N/A" } } // Now find the geometry, including decorations, of the client window. // Note that DecorGeometry actually traverses the window tree by // issuing QueryTree requests until a top-level window (i.e., its // parent is the root window) is found. The geometry of *that* window // is then returned. dgeom, err := xwindow.New(X, clientid).DecorGeometry() if err != nil { log.Printf("Could not get geometry for %s (0x%X) because: %s", name, clientid, err) continue } fmt.Printf("%s (0x%x)\n", name, clientid) fmt.Printf("\tGeometry: %s\n", dgeom) } }
func main() { var err error X, err = xgbutil.NewConn() if err != nil { log.Fatal(err) } clientids, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } for _, clientid := range clientids { name, err := ewmh.WmNameGet(X, clientid) if err != nil { continue } if name == "Super Hexagon" { HexWindow = xwindow.New(X, clientid) break } } if HexWindow == nil { log.Fatal("Couldn't find Super Hexagon window.") } //Create a window DisplayWindow, err = xwindow.Generate(X) if err != nil { log.Fatalf("Could not generate a new window X id: %s", err) } dgeom, _ := HexWindow.DecorGeometry() DisplayWindow.Create(X.RootWin(), 0, 0, dgeom.Width(), dgeom.Height(), xproto.CwBackPixel, 0) DisplayWindow.Map() //Start the routine that updates the window go updater() xevent.Main(X) }
func (m *ClientManager) listenRootWindow() { var update = func() { list, err := ewmh.ClientListGet(XU) if err != nil { logger.Warning("Can't Get _NET_CLIENT_LIST", err) } isLauncherShown = false for _, xid := range list { if !isDeepinLauncher(xid) { continue } winProps, err := xproto.GetWindowAttributes(XU.Conn(), xid).Reply() if err != nil { break } if winProps.MapState == xproto.MapStateViewable { isLauncherShown = true } break } ENTRY_MANAGER.runtimeAppChanged(list) } xwindow.New(XU, XU.RootWin()).Listen(xproto.EventMaskPropertyChange) xevent.PropertyNotifyFun(func(XU *xgbutil.XUtil, ev xevent.PropertyNotifyEvent) { switch ev.Atom { case _NET_CLIENT_LIST: update() case _NET_ACTIVE_WINDOW: var err error isLauncherShown = false if activeWindow, err = ewmh.ActiveWindowGet(XU); err == nil { appId := find_app_id_by_xid(activeWindow, DisplayModeType(setting.GetDisplayMode())) logger.Debug("current active window:", appId) if rApp, ok := ENTRY_MANAGER.runtimeApps[appId]; ok { logger.Debug("find runtime app") rApp.setLeader(activeWindow) rApp.updateState(activeWindow) } logger.Debug("active window is", appId) if appId != DDELauncher { LAUNCHER, err := launcher.NewLauncher( "com.deepin.dde.launcher", "/com/deepin/dde/launcher", ) if err != nil { logger.Debug(err) } else { LAUNCHER.Hide() launcher.DestroyLauncher(LAUNCHER) } } else { isLauncherShown = true } lastActive = appId dbus.Emit(m, "ActiveWindowChanged", uint32(activeWindow)) } hideMode := HideModeType(setting.GetHideMode()) if hideMode == HideModeSmartHide || hideMode == HideModeKeepHidden { hideModemanager.UpdateState() } case _NET_SHOWING_DESKTOP: dbus.Emit(m, "ShowingDesktopChanged") case DEEPIN_SCREEN_VIEWPORT: updateCurrentViewport() } }).Connect(XU, XU.RootWin()) update() xevent.Main(XU) }
func main() { // Connect to the X server using the DISPLAY environment variable. X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Wrap the root window in a nice Window type. root := xwindow.New(X, X.RootWin()) // Get the geometry of the root window. rgeom, err := root.Geometry() if err != nil { log.Fatal(err) } // Get the rectangles for each of the active physical heads. // These are returned sorted in order from left to right and then top // to bottom. // But first check if Xinerama is enabled. If not, use root geometry. var heads xinerama.Heads if X.ExtInitialized("XINERAMA") { heads, err = xinerama.PhysicalHeads(X) if err != nil { log.Fatal(err) } } else { heads = xinerama.Heads{rgeom} } // Fetch the list of top-level client window ids currently managed // by the running window manager. clients, err := ewmh.ClientListGet(X) if err != nil { log.Fatal(err) } // Output the head geometry before modifying them. fmt.Println("Workarea for each head:") for i, head := range heads { fmt.Printf("\tHead #%d: %s\n", i+1, head) } // For each client, check to see if it has struts, and if so, apply // them to our list of head rectangles. for _, clientid := range clients { strut, err := ewmh.WmStrutPartialGet(X, clientid) if err != nil { // no struts for this client continue } // Apply the struts to our heads. // This modifies 'heads' in place. xrect.ApplyStrut(heads, uint(rgeom.Width()), uint(rgeom.Height()), strut.Left, strut.Right, strut.Top, strut.Bottom, strut.LeftStartY, strut.LeftEndY, strut.RightStartY, strut.RightEndY, strut.TopStartX, strut.TopEndX, strut.BottomStartX, strut.BottomEndX) } // Now output the head geometry again after modification. fmt.Println("Workarea for each head after applying struts:") for i, head := range heads { fmt.Printf("\tHead #%d: %s\n", i+1, head) } }
func main() { X, Xerr = xgbutil.NewConn() if Xerr != nil { panic(Xerr) } active, _ := ewmh.ActiveWindowGet(X) parent, _ := xwindow.ParentWindow(X, active) actOpacity, _ := ewmh.WmWindowOpacityGet(X, parent) fmt.Printf("Opacity for active window: %f\n", actOpacity) showDesk, _ := ewmh.ShowingDesktopGet(X) fmt.Printf("Showing desktop? %v\n", showDesk) wmName, err := ewmh.GetEwmhWM(X) if err != nil { fmt.Printf("No conforming window manager found... :-(\n") fmt.Println(err) } else { fmt.Printf("Window manager: %s\n", wmName) } pager := xproto.Window(0x160001e) middle := xproto.Window(0x3200016) geom, _ := ewmh.DesktopGeometryGet(X) desktops, _ := ewmh.DesktopNamesGet(X) curdesk, _ := ewmh.CurrentDesktopGet(X) clients, _ := ewmh.ClientListGet(X) activeName, _ := ewmh.WmNameGet(X, active) fmt.Printf("Active window: %x\n", active) fmt.Printf("Current desktop: %d\n", curdesk) fmt.Printf("Client list: %v\n", clients) fmt.Printf("Desktop geometry: (width: %d, height: %d)\n", geom.Width, geom.Height) fmt.Printf("Active window name: %s\n", activeName) fmt.Printf("Desktop names: %s\n", desktops) var desk string if curdesk < len(desktops) { desk = desktops[curdesk] } else { desk = string(curdesk) } fmt.Printf("Current desktop: %s\n", desk) // fmt.Printf("\nChanging current desktop to 25 from %d\n", curdesk) ewmh.CurrentDesktopSet(X, curdesk) // fmt.Printf("Current desktop is now: %d\n", ewmh.CurrentDesktop(X)) fmt.Printf("Setting active win to %x\n", middle) // ewmh.ActiveWindowReq(X, middle) rand.Seed(int64(time.Now().Nanosecond())) randStr := make([]byte, 20) for i, _ := range randStr { if rf := rand.Float32(); rf < 0.40 { randStr[i] = byte('a' + rand.Intn('z'-'a')) } else if rf < 0.80 { randStr[i] = byte('A' + rand.Intn('Z'-'A')) } else { randStr[i] = ' ' } } ewmh.WmNameSet(X, active, string(randStr)) newName, _ := ewmh.WmNameGet(X, active) fmt.Printf("New name: %s\n", newName) // deskNames := ewmh.DesktopNamesGet(X) // fmt.Printf("Desktop names: %s\n", deskNames) // deskNames[len(deskNames) - 1] = "xgbutil" // ewmh.DesktopNamesSet(X, deskNames) // fmt.Printf("Desktop names: %s\n", ewmh.DesktopNamesGet(X)) supported, _ := ewmh.SupportedGet(X) fmt.Printf("Supported hints: %v\n", supported) fmt.Printf("Setting supported hints...\n") ewmh.SupportedSet(X, []string{"_NET_CLIENT_LIST", "_NET_WM_NAME", "_NET_WM_DESKTOP"}) numDesks, _ := ewmh.NumberOfDesktopsGet(X) fmt.Printf("Number of desktops: %d\n", numDesks) // ewmh.NumberOfDesktopsReq(X.EwmhNumberOfDesktops(X) + 1) // time.Sleep(time.Second) // fmt.Printf("Number of desktops: %d\n", ewmh.NumberOfDesktops(X)) viewports, _ := ewmh.DesktopViewportGet(X) fmt.Printf("Viewports (%d): %v\n", len(viewports), viewports) // viewports[2].X = 50 // viewports[2].Y = 293 // ewmh.DesktopViewportSet(X, viewports) // time.Sleep(time.Second) // // viewports = ewmh.DesktopViewport(X) // fmt.Printf("Viewports (%d): %v\n", len(viewports), viewports) // ewmh.CurrentDesktopReq(X, 3) visDesks, _ := ewmh.VisibleDesktopsGet(X) workarea, _ := ewmh.WorkareaGet(X) fmt.Printf("Visible desktops: %v\n", visDesks) fmt.Printf("Workareas: %v\n", workarea) // fmt.Printf("Virtual roots: %v\n", ewmh.VirtualRoots(X)) // fmt.Printf("Desktop layout: %v\n", ewmh.DesktopLayout(X)) fmt.Printf("Closing window %x\n", 0x2e004c5) ewmh.CloseWindow(X, 0x1e00cdf) fmt.Printf("Moving/resizing window: %x\n", 0x2e004d0) ewmh.MoveresizeWindow(X, 0x2e004d0, 1920, 30, 500, 500) // fmt.Printf("Trying to initiate a moveresize...\n") // ewmh.WmMoveresize(X, 0x2e004db, xgbutil.EwmhMove) // time.Sleep(5 * time.Second) // ewmh.WmMoveresize(X, 0x2e004db, xgbutil.EwmhCancel) // fmt.Printf("Stacking window %x...\n", 0x2e00509) // ewmh.RestackWindow(X, 0x2e00509) fmt.Printf("Requesting frame extents for active window...\n") ewmh.RequestFrameExtents(X, active) activeDesk, _ := ewmh.WmDesktopGet(X, active) activeType, _ := ewmh.WmWindowTypeGet(X, active) fmt.Printf("Active window's desktop: %d\n", activeDesk) fmt.Printf("Active's types: %v\n", activeType) // fmt.Printf("Pager's types: %v\n", ewmh.WmWindowType(X, 0x180001e)) // fmt.Printf("Pager's state: %v\n", ewmh.WmState(X, 0x180001e)) // ewmh.WmStateReq(X, active, xgbutil.EwmhStateToggle, // "_NET_WM_STATE_HIDDEN") // ewmh.WmStateReqExtra(X, active, xgbutil.EwmhStateToggle, // "_NET_WM_STATE_MAXIMIZED_VERT", // "_NET_WM_STATE_MAXIMIZED_HORZ", 2) activeAllowed, _ := ewmh.WmAllowedActionsGet(X, active) fmt.Printf("Allowed actions on active: %v\n", activeAllowed) struts, err := ewmh.WmStrutGet(X, pager) if err != nil { fmt.Printf("Pager struts: %v\n", err) } else { fmt.Printf("Pager struts: %v\n", struts) } pstruts, err := ewmh.WmStrutPartialGet(X, pager) if err != nil { fmt.Printf("Pager struts partial: %v - %v\n", pstruts, err) } else { fmt.Printf("Pager struts partial: %v\n", pstruts.BottomStartX) } // fmt.Printf("Icon geometry for active: %v\n", // ewmh.WmIconGeometry(X, active)) icons, _ := ewmh.WmIconGet(X, active) fmt.Printf("Active window's (%x) icon data: (length: %v)\n", active, len(icons)) for _, icon := range icons { fmt.Printf("\t(%d, %d)", icon.Width, icon.Height) fmt.Printf(" :: %d == %d\n", icon.Width*icon.Height, len(icon.Data)) } // fmt.Printf("Now set them again...\n") // ewmh.WmIconSet(X, active, icons[:len(icons) - 1]) }
func ManageResizingWindows(X *xgbutil.XUtil) { var DRAG_DATA *ResizeDrag handleDragStart := func(X *xgbutil.XUtil, rx, ry, ex, ey int) (cont bool, cursor xproto.Cursor) { // get the clicked window win, err := wm.FindManagedWindowUnderMouse(X) if err != nil { log.Printf("ResizeStart: couldn't find window under mouse: %v\n", err) return false, 0 } // get coordinates inside the clicked window _, reply, err := wm.FindNextUnderMouse(X, win) if err != nil { log.Printf("ResizeStart: couldn't get coordinates of click inside win %v: %v\n", win, err) return false, 0 } // create an xwindow.Window so we can get a rectangle to find our bearings from xwin := xwindow.New(X, win) geom, err := xwin.DecorGeometry() if err != nil { log.Printf("ResizeStart: geometry error: %v\n", err) return false, 0 } // get what side of the rect our mouseclick was on x, y := int(reply.WinX), int(reply.WinY) dir := SideOfRectangle(geom, x, y) // get coordinate part for the edge. this is either X or Y. target_edge := EdgePos(geom, dir) log.Printf("ResizeStart: on window %v - %v. Direction/edge: %v/%v\n", win, geom, dir, target_edge) // find adjacent windows adjacent := list.New() // note that this is an intellegent request: the WM only gives us a list of visible, normal windows // we don't have to worry about moving hidden windows or something managed_windows, err := ewmh.ClientListGet(X) if err != nil { // we can safley ignore this error, because then we just fall back to resizing only this window log.Printf("ResizeStart: error getting EWMH client list: %v\n", err) } else { // select managed windows // always enough space // TODO: don't grossly overallocate for _, candidate_id := range managed_windows { // no need to run calculations for ourself! if candidate_id == win { continue } cand_window := xwindow.New(X, candidate_id) cand_geom, err := cand_window.DecorGeometry() if err != nil { log.Printf("ResizeStart: couldn't get geometry for ajacency candidate %v: %v\n", candidate_id, err) continue } cand_edge := EdgePos(cand_geom, dir.Opposite()) if abs(cand_edge-target_edge) <= AdjacencyEpsilon { // cool, edges are touching. // make sure this window isn't totally above or below the candidate // we do so by constructing a rect using the clicked window's edge // and the candidate's orthagonal dimension // if the rect overlaps, then this window is truly adjacent // // TODO: consider adding a mimumum overlap if dir == wm.Top || dir == wm.Bottom { // measuring X coords if EdgePos(cand_geom, wm.Right) < EdgePos(geom, wm.Left) { continue } if EdgePos(cand_geom, wm.Left) > EdgePos(geom, wm.Right) { continue } } else { if EdgePos(cand_geom, wm.Bottom) < EdgePos(geom, wm.Top) { continue } if EdgePos(cand_geom, wm.Top) > EdgePos(geom, wm.Bottom) { continue } } // if a window has made it to here, it is adgacent! // add it to the list log.Printf("ResizeStart: will resize adjacent window: %v - %v\n", candidate_id, cand_geom) adjacent.PushBack(cand_window) } } } // construct the drag data data := ResizeDrag{xwin, dir, adjacent, rx, ry} DRAG_DATA = &data // TODO: finish this // create an edge // find the adjacent windows // start the drag return true, 0 } handleResize := func(rx, ry int) { delta := rx - DRAG_DATA.LastX if DRAG_DATA.Direction == wm.Top || DRAG_DATA.Direction == wm.Bottom { delta = ry - DRAG_DATA.LastY } if DRAG_DATA.Direction == wm.Left || DRAG_DATA.Direction == wm.Top { delta = delta * -1 } target_geom, err := DRAG_DATA.Window.DecorGeometry() if err != nil { log.Printf("Geom retrieve err: %v\n", err) return } target_edge := EdgePos(target_geom, DRAG_DATA.Direction) // resize the target by the delta err = ResizeDirection(X, DRAG_DATA.Window, DRAG_DATA.Direction, delta) if err != nil { log.Printf("ResizeStep: can't resize target: %v\n", err) return } // calculate actual delta that occured, for resizing the adjacent windows // handles issues with window sizing hints on windows like terminals // making big differences for us target_geom_a, err := DRAG_DATA.Window.DecorGeometry() if err != nil { log.Printf("ResizeStep: Geom retrieve err: %v\n", err) return } target_edge_a := EdgePos(target_geom_a, DRAG_DATA.Direction) delta = target_edge_a - target_edge if DRAG_DATA.Direction == wm.Left || DRAG_DATA.Direction == wm.Top { delta = delta * -1 } // resize each adjacent window by the opposite for e := DRAG_DATA.Adjacent.Front(); e != nil; e = e.Next() { // extract window from the linked list adj_win := e.Value.(*xwindow.Window) adj_geom, err := adj_win.DecorGeometry() if err != nil { log.Printf("ResizeStep: can't query adjacent window %v geometry: %v", adj_win, err) } log.Printf("ResizeStep: resizing adjacent window %v - %v: edge/delta %v/%v\n", adj_win.Id, adj_geom, DRAG_DATA.Direction.Opposite(), -delta) // resize in the opposite direction, with the opposite delta // except the delta should be some actual delta calculated from our source window, // because issues with terminal windows happen err = ResizeDirection(X, adj_win, DRAG_DATA.Direction.Opposite(), -delta) // then to garuntee the edges touch... AdjoinEdge(DRAG_DATA.Window, adj_win, DRAG_DATA.Direction) if err != nil { log.Printf("ResizeStep: can't resize adjacent window %v: %v\n", adj_win, err) continue } } // save new coordinates DRAG_DATA.LastX = rx DRAG_DATA.LastY = ry } handleDragStep := func(X *xgbutil.XUtil, rx, ry, ex, ey int) { if DynamicDragResize { handleResize(rx, ry) } } handleDragEnd := func(X *xgbutil.XUtil, rx, ry, ex, ey int) { // only run on high enough deltas. Prevents windows from resizing when the user has gone "nah." // use the adjacency epsilon here too delta := abs(rx - DRAG_DATA.LastX) if DRAG_DATA.Direction == wm.Top || DRAG_DATA.Direction == wm.Bottom { delta = abs(ry - DRAG_DATA.LastY) } if delta > AdjacencyEpsilon { handleResize(rx, ry) } else { log.Printf("ResizeEnd: delta %v less than epsilon %v, skipping resize\n", delta, AdjacencyEpsilon) } DRAG_DATA = nil } // resizes the window by 1px vertically, then observes the actual change resizeBugHunt := func(X *xgbutil.XUtil, ev xevent.ButtonPressEvent) { // get xwindow from click clicked, err := wm.FindManagedWindowUnderMouse(X) if err != nil { log.Println(err) return } win := xwindow.New(X, clicked) names := []string{"PreDecor", "PostDecorPreMove", "PostDecor", "Pre", "Post"} geometries := make(map[string]xrect.Rect, 4) // take measurements pre_decor, err := win.DecorGeometry() if err != nil { log.Printf("Error fetching pre DecorGeom: %v\n", err) } geometries["PreDecor"] = pre_decor geo, err := win.Geometry() if err != nil { log.Printf("Error fetching pre Geom: %v\n", err) } geometries["Pre"] = geo // resize vertically by 1px log.Println("Resizing using window.Geometry() + 50, not DecorGeometry() + 1") //err = win.WMResize(geo.Width() + 50, geo.Height()) if err != nil { log.Println(err) } // wait to finish err = wm.PollFor(win, wm.GeometryDiffers(geo), wm.DecorDiffers(pre_decor)) if err != nil { log.Printf("Oops wjile waiting for resizing and things: %v\n", err) } post_decor_pre_move, _, err := wm.Geometries(win) if err != nil { log.Println(err) post_decor_pre_move = pre_decor } geometries["PostDecorPreMove"] = post_decor_pre_move // move zero pixels, then wait err = wm.Move(win, post_decor_pre_move.X(), post_decor_pre_move.Y()) if err != nil { log.Printf("error in wm.Move zero px: %v\n", err) } geo, err = win.DecorGeometry() if err != nil { log.Printf("Error fetching post DecorGeom: %v\n", err) } geometries["PostDecor"] = geo geo, err = win.Geometry() if err != nil { log.Printf("Error fetching post Geom: %v\n", err) } geometries["Post"] = geo for _, k := range names { log.Printf("%s: %v\n", k, geometries[k]) } // release X events // needed if the event binding is synchronous // see http://godoc.burntsushi.net/pkg/github.com/BurntSushi/xgbutil/mousebind/#hdr-When_to_use_a_synchronous_binding // xproto.AllowEvents(X.Conn(), xproto.AllowReplayPointer, 0) } // bind handler mousebind.Drag(X, X.RootWin(), X.RootWin(), KeyComboResize, true, handleDragStart, handleDragStep, handleDragEnd) mousebind.ButtonPressFun(resizeBugHunt).Connect(X, X.RootWin(), ui.KeyOption+"-Shift-Control-1", false, true) }