Beispiel #1
0
func main() {
	X, err := xgb.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	// Get the window id of the root window.
	setup := xproto.Setup(X)
	root := setup.DefaultScreen(X).Root

	// Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW".
	aname := "_NET_ACTIVE_WINDOW"
	activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
		aname).Reply()
	if err != nil {
		log.Fatal(err)
	}

	// Get the atom id (i.e., intern an atom) of "_NET_WM_NAME".
	aname = "_NET_WM_NAME"
	nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
		aname).Reply()
	if err != nil {
		log.Fatal(err)
	}

	// Get the actual value of _NET_ACTIVE_WINDOW.
	// Note that 'reply.Value' is just a slice of bytes, so we use an
	// XGB helper function, 'Get32', to pull an unsigned 32-bit integer out
	// of the byte slice. We then convert it to an X resource id so it can
	// be used to get the name of the window in the next GetProperty request.
	reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
	if err != nil {
		log.Fatal(err)
	}
	windowId := xproto.Window(xgb.Get32(reply.Value))
	fmt.Printf("Active window id: %X\n", windowId)

	// Now get the value of _NET_WM_NAME for the active window.
	// Note that this time, we simply convert the resulting byte slice,
	// reply.Value, to a string.
	reply, err = xproto.GetProperty(X, false, windowId, nameAtom.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Active window name: %s\n", string(reply.Value))
}
Beispiel #2
0
func connect(c *xgb.Conn, s *xproto.ScreenInfo, rl_execute_atom xproto.Atom, args []string) {
	log.Println("Connecting with args:", args)

	tree, err := xproto.QueryTree(c, s.Root).Reply()
	if err != nil {
		log.Panic("QueryTree failed:", err)
	}

	// Broadcast a property request to every window
	results := make([]xproto.GetPropertyCookie, len(tree.Children))
	for ch, child := range tree.Children {
		results[ch] = xproto.GetProperty(c, false, child,
			rl_execute_atom, xproto.GetPropertyTypeAny, 0, 1024)
	}

	success := false
	// Get the responses, look for windows that can recieve our command
	for i, r := range results {
		reply, err := r.Reply()
		if err != nil {
			log.Panic("GetPropertyRequest failed:", err)
		}
		if reply.Format != 0 {
			data := []byte(strings.Join(args, "\x00"))
			err = xproto.ChangePropertyChecked(c, xproto.PropModeReplace, tree.Children[i],
				rl_execute_atom, xproto.AtomString, 8, uint32(len(data)), data).Check()
			log.Println(" .. sent")
			success = true
		}
	}
	if success != true {
		log.Println(" .. server not running? atom = ", rl_execute_atom)
	}
}
Beispiel #3
0
func (w *window) property(a xp.Atom) string {
	p, err := xp.GetProperty(xConn, false, w.xWin, a, xp.GetPropertyTypeAny, 0, 1<<32-1).Reply()
	if err != nil {
		log.Println(err)
	}
	if p == nil {
		return ""
	}
	return string(p.Value)
}
Beispiel #4
0
func (logger *WindowLogger) getCurWindowTitle() (name string, err error) {
	// Get the window id of the root window.
	setup := xproto.Setup(logger.X11Connection)
	root := setup.DefaultScreen(logger.X11Connection).Root

	// Get the atom id (i.e., intern an atom) of "_NET_ACTIVE_WINDOW".
	aname := "_NET_ACTIVE_WINDOW"
	activeAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)),
		aname).Reply()
	if err != nil {
		return "", err
	}

	// Get the atom id (i.e., intern an atom) of "_NET_WM_NAME".
	aname = "_NET_WM_NAME"
	nameAtom, err := xproto.InternAtom(logger.X11Connection, true, uint16(len(aname)),
		aname).Reply()
	if err != nil {
		return "", err
	}

	// Get the actual value of _NET_ACTIVE_WINDOW.
	// Note that 'reply.Value' is just a slice of bytes, so we use an
	// XGB helper function, 'Get32', to pull an unsigned 32-bit integer out
	// of the byte slice. We then convert it to an X resource id so it can
	// be used to get the name of the window in the next GetProperty request.
	reply, err := xproto.GetProperty(logger.X11Connection, false, root, activeAtom.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
	if err != nil {
		return "", err
	}
	windowId := xproto.Window(xgb.Get32(reply.Value))

	// Now get the value of _NET_WM_NAME for the active window.
	// Note that this time, we simply convert the resulting byte slice,
	// reply.Value, to a string.
	reply, err = xproto.GetProperty(logger.X11Connection, false, windowId, nameAtom.Atom,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
	if err != nil {
		return "", err
	}
	return string(reply.Value), nil
}
Beispiel #5
0
func start_server(c *xgb.Conn, s *xproto.ScreenInfo, rl_execute_atom xproto.Atom) {
	win, err := xproto.NewWindowId(c)
	if err != nil {
		panic(err)
	}

	// Make a window which can be communicated with
	err = xproto.CreateWindowChecked(c, s.RootDepth, win, s.Root, 0, 0, 1, 1, 0, 0, 0, 0, nil).Check()
	if err != nil {
		panic(err)
	}

	err = xproto.ChangePropertyChecked(c, xproto.PropModeReplace, win,
		rl_execute_atom, xproto.AtomString, 8, xproto.PropModeReplace,
		[]byte("\x00")).Check()
	if err != nil {
		panic(err)
	}
	err = xproto.ChangeWindowAttributesChecked(c, win, xproto.CwEventMask, []uint32{xproto.EventMaskPropertyChange}).Check()
	if err != nil {
		panic(err)
	}

	get_execute_value := func() string {
		response, err := xproto.GetProperty(c, false, win, rl_execute_atom,
			xproto.GetPropertyTypeAny, 0, 1024).Reply()
		if err != nil {
			panic(err)
		}
		result := string(response.Value)
		return result
	}

	log.Print("Ready and waiting..")
	// Event loop
	for {
		reply, err := c.WaitForEvent()
		if err != nil {
			log.Panic("Error in event loop:", err)
		}

		switch event := reply.(type) {
		case xproto.PropertyNotifyEvent:
			if event.Window == win && event.Atom == rl_execute_atom {
				values := strings.Split(get_execute_value(), "\x00")
				run(values)
			}
		}
	}
}
Beispiel #6
0
func (a *atomic) GetProp(w xproto.Window, s string) (*xproto.GetPropertyReply, error) {
	atomId, err := a.Atom(s)
	if err != nil {
		return nil, err
	}

	reply, err := xproto.GetProperty(a.c, false, w, atomId, xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()

	if err != nil {
		msg := fmt.Sprintf("Error retrieving property '%s' on window %x: %s", s, w, err)
		return nil, GetPropertyError(msg)
	}

	if reply.Format == 0 {
		msg := fmt.Sprintf("No such property '%s' on window %x", s, w)
		return nil, GetPropertyError(msg)
	}

	return reply, nil
}
Beispiel #7
0
// GetProperty abstracts the messiness of calling xgb.GetProperty.
func GetProperty(xu *xgbutil.XUtil, win xproto.Window, atom string) (
	*xproto.GetPropertyReply, error) {

	atomId, err := Atm(xu, atom)
	if err != nil {
		return nil, err
	}

	reply, err := xproto.GetProperty(xu.Conn(), false, win, atomId,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()

	if err != nil {
		return nil, fmt.Errorf("GetProperty: Error retrieving property '%s' "+
			"on window %x: %s", atom, win, err)
	}

	if reply.Format == 0 {
		return nil, fmt.Errorf("GetProperty: No such property '%s' on "+
			"window %x.", atom, win)
	}

	return reply, nil
}
Beispiel #8
0
// Listen ...
func Listen(fn func(e Event)) error {
	X, err := xgb.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	setup := xproto.Setup(X)
	root := setup.DefaultScreen(X).Root

	var prevWindowID xproto.Window
	var prevClasses []string

	for {
		<-time.After(msRefresh * time.Millisecond)

		// From one of the xgb examples.
		aname := "_NET_ACTIVE_WINDOW"
		activeAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
			aname).Reply()
		if err != nil {
			log.Println(err)
			continue
		}

		reply, err := xproto.GetProperty(X, false, root, activeAtom.Atom,
			xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
		if err != nil {
			log.Println(err)
			continue
		}

		windowID := xproto.Window(xgb.Get32(reply.Value))

		aname = "WM_CLASS"
		nameAtom, err := xproto.InternAtom(X, true, uint16(len(aname)),
			aname).Reply()
		if err != nil {
			log.Println(err)
			continue
		}

		reply, err = xproto.GetProperty(X, false, windowID, nameAtom.Atom,
			xproto.GetPropertyTypeAny, 0, (1<<32)-1).Reply()
		if err != nil {
			log.Println(err)
			continue
		}

		classes := stringSlice(reply.Value)

		// Check if active window has changed since last time.
		if windowID != prevWindowID {
			fn(Lost{
				WMClass: prevClasses,
			})
			fn(Gained{
				WMClass: classes,
			})
			prevWindowID = windowID
			prevClasses = classes
		}
	}
}
Beispiel #9
0
func manage(xWin xp.Window, mapRequest bool) {
	callFocus := false
	w := findWindow(func(w *window) bool { return w.xWin == xWin })
	if w == nil {
		wmDeleteWindow, wmTakeFocus := false, false
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMProtocols,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			for v := prop.Value; len(v) >= 4; v = v[4:] {
				switch xp.Atom(u32(v)) {
				case atomWMDeleteWindow:
					wmDeleteWindow = true
				case atomWMTakeFocus:
					wmTakeFocus = true
				}
			}
		}

		transientFor := (*window)(nil)
		if prop, err := xp.GetProperty(xConn, false, xWin, atomWMTransientFor,
			xp.GetPropertyTypeAny, 0, 64).Reply(); err != nil {
			log.Println(err)
		} else if prop != nil {
			if v := prop.Value; len(v) == 4 {
				transientForXWin := xp.Window(u32(v))
				transientFor = findWindow(func(w *window) bool {
					return w.xWin == transientForXWin
				})
			}
		}

		k := screens[0].workspace
		if p, err := xp.QueryPointer(xConn, rootXWin).Reply(); err != nil {
			log.Println(err)
		} else if p != nil {
			k = screenContaining(p.RootX, p.RootY).workspace
		}
		w = &window{
			transientFor: transientFor,
			xWin:         xWin,
			rect: xp.Rectangle{
				X:      offscreenXY,
				Y:      offscreenXY,
				Width:  1,
				Height: 1,
			},
			wmDeleteWindow: wmDeleteWindow,
			wmTakeFocus:    wmTakeFocus,
		}
		f := k.focusedFrame
		previous := k.dummyWindow.link[prev]
		if transientFor != nil {
			previous = transientFor
		} else if f.window != nil {
			previous = f.window
		}
		w.link[next] = previous.link[next]
		w.link[prev] = previous
		w.link[next].link[prev] = w
		w.link[prev].link[next] = w

		if transientFor != nil && transientFor.frame != nil {
			f = transientFor.frame
			f.window, transientFor.frame = nil, nil
		} else if f.window != nil {
			f = k.mainFrame.firstEmptyFrame()
		}
		if f != nil {
			f.window, w.frame = w, f
			callFocus = f == k.focusedFrame
		} else {
			pulseChan <- time.Now()
		}

		check(xp.ChangeWindowAttributesChecked(xConn, xWin, xp.CwEventMask,
			[]uint32{xp.EventMaskEnterWindow | xp.EventMaskStructureNotify},
		))
		w.configure()
		if transientFor != nil {
			transientFor.hasTransientFor = true
			transientFor.configure()
		}
	}
	if mapRequest {
		check(xp.MapWindowChecked(xConn, xWin))
	}
	if callFocus {
		focus(w)
	}
	makeLists()
	pulseChan <- time.Now()
}