func changeWorkspaceIfNeeded(xid xproto.Window) error { desktopNum, err := xprop.PropValNum(xprop.GetProperty(XU, xid, "_NET_WM_DESKTOP")) if err != nil { return fmt.Errorf("Get _NET_WM_DESKTOP failed: %s", err) } currentDesktop, err := ewmh.CurrentDesktopGet(XU) if err != nil { return fmt.Errorf("Get _NET_CURRENT_DESKTOP failed: %v", err) } if currentDesktop == desktopNum { return fmt.Errorf("No need to change workspace, the current desktop is already %v", currentDesktop) } timeStamp, err := ewmh.WmUserTimeGet(XU, xid) if err != nil { logger.Warningf("Get timestamp of 0x%x failed: %v", uint32(xid), err) } err = ewmh.ClientEvent(XU, XU.RootWin(), "_NET_CURRENT_DESKTOP", int(desktopNum), int(timeStamp)) if err != nil { return fmt.Errorf("Send ClientMessage Failed: %v", err) } return nil }
func (m *TrayManager) RequireManageTrayIcons() { mstype, err := xprop.Atm(TrayXU, "MANAGER") if err != nil { logger.Warning("Get MANAGER Failed") return } timeStamp, _ := ewmh.WmUserTimeGet(TrayXU, m.owner) cm, err := xevent.NewClientMessage( 32, TrayXU.RootWin(), mstype, int(timeStamp), int(_NET_SYSTEM_TRAY_S0), int(m.owner), ) if err != nil { logger.Warning("Send MANAGER Request failed:", err) return } // !!! ewmh.ClientEvent not use EventMaskStructureNotify. xevent.SendRootEvent(TrayXU, cm, uint32(xproto.EventMaskStructureNotify)) }
func (c *Client) handleProperty(name string) { switch name { case "_NET_WM_VISIBLE_NAME": fallthrough case "_NET_WM_NAME": fallthrough case "WM_NAME": c.refreshName() case "_NET_WM_ICON": c.refreshIcon() case "WM_HINTS": if hints, err := icccm.WmHintsGet(wm.X, c.Id()); err == nil { c.hints = hints c.refreshIcon() } case "WM_NORMAL_HINTS": if nhints, err := icccm.WmNormalHintsGet(wm.X, c.Id()); err == nil { c.nhints = nhints } case "WM_TRANSIENT_FOR": if trans, err := icccm.WmTransientForGet(wm.X, c.Id()); err == nil { if transCli := wm.FindManagedClient(trans); transCli != nil { c.transientFor = transCli.(*Client) } } case "_NET_WM_USER_TIME": if newTime, err := ewmh.WmUserTimeGet(wm.X, c.Id()); err == nil { c.time = xproto.Timestamp(newTime) } case "_NET_WM_STRUT_PARTIAL": c.maybeApplyStruts() case "_MOTIF_WM_HINTS": // This is a bit messed up. If a client is floating, we don't // really care what the decorations are, so we oblige blindly. // However, if we're tiling, then we don't want to mess with // the frames---but we also want to make sure that any states // the client might revert to have the proper frames. decor := c.shouldDecor() if _, ok := c.Layout().(layout.Floater); ok { if decor { c.FrameFull() } else { c.FrameNada() } } else { for k := range c.states { s := c.states[k] if decor { s.frame = c.frames.full } else { s.frame = c.frames.nada } c.states[k] = s } } } }
func (m *TrayManager) tryOwner() bool { // Make a check, the tray application MUST be 1. reply, err := m.getSelectionOwner() if err != nil { logger.Error(err) return false } if reply.Owner != 0 { logger.Warning("Another System tray application is running") return false } timeStamp, _ := ewmh.WmUserTimeGet(TrayXU, m.owner) err = xproto.SetSelectionOwnerChecked( TrayXU.Conn(), m.owner, _NET_SYSTEM_TRAY_S0, xproto.Timestamp(timeStamp), ).Check() if err != nil { logger.Warning("Set Selection Owner failed: ", err) return false } //owner the _NET_SYSTEM_TRAY_Sn logger.Info("Required _NET_SYSTEM_TRAY_S0 successful") m.RequireManageTrayIcons() xprop.ChangeProp32( TrayXU, m.owner, "_NET_SYSTEM_TRAY_VISUAL", "VISUALID", uint(TRAYMANAGER.visual), ) xprop.ChangeProp32( TrayXU, m.owner, "_NET_SYSTEM_TRAY_ORIENTAION", "CARDINAL", 0, ) reply, err = m.getSelectionOwner() if err != nil { logger.Warning(err) return false } return reply.Owner != 0 }
func (c *client) cbPropertyNotify() xevent.PropertyNotifyFun { // helper function to log property vals showVals := func(o, n interface{}) { logger.Lots.Printf("\tOld value: '%s', new value: '%s'", o, n) } f := func(X *xgbutil.XUtil, ev xevent.PropertyNotifyEvent) { name, err := xprop.AtomName(c.X, ev.Atom) if err != nil { logger.Warning.Printf("Could not get property atom name for '%s' "+ "because: %s.", ev, err) } logger.Lots.Printf("Updating property %s with state %v on window %s", name, ev.State, c) switch name { case "_NET_WM_VISIBLE_NAME": fallthrough case "_NET_WM_NAME": fallthrough case "WM_NAME": c.refreshName() case "_NET_WM_ICON": case "WM_HINTS": if hints, err := icccm.WmHintsGet(X, c.Id()); err == nil { c.hints = hints } case "WM_NORMAL_HINTS": if nhints, err := icccm.WmNormalHintsGet(X, c.Id()); err == nil { c.nhints = nhints } case "WM_TRANSIENT_FOR": if trans, err := icccm.WmTransientForGet(X, c.Id()); err == nil { if transCli := wingo.findManagedClient(trans); transCli != nil { c.transientFor = transCli } } case "_NET_WM_USER_TIME": if newTime, err := ewmh.WmUserTimeGet(X, c.Id()); err == nil { showVals(c.time, newTime) c.time = xproto.Timestamp(newTime) } case "_NET_WM_STRUT_PARTIAL": } } return xevent.PropertyNotifyFun(f) }
func (m *TrayManager) Unmanage() bool { reply, err := m.getSelectionOwner() if err != nil { logger.Warning("get selection owner failed:", err) return false } if reply.Owner != m.owner { logger.Warning("not selection owner") return false } m.destroyOwnerWindow() trayicons := m.TrayIcons for _, icon := range trayicons { m.removeTrayIcon(xproto.Window(icon)) } timeStamp, _ := ewmh.WmUserTimeGet(TrayXU, m.owner) return xproto.SetSelectionOwnerChecked( TrayXU.Conn(), 0, _NET_SYSTEM_TRAY_S0, xproto.Timestamp(timeStamp), ).Check() == nil }