Пример #1
0
// A convenience function to grab the KeyboardMapping and ModifierMapping
// from X. We need to do this on startup (see Initialize) and whenever we
// get a MappingNotify event.
func MapsGet(xu *xgbutil.XUtil) (*xproto.GetKeyboardMappingReply,
	*xproto.GetModifierMappingReply) {

	min, max := minMaxKeycodeGet(xu)
	queryKeymap, _ := xproto.GetKeyboardMapping(xu.Conn(), nil,
		min, byte(max-min+1))
	newKeymap, keyErr := queryKeymap.Reply()
	queryModmap, _ := xproto.GetModifierMapping(xu.Conn(), nil)
	newModmap, modErr := queryModmap.Reply()

	// If there are errors, we really need to panic. We just can't do
	// any key binding without a mapping from the server.
	if keyErr != nil {
		panic(fmt.Sprintf("COULD NOT GET KEYBOARD MAPPING: %v\n"+
			"THIS IS AN UNRECOVERABLE ERROR.\n",
			keyErr))
	}
	if modErr != nil {
		panic(fmt.Sprintf("COULD NOT GET MODIFIER MAPPING: %v\n"+
			"THIS IS AN UNRECOVERABLE ERROR.\n",
			keyErr))
	}

	return newKeymap, newModmap
}
Пример #2
0
// GrabKeyboard grabs the entire keyboard.
// Returns whether GrabStatus is successful and an error if one is reported by
// XGB. It is possible to not get an error and the grab to be unsuccessful.
// The purpose of 'win' is that after a grab is successful, ALL Key*Events will
// be sent to that window. Make sure you have a callback attached :-)
func GrabKeyboard(xu *xgbutil.XUtil, win xproto.Window) error {
	query, _ := xproto.GrabKeyboard(xu.Conn(), nil, false, win, 0,
		xproto.GrabModeAsync, xproto.GrabModeAsync)
	reply, err := query.Reply()
	if err != nil {
		return fmt.Errorf("GrabKeyboard: Error grabbing keyboard on "+
			"window '%x': %s", win, err)
	}

	switch reply.Status {
	case xproto.GrabStatusSuccess:
		// all is well
	case xproto.GrabStatusAlreadyGrabbed:
		return fmt.Errorf("GrabKeyboard: Could not grab keyboard. " +
			"Status: AlreadyGrabbed.")
	case xproto.GrabStatusInvalidTime:
		return fmt.Errorf("GrabKeyboard: Could not grab keyboard. " +
			"Status: InvalidTime.")
	case xproto.GrabStatusNotViewable:
		return fmt.Errorf("GrabKeyboard: Could not grab keyboard. " +
			"Status: NotViewable.")
	case xproto.GrabStatusFrozen:
		return fmt.Errorf("GrabKeyboard: Could not grab keyboard. " +
			"Status: Frozen.")
	}
	return nil
}
Пример #3
0
// PhyiscalHeads returns the list of heads in a physical ordering.
// Namely, left to right then top to bottom. (Defined by (X, Y).)
// Xinerama must have been initialized, otherwise the xinerama.QueryScreens
// request will panic.
// PhysicalHeads also checks to make sure each rectangle has a unique (x, y)
// tuple, so as not to return the geometry of cloned displays.
// (At present moment, xgbutil initializes Xinerama automatically during
// initial connection.)
func PhysicalHeads(xu *xgbutil.XUtil) (Heads, error) {
	query, _ := xinerama.QueryScreens(xu.Conn(), nil)
	xinfo, err := query.Reply()
	if err != nil {
		return nil, err
	}

	hds := make(Heads, 0)
	for _, info := range xinfo.ScreenInfo {
		head := xrect.New(int(info.XOrg), int(info.YOrg),
			int(info.Width), int(info.Height))

		// Maybe Xinerama is enabled, but we have cloned displays...
		unique := true
		for _, h := range hds {
			if h.X() == head.X() && h.Y() == head.Y() {
				unique = false
				break
			}
		}

		if unique {
			hds = append(hds, head)
		}
	}

	sort.Sort(hds)
	return hds, nil
}
Пример #4
0
// Ungrab undoes Grab. It will handle all combinations od modifiers found
// in xevent.IgnoreMods.
func Ungrab(xu *xgbutil.XUtil, win xproto.Window,
	mods uint16, key xproto.Keycode) {

	for _, m := range xevent.IgnoreMods {
		query, _ := xproto.UngrabKeyChecked(xu.Conn(), nil, key, win, mods|m)
		query.Check()
	}
}
Пример #5
0
// Ungrab undoes Grab. It will handle all combinations of modifiers found
// in xevent.IgnoreMods.
func Ungrab(xu *xgbutil.XUtil, win xproto.Window, mods uint16,
	button xproto.Button) {

	for _, m := range xevent.IgnoreMods {
		query, _ := xproto.UngrabButtonChecked(xu.Conn(), nil, byte(button), win, mods|m)
		query.Check()
	}
}
Пример #6
0
// Grab grabs a key with mods on a particular window.
// This will also grab all combinations of modifiers found in xevent.IgnoreMods.
func Grab(xu *xgbutil.XUtil, win xproto.Window,
	mods uint16, key xproto.Keycode) {

	for _, m := range xevent.IgnoreMods {
		xproto.GrabKey(xu.Conn(), nil, true, win, mods|m, key,
			xproto.GrabModeAsync, xproto.GrabModeAsync)
	}
}
Пример #7
0
// Grab grabs a button with mods on a particular window.
// Will also grab all combinations of modifiers found in xevent.IgnoreMods
// If 'sync' is True, then no further events can be processed until the
// grabbing client allows them to be. (Which is done via AllowEvents. Thus,
// if sync is True, you *must* make some call to AllowEvents at some
// point, or else your client will lock.)
func Grab(xu *xgbutil.XUtil, win xproto.Window, mods uint16,
	button xproto.Button, sync bool) {

	var pSync byte = xproto.GrabModeAsync
	if sync {
		pSync = xproto.GrabModeSync
	}

	for _, m := range xevent.IgnoreMods {
		xproto.GrabButton(xu.Conn(), nil, true, win, pointerMasks,
			pSync, xproto.GrabModeAsync, 0, 0, byte(button), mods|m)
	}
}
Пример #8
0
// GrabChecked Grabs a key with mods on a particular window.
// This is the same as Grab, except that it issue a checked request.
// Which means that an error could be returned and handled on the spot.
// (Checked requests are slower than unchecked requests.)
// This will also grab all combinations of modifiers found in xevent.IgnoreMods.
func GrabChecked(xu *xgbutil.XUtil, win xproto.Window,
	mods uint16, key xproto.Keycode) error {

	var err error
	for _, m := range xevent.IgnoreMods {
		query, _ := xproto.GrabKeyChecked(xu.Conn(), nil, true, win,
			mods|m, key, xproto.GrabModeAsync, xproto.GrabModeAsync)
		err = query.Check()
		if err != nil {
			return err
		}
	}
	return nil
}
Пример #9
0
// GrabPointer grabs the entire pointer.
// Returns whether GrabStatus is successful and an error if one is reported by
// XGB. It is possible to not get an error and the grab to be unsuccessful.
// The purpose of 'win' is that after a grab is successful, ALL Button*Events
// will be sent to that window. Make sure you have a callback attached :-)
func GrabPointer(xu *xgbutil.XUtil, win xproto.Window, confine xproto.Window,
	cursor xproto.Cursor) (bool, error) {

	query, _ := xproto.GrabPointer(xu.Conn(), nil, false, win,
		pointerMasks, xproto.GrabModeAsync, xproto.GrabModeAsync,
		confine, cursor, 0)
	reply, err := query.Reply()
	if err != nil {
		return false, fmt.Errorf("GrabPointer: Error grabbing pointer on "+
			"window '%x': %s", win, err)
	}

	return reply.Status == xproto.GrabStatusSuccess, nil
}
Пример #10
0
// ChangeProperty abstracts the semi-nastiness of xgb.ChangeProperty.
func ChangeProp(xu *xgbutil.XUtil, win xproto.Window, format byte, prop string,
	typ string, data []byte) error {

	propAtom, err := Atm(xu, prop)
	if err != nil {
		return err
	}

	typAtom, err := Atm(xu, typ)
	if err != nil {
		return err
	}

	query, _ := xproto.ChangePropertyChecked(xu.Conn(), nil,
		xproto.PropModeReplace, win, propAtom, typAtom, format,
		uint32(len(data)/(int(format)/8)), data)
	return query.Check()
}
Пример #11
0
// AtomName fetches a string representation of an ATOM given its integer id.
func AtomName(xu *xgbutil.XUtil, aid xproto.Atom) (string, error) {
	// Check the cache first
	if atomName, ok := atomNameGet(xu, aid); ok {
		return string(atomName), nil
	}

	query, _ := xproto.GetAtomName(xu.Conn(), nil, aid)
	reply, err := query.Reply()
	if err != nil {
		return "", fmt.Errorf("AtomName: Error fetching name for ATOM "+
			"id '%d': %s", aid, err)
	}

	// If we're here, it means we didn't have ths ATOM id cached. So cache it.
	atomName := string(reply.Name)
	cacheAtom(xu, atomName, aid)

	return atomName, nil
}
Пример #12
0
// GrabChecked grabs a button with mods on a particular window. It does the
// same thing as Grab, but issues a checked request and returns an error
// on failure.
// Will also grab all combinations of modifiers found in xevent.IgnoreMods
// If 'sync' is True, then no further events can be processed until the
// grabbing client allows them to be. (Which is done via AllowEvents. Thus,
// if sync is True, you *must* make some call to AllowEvents at some
// point, or else your client will lock.)
func GrabChecked(xu *xgbutil.XUtil, win xproto.Window, mods uint16,
	button xproto.Button, sync bool) error {

	var pSync byte = xproto.GrabModeAsync
	if sync {
		pSync = xproto.GrabModeSync
	}

	var err error
	for _, m := range xevent.IgnoreMods {
		query, _ := xproto.GrabButtonChecked(xu.Conn(), nil, true, win,
			pointerMasks, pSync, xproto.GrabModeAsync, 0, 0,
			byte(button), mods|m)
		err = query.Check()
		if err != nil {
			return err
		}
	}
	return nil
}
Пример #13
0
// Atom interns an atom and panics if there is any error.
func Atom(xu *xgbutil.XUtil, name string,
	onlyIfExists bool) (xproto.Atom, error) {

	// Check the cache first
	if aid, ok := atomGet(xu, name); ok {
		return aid, nil
	}

	query, _ := xproto.InternAtom(xu.Conn(), nil, onlyIfExists,
		uint16(len(name)), name)
	reply, err := query.Reply()
	if err != nil {
		return 0, fmt.Errorf("Atom: Error interning atom '%s': %s", name, err)
	}

	// If we're here, it means we didn't have this atom cached. So cache it!
	cacheAtom(xu, name, reply.Atom)

	return reply.Atom, nil
}
Пример #14
0
// Read reads one or more events and queues them in XUtil.
// If 'block' is True, then call 'WaitForEvent' before sucking up
// all events that have been queued by XGB.
func Read(xu *xgbutil.XUtil, block bool) {
	if block {
		ev, err := xu.Conn().WaitForEvent()
		if ev == nil && err == nil {
			xgbutil.Logger.Fatal("BUG: Could not read an event or an error.")
		}
		Enqueue(xu, ev, err)
	}

	// Clean up anything that's in the queue
	for {
		ev, err := xu.Conn().PollForEvent()

		// No events left...
		if ev == nil && err == nil {
			break
		}

		// We're good, queue it up
		Enqueue(xu, ev, err)
	}
}
Пример #15
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
	}

	query, _ := xproto.GetProperty(xu.Conn(), nil, false, win, atomId,
		xproto.GetPropertyTypeAny, 0, (1<<32)-1)
	reply, err := query.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
}
Пример #16
0
// UngrabKeyboard undoes GrabKeyboard.
func UngrabKeyboard(xu *xgbutil.XUtil) {
	xproto.UngrabKeyboard(xu.Conn(), nil, 0)
}
Пример #17
0
// SendRootEvent takes a type implementing the xgb.Event interface, converts it
// to raw X bytes, and sends it to the root window using the SendEvent request.
func SendRootEvent(xu *xgbutil.XUtil, ev xgb.Event, evMask uint32) error {
	query, _ := xproto.SendEventChecked(xu.Conn(), nil, false, xu.RootWin(),
		evMask, string(ev.Bytes()))
	return query.Check()
}
Пример #18
0
// UngrabPointer undoes GrabPointer.
func UngrabPointer(xu *xgbutil.XUtil) {
	xproto.UngrabPointer(xu.Conn(), nil, 0)
}
Пример #19
0
// ReplayPointer is a quick alias to AllowEvents with 'ReplayPointer' mode.
func ReplayPointer(xu *xgbutil.XUtil) {
	xproto.AllowEvents(xu.Conn(), nil, xproto.AllowReplayPointer, 0)
}