Example #1
0
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
			}
		}
	}
}
Example #2
0
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)
}
Example #3
0
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
	}
}
Example #4
0
// 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)
}
Example #5
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)
}
Example #6
0
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()
}
Example #7
0
// 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)
}
Example #8
0
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()
}