// 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 {
		xproto.UngrabButtonChecked(xu.Conn(), byte(button), win, mods|m).Check()
	}
}
Example #2
0
File: shape.go Project: justjake/j3
// compose a number of rectabgles into a window shape
func ComposeShape(X *xgbutil.XUtil, dst xproto.Window, rects []xrect.Rect) (err error) {

	combine_bounds := make([]shape.CombineCookie, len(rects))
	combine_clip := make([]shape.CombineCookie, len(rects))

	var operation shape.Op

	for i, rect := range rects {
		// make rectangular window of correct goemetry
		win, err := xwindow.Generate(X)
		if err != nil {
			log.Fatalf("ComposeShape: Error creating rectange %v window.", rect)
			return err
		}
		win.Create(X.RootWin(), rect.X(), rect.Y(), rect.Width(), rect.Height(), xproto.CwBackPixel, 0xffffff)

		// choose operation. on the first one, we want to set the shape.
		if i == 0 {
			operation = shape.SoSet
		} else {
			operation = shape.SoUnion
		}

		// combine window request
		x, y := int16(rect.X()), int16(rect.Y())

		combine_kind := shape.Kind(shape.SkBounding)
		combine_bounds[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id)
		combine_kind = shape.Kind(shape.SkClip)
		combine_clip[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id)
	}
	return nil
}
Example #3
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 {
		xproto.UngrabKeyChecked(xu.Conn(), key, win, mods|m).Check()
	}
}
Example #4
0
func newParent(X *xgbutil.XUtil, cid xproto.Window) (*Parent, error) {
	parent, err := xwindow.Generate(X)
	if err != nil {
		logger.Error.Printf("Could not create a parent window for client "+
			"with id '%d' because: %s", cid, err)
		logger.Error.Fatalf("In a state where no new windows can be created. " +
			"Unfortunately, we must exit.")
	}

	err = parent.CreateChecked(X.RootWin(), 0, 0, 1, 1,
		xproto.CwEventMask,
		xproto.EventMaskSubstructureRedirect|
			xproto.EventMaskButtonPress|xproto.EventMaskButtonRelease)
	if err != nil {
		return nil, err
	}

	err = xproto.ReparentWindowChecked(X.Conn(),
		cid, parent.Id, 0, 0).Check()
	if err != nil {
		return nil, err
	}

	return &Parent{parent}, nil
}
Example #5
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 {
	reply, err := xproto.GrabKeyboard(xu.Conn(), false, win, 0,
		xproto.GrabModeAsync, xproto.GrabModeAsync).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
}
Example #6
0
// NewDrawable converts an X drawable into a xgraphics.Image.
// This is used in NewIcccmIcon.
func NewDrawable(X *xgbutil.XUtil, did xproto.Drawable) (*Image, error) {
	// Get the geometry of the pixmap for use in the GetImage request.
	pgeom, err := xwindow.RawGeometry(X, xproto.Drawable(did))
	if err != nil {
		return nil, err
	}

	// Get the image data for each pixmap.
	pixmapData, err := xproto.GetImage(X.Conn(), xproto.ImageFormatZPixmap,
		did,
		0, 0, uint16(pgeom.Width()), uint16(pgeom.Height()),
		(1<<32)-1).Reply()
	if err != nil {
		return nil, err
	}

	// Now create the xgraphics.Image and populate it with data from
	// pixmapData and maskData.
	ximg := New(X, image.Rect(0, 0, pgeom.Width(), pgeom.Height()))

	// We'll try to be a little flexible with the image format returned,
	// but not completely flexible.
	err = readDrawableData(X, ximg, did, pixmapData,
		pgeom.Width(), pgeom.Height())
	if err != nil {
		return nil, err
	}

	return ximg, nil
}
Example #7
0
// CreateCursorExtra features all available parameters to creating a cursor.
// It will return an error if there is a problem with any of the requests
// made to create the cursor.
// (This implies each request is a checked request. The performance loss is
// probably acceptable since cursors should be created once and reused.)
func CreateCursorExtra(xu *xgbutil.XUtil, cursor, foreRed, foreGreen,
	foreBlue, backRed, backGreen, backBlue uint16) (xproto.Cursor, error) {

	fontId, err := xproto.NewFontId(xu.Conn())
	if err != nil {
		return 0, err
	}

	cursorId, err := xproto.NewCursorId(xu.Conn())
	if err != nil {
		return 0, err
	}

	err = xproto.OpenFontChecked(xu.Conn(), fontId,
		uint16(len("cursor")), "cursor").Check()
	if err != nil {
		return 0, err
	}

	err = xproto.CreateGlyphCursorChecked(xu.Conn(), cursorId, fontId, fontId,
		cursor, cursor+1,
		foreRed, foreGreen, foreBlue,
		backRed, backGreen, backBlue).Check()
	if err != nil {
		return 0, err
	}

	err = xproto.CloseFontChecked(xu.Conn(), fontId).Check()
	if err != nil {
		return 0, err
	}

	return cursorId, nil
}
Example #8
0
// Generate is just like New, but generates a new X resource id for you.
// Geom is initialized to (0, 0) 1x1.
// It is possible for id generation to return an error, in which case, an
// error is returned here.
func Generate(xu *xgbutil.XUtil) (*Window, error) {
	wid, err := xproto.NewWindowId(xu.Conn())
	if err != nil {
		return nil, err
	}
	return New(xu, wid), nil
}
// 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) {
	xinfo, err := xinerama.QueryScreens(xu.Conn()).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
}
Example #10
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(), true, win, mods|m, key,
			xproto.GrabModeAsync, xproto.GrabModeAsync)
	}
}
Example #11
0
// RawGeometry isn't smart. It just queries the window given for geometry.
func RawGeometry(xu *xgbutil.XUtil, win xproto.Drawable) (xrect.Rect, error) {
	xgeom, err := xproto.GetGeometry(xu.Conn(), win).Reply()
	if err != nil {
		return nil, err
	}
	return xrect.New(int(xgeom.X), int(xgeom.Y),
		int(xgeom.Width), int(xgeom.Height)), nil
}
Example #12
0
func clientMessage(X *xgbutil.XUtil, event xgb.Event) {
	ev := event.(xproto.ClientMessageEvent)
	cookie := xproto.GetAtomName(X.Conn(), ev.Type)
	reply, _ := cookie.Reply()
	log.WithFields(log.Fields{
		"name": reply.Name,
		"data": ev.Data,
	}).Info("client Message:", ev)
}
Example #13
0
File: mouse.go Project: justjake/j3
// translate an X, Y value from one window to the euclidean space of another. Useful for translating
// the arbitrary position of some window's (0,0) point into root window space
func TranslateCoordinatesSync(X *xgbutil.XUtil, src, dest xproto.Window, x, y int) (dest_x, dest_y int, err error) {
	Xx, Xy := int16(x), int16(y)
	cookie := xproto.TranslateCoordinates(X.Conn(), src, dest, Xx, Xy)
	reply, err := cookie.Reply()
	if err != nil {
		return 0, 0, err
	}
	dest_x, dest_y = int(reply.DstX), int(reply.DstY)
	return
}
Example #14
0
File: mouse.go Project: justjake/j3
// wrapper around xproto.QueryPointer that performs a simple synchronous query
func FindNextUnderMouse(X *xgbutil.XUtil, parent xproto.Window) (xproto.Window, *xproto.QueryPointerReply, error) {
	// start query pointer request
	cookie := xproto.QueryPointer(X.Conn(), parent)

	// block and get reply for client
	reply, err := cookie.Reply()
	if err != nil {
		return 0, nil, err
	}
	return reply.Child, reply, nil
}
Example #15
0
// currentTime forcefully causes a PropertyNotify event to fire on the root
// window, then scans the event queue and picks up the time.
//
// It is NOT SAFE to call this function in a place other than Wingo's
// initialization. Namely, this function subverts xevent's queue and reads
// events directly from X.
func currentTime(X *xgbutil.XUtil) (xproto.Timestamp, error) {
	wmClassAtom, err := xprop.Atm(X, "WM_CLASS")
	if err != nil {
		return 0, err
	}

	stringAtom, err := xprop.Atm(X, "STRING")
	if err != nil {
		return 0, err
	}

	// Make sure we're listening to PropertyChange events on the root window.
	err = xwindow.New(X, X.RootWin()).Listen(xproto.EventMaskPropertyChange)
	if err != nil {
		return 0, fmt.Errorf(
			"Could not listen to Root window events (PropertyChange): %s", err)
	}

	// Do a zero-length append on a property as suggested by ICCCM 2.1.
	err = xproto.ChangePropertyChecked(
		X.Conn(), xproto.PropModeAppend, X.RootWin(),
		wmClassAtom, stringAtom, 8, 0, nil).Check()
	if err != nil {
		return 0, err
	}

	// Now look for the PropertyNotify generated by that zero-length append
	// and return the timestamp attached to that event.
	// Note that we do this outside of xgbutil/xevent, since ownership
	// is literally the first thing we do after connecting to X.
	// (i.e., we don't have our event handling system initialized yet.)
	timeout := time.After(3 * time.Second)
	for {
		select {
		case <-timeout:
			return 0, fmt.Errorf(
				"Expected a PropertyNotify event to get a valid timestamp, " +
					"but never received one.")
		default:
			ev, err := X.Conn().PollForEvent()
			if err != nil {
				continue
			}
			if propNotify, ok := ev.(xproto.PropertyNotifyEvent); ok {
				X.TimeSet(propNotify.Time) // why not?
				return propNotify.Time, nil
			}
			time.Sleep(100 * time.Millisecond)
		}
	}
	panic("unreachable")
}
// 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) {

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

	return reply.Status == xproto.GrabStatusSuccess, nil
}
// 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(), true, win, pointerMasks, pSync,
			xproto.GrabModeAsync, 0, 0, byte(button), mods|m)
	}
}
Example #18
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 {
		err = xproto.GrabKeyChecked(xu.Conn(), true, win, mods|m, key,
			xproto.GrabModeAsync, xproto.GrabModeAsync).Check()
		if err != nil {
			return err
		}
	}
	return nil
}
Example #19
0
func GetOutputs(X *xgbutil.XUtil) (outputs []*randr.GetOutputInfoReply) {
	resources, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply()
	if err != nil {
		return nil
	}
	for _, output := range resources.Outputs {
		oinfo, err := randr.GetOutputInfo(X.Conn(), output, 0).Reply()
		if err != nil {
			return nil
		}
		outputs = append(outputs, oinfo)
	}
	return outputs
}
Example #20
0
File: root.go Project: mkrull/wingo
func handleMotionNotify(X *xgbutil.XUtil, ev xevent.MotionNotifyEvent) {
	qp, err := xproto.QueryPointer(X.Conn(), X.RootWin()).Reply()
	if err != nil {
		logger.Warning.Printf("Could not query pointer: %s", err)
		return
	}

	geom := xrect.New(int(qp.RootX), int(qp.RootY), 1, 1)
	if wrk := wm.Heads.FindMostOverlap(geom); wrk != nil {
		if wrk != wm.Workspace() {
			wm.SetWorkspace(wrk, false)
			wm.FocusFallback()
		}
	}
}
Example #21
0
// NewBackground creates an xgraphics.Image which spans the entire screen,
// initialized to black.
func NewBackground(X *xgbutil.XUtil) (*xgraphics.Image, error) {
	res, err := randr.GetScreenResources(X.Conn(), X.RootWin()).Reply()
	if err != nil {
		return nil, err
	}
	var bgRect image.Rectangle
	for _, output := range res.Outputs {
		r, err := util.OutputRect(X, output)
		// NOTE: It doesn't really matter if this returns a Zero Rectangle.
		if err != nil {
			return nil, err
		}
		bgRect = bgRect.Union(r)
	}
	return xgraphics.New(X, bgRect), nil
}
Example #22
0
// announce sends a ClientMessage event to the root window to let everyone
// know that Wingo is the boss. (As per ICCCM 2.8.)
func announce(X *xgbutil.XUtil) {
	typAtom, err := xprop.Atm(X, "MANAGER")
	if err != nil {
		logger.Warning.Println(err)
		return
	}
	manSelAtom, err := managerAtom(X)
	if err != nil {
		logger.Warning.Println(err)
		return
	}
	cm, err := xevent.NewClientMessage(32, X.RootWin(), typAtom,
		int(X.TimeGet()), int(manSelAtom), int(X.Dummy()))
	xproto.SendEvent(X.Conn(), false, X.RootWin(),
		xproto.EventMaskStructureNotify, string(cm.Bytes()))
}
Example #23
0
func (b *brightness) adjust(Xu *xgbutil.XUtil, increase bool) error {
	X := Xu.Conn()
	root := xproto.Setup(X).DefaultScreen(X).Root
	screens, err := randr.GetScreenResources(X, root).Reply()
	if err != nil {
		return fmt.Errorf("getting screen: %v", err)
	}

	for _, output := range screens.Outputs {
		query, err := randr.QueryOutputProperty(X, output, b.prop).Reply()
		if err != nil {
			if _, ok := err.(xproto.NameError); ok {
				// this output has no backlight
				continue
			}
			return fmt.Errorf("query backlight: %v", err)
		}
		if !query.Range {
			return errors.New("backlight brightness range not specified")
		}
		if len(query.ValidValues) != 2 {
			return fmt.Errorf("expected min and max, got: %v", query.ValidValues)
		}
		min, max := query.ValidValues[0], query.ValidValues[1]
		// log.Printf("backlight range: %d .. %d", min, max)

		get, err := randr.GetOutputProperty(X, output, b.prop, xproto.AtomNone, 0, 4, false, false).Reply()
		if err != nil {
			return fmt.Errorf("get backlight property: %v", err)
		}
		if get.Type != xproto.AtomInteger ||
			get.NumItems != 1 ||
			get.Format != 32 {
			return fmt.Errorf("backlight property value looks wrong")
		}
		old := *(*int32)(unsafe.Pointer(&get.Data[0]))
		// log.Printf("backlight data: %d", old)

		bri := delta5(old, min, max, increase)

		data := (*[4]byte)(unsafe.Pointer(&bri))[:]
		if err := randr.ChangeOutputPropertyChecked(X, output, b.prop, xproto.AtomInteger, 32, xproto.PropModeReplace, 1, data).Check(); err != nil {
			return err
		}
	}
	return nil
}
Example #24
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
	}

	return xproto.ChangePropertyChecked(xu.Conn(), xproto.PropModeReplace, win,
		propAtom, typAtom, format,
		uint32(len(data)/(int(format)/8)), data).Check()
}
Example #25
0
func newParent(X *xgbutil.XUtil, cid xproto.Window) (*Parent, error) {
	parent, err := xwindow.Generate(X)
	if err != nil {
		logger.Error.Printf("Could not create a parent window for client "+
			"with id '%d' because: %s", cid, err)
		logger.Error.Fatalf("In a state where no new windows can be created. " +
			"Unfortunately, we must exit.")
	}

	// clientAttrs, err := xproto.GetWindowAttributes(X.Conn(), cid).Reply()
	// if err != nil {
	// return nil, fmt.Errorf("Could not get window attributes: %s", err)
	// }

	// visual := clientAttrs.Visual
	// vdepth := getVisualDepth(X, visual)
	visual := X.Screen().RootVisual
	vdepth := X.Screen().RootDepth
	// logger.Debug.Printf("Visualid: %x, Depth: %d", visual, vdepth)
	err = xproto.CreateWindowChecked(X.Conn(),
		vdepth, parent.Id, X.RootWin(),
		0, 0, 1, 1, 0, xproto.WindowClassInputOutput, visual,
		xproto.CwEventMask,
		[]uint32{
			xproto.EventMaskSubstructureRedirect |
				xproto.EventMaskButtonPress |
				xproto.EventMaskButtonRelease |
				xproto.EventMaskFocusChange,
		}).Check()
	if err != nil {
		return nil, fmt.Errorf("Could not create window: %s", err)
	}

	err = xproto.ReparentWindowChecked(X.Conn(),
		cid, parent.Id, 0, 0).Check()
	if err != nil {
		return nil, fmt.Errorf("Could not reparent window: %s", err)
	}

	return &Parent{
		Window:      parent,
		MoveState:   &MoveState{},
		ResizeState: &ResizeState{},
		isMapped:    false,
	}, nil
}
Example #26
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
	}

	reply, err := xproto.GetAtomName(xu.Conn(), aid).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
}
// 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 {
		err = xproto.GrabButtonChecked(xu.Conn(), true, win, pointerMasks,
			pSync, xproto.GrabModeAsync, 0, 0, byte(button), mods|m).Check()
		if err != nil {
			return err
		}
	}
	return nil
}
Example #28
0
File: ipc.go Project: mkrull/wingo
func socketFilePath(X *xgbutil.XUtil) string {
	xc := X.Conn()
	name := fmt.Sprintf(":%d.%d", xc.DisplayNumber, xc.DefaultScreen)

	var runtimeDir string
	xdgRuntime := os.Getenv("XDG_RUNTIME_DIR")
	if len(xdgRuntime) > 0 {
		runtimeDir = path.Join(xdgRuntime, "wingo")
	} else {
		runtimeDir = path.Join(os.TempDir(), "wingo")
	}

	if err := os.MkdirAll(runtimeDir, 0777); err != nil {
		logger.Error.Fatalf("Could not create directory '%s': %s",
			runtimeDir, err)
	}

	return path.Join(runtimeDir, name)
}
Example #29
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
	}

	reply, err := xproto.InternAtom(xu.Conn(), onlyIfExists,
		uint16(len(name)), name).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
}
Example #30
0
func newBrightness(Xu *xgbutil.XUtil) (*brightness, error) {
	const atomName = "Backlight"
	atomReply, err := xproto.InternAtom(Xu.Conn(), true, uint16(len(atomName)), atomName).Reply()
	if err != nil {
		return nil, fmt.Errorf("no backlight: %v", err)
	}

	b := &brightness{
		prop: atomReply.Atom,
	}

	if err := bind(Xu,
		binding{"XF86MonBrightnessUp", b.up},
		binding{"XF86MonBrightnessDown", b.down},
	); err != nil {
		return nil, err
	}

	return b, nil
}