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 main() { X, _ := xgbutil.NewConn() active, err := ewmh.ActiveWindowGet(X) wmName, err := icccm.WmNameGet(X, active) showTest("WM_NAME get", wmName, err) err = icccm.WmNameSet(X, active, "hooblah") wmName, _ = icccm.WmNameGet(X, active) showTest("WM_NAME set", wmName, err) wmNormHints, err := icccm.WmNormalHintsGet(X, active) showTest("WM_NORMAL_HINTS get", wmNormHints, err) wmNormHints.Width += 5 err = icccm.WmNormalHintsSet(X, active, wmNormHints) showTest("WM_NORMAL_HINTS set", wmNormHints, err) wmHints, err := icccm.WmHintsGet(X, active) showTest("WM_HINTS get", wmHints, err) wmHints.InitialState = icccm.StateNormal err = icccm.WmHintsSet(X, active, wmHints) showTest("WM_NORMAL_HINTS set", wmHints, err) wmClass, err := icccm.WmClassGet(X, active) showTest("WM_CLASS get", wmClass, err) wmClass.Instance = "hoopdy hoop" err = icccm.WmClassSet(X, active, wmClass) showTest("WM_CLASS set", wmClass, err) wmTrans, err := icccm.WmTransientForGet(X, active) showTest("WM_TRANSIENT_FOR get", wmTrans, err) wmProts, err := icccm.WmProtocolsGet(X, active) showTest("WM_PROTOCOLS get", wmProts, err) wmClient, err := icccm.WmClientMachineGet(X, active) showTest("WM_CLIENT_MACHINE get", wmClient, err) err = icccm.WmClientMachineSet(X, active, "Leopard") wmClient, _ = icccm.WmClientMachineGet(X, active) showTest("WM_CLIENT_MACHINE set", wmClient, err) wmState, err := icccm.WmStateGet(X, active) showTest("WM_STATE get", wmState, err) wmState.Icon = xproto.Window(8365538) wmState.State = icccm.StateNormal err = icccm.WmStateSet(X, active, wmState) wmState, _ = icccm.WmStateGet(X, active) showTest("WM_STATE set", wmState, err) }
func (c *client) fetchXProperties() { var err error c.hints, err = icccm.WmHintsGet(c.X, c.Id()) if err != nil { logger.Warning.Println(err) logger.Message.Printf("Using reasonable defaults for WM_HINTS for %X", c.Id()) c.hints = &icccm.Hints{ Flags: icccm.HintInput | icccm.HintState, Input: 1, InitialState: icccm.StateNormal, } } c.nhints, err = icccm.WmNormalHintsGet(c.X, c.Id()) if err != nil { logger.Warning.Println(err) logger.Message.Printf("Using reasonable defaults for WM_NORMAL_HINTS "+ "for %X", c.Id()) c.nhints = &icccm.NormalHints{} } c.protocols, err = icccm.WmProtocolsGet(c.X, c.Id()) if err != nil { logger.Warning.Printf( "Window %X does not have WM_PROTOCOLS set.", c.Id()) } c.winTypes, err = ewmh.WmWindowTypeGet(c.X, c.Id()) if err != nil { logger.Warning.Printf("Could not find window type for window %X, "+ "using 'normal'.", c.Id()) c.winTypes = []string{"_NET_WM_WINDOW_TYPE_NORMAL"} } trans, _ := icccm.WmTransientForGet(c.X, c.Id()) if trans == 0 { for _, c2 := range wingo.clients { if c2.transient(c) { c.transientFor = c2 break } } } else if transCli := wingo.findManagedClient(trans); transCli != nil { c.transientFor = transCli } }
// findIconIcccm helps FindIcon by trying to return an icccm-style icon. func findIconIcccm(X *xgbutil.XUtil, wid xproto.Window) (*Image, error) { hints, err := icccm.WmHintsGet(X, wid) if err != nil { return nil, err } // Only continue if the WM_HINTS flags say an icon is specified and // if at least one of icon pixmap or icon mask is non-zero. if hints.Flags&icccm.HintIconPixmap == 0 || (hints.IconPixmap == 0 && hints.IconMask == 0) { return nil, fmt.Errorf("No icon found in WM_HINTS.") } return NewIcccmIcon(X, hints.IconPixmap, hints.IconMask) }
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 showIcon(X *xgbutil.XUtil, wid xproto.Window, name string) { hints, err := icccm.WmHintsGet(X, wid) if err != nil { log.Fatal(err) } ximg, err := xgraphics.NewIcccmIcon(X, hints.IconPixmap, hints.IconMask) if err != nil { log.Fatal(err) } err = ximg.SavePng(fmt.Sprintf("%s.png", name)) if err != nil { log.Fatal(err) } ximg.XShow() }
// WMTakeFocus will do all the necessary setup to support the WM_TAKE_FOCUS // protocol using the "LocallyActive" input model described in Section 4.1.7 // of the ICCCM. Namely, listening to ClientMessage events and running the // callback function provided when a WM_TAKE_FOCUS ClientMessage has been // received. // // Typically, the callback function should include a call to SetInputFocus // with the "Parent" InputFocus type, the sub-window id of the window that // should have focus, and the 'tstamp' timestamp. func (w *Window) WMTakeFocus(cb func(w *Window, tstamp xproto.Timestamp)) { // Make sure the Input flag is set to true in WM_HINTS. We first // must retrieve the current WM_HINTS, so we don't overwrite the flags. curFlags := 0 if hints, err := icccm.WmHintsGet(w.X, w.Id); err == nil { curFlags = hints.Flags } icccm.WmHintsSet(w.X, w.Id, &icccm.Hints{ Flags: curFlags | icccm.HintInput, Input: 1, }) // Get the current protocols so we don't overwrite anything. prots, _ := icccm.WmProtocolsGet(w.X, w.Id) // If WM_TAKE_FOCUS isn't here, add it. Otherwise, move on. wmfocus := false for _, prot := range prots { if prot == "WM_TAKE_FOCUS" { wmfocus = true break } } if !wmfocus { icccm.WmProtocolsSet(w.X, w.Id, append(prots, "WM_TAKE_FOCUS")) } // Attach a ClientMessage event handler. It will determine whether the // ClientMessage is a 'focus' request, and if so, run the callback 'cb' // provided. xevent.ClientMessageFun( func(X *xgbutil.XUtil, ev xevent.ClientMessageEvent) { if icccm.IsFocusProtocol(X, ev) { cb(w, xproto.Timestamp(ev.Data.Data32[1])) } }).Connect(w.X, w.Id) }
func (c *Client) fetchXProperties() { var err error c.hints, err = icccm.WmHintsGet(wm.X, c.Id()) if err != nil { logger.Warning.Println(err) logger.Message.Printf("Using reasonable defaults for WM_HINTS for %X", c.Id()) c.hints = &icccm.Hints{ Flags: icccm.HintInput | icccm.HintState, Input: 1, InitialState: icccm.StateNormal, } } c.nhints, err = icccm.WmNormalHintsGet(wm.X, c.Id()) if err != nil { logger.Warning.Println(err) logger.Message.Printf("Using reasonable defaults for WM_NORMAL_HINTS "+ "for %X", c.Id()) c.nhints = &icccm.NormalHints{} } c.protocols, err = icccm.WmProtocolsGet(wm.X, c.Id()) if err != nil { logger.Warning.Printf( "Window %X does not have WM_PROTOCOLS set.", c.Id()) } c.winTypes, err = ewmh.WmWindowTypeGet(wm.X, c.Id()) if err != nil { logger.Warning.Printf("Could not find window type for window %X, "+ "using 'normal'.", c.Id()) c.winTypes = []string{"_NET_WM_WINDOW_TYPE_NORMAL"} } c.winStates, err = ewmh.WmStateGet(wm.X, c.Id()) if err != nil { c.winStates = []string{} ewmh.WmStateSet(wm.X, c.Id(), c.winStates) } c.class, err = icccm.WmClassGet(wm.X, c.Id()) if err != nil { logger.Warning.Printf("Could not find window class for window %X: %s", c.Id(), err) c.class = &icccm.WmClass{ Instance: "", Class: "", } } trans, _ := icccm.WmTransientForGet(wm.X, c.Id()) if trans == 0 { for _, c2_ := range wm.Clients { c2 := c2_.(*Client) if c2.transient(c) { c.transientFor = c2 break } } } else if transCli := wm.FindManagedClient(trans); transCli != nil { c.transientFor = transCli.(*Client) } tmp, err := xprop.PropValNum( xprop.GetProperty(wm.X, c.Id(), "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED")) if err == nil { c.gtkMaximizeNada = (tmp == 1) } else { c.gtkMaximizeNada = false } c.setShaped() }