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
}
Beispiel #2
0
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))
}
Beispiel #3
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
			}
		}
	}
}
Beispiel #4
0
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
}
Beispiel #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)
}
Beispiel #6
0
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
}