Example #1
0
func main() {
	X, err := xgbutil.NewConn()
	fatal(err)

	// Whenever the mousebind package is used, you must call Initialize.
	// Similarly for the keybind package.
	keybind.Initialize(X)
	mousebind.Initialize(X)

	// Easter egg! Use a right click to draw a gopher.
	gopherPng, _, err := image.Decode(bytes.NewBuffer(gopher.GopherPng()))
	fatal(err)

	// Now scale it to a reasonable size.
	gopher := xgraphics.Scale(gopherPng, gopherWidth, gopherHeight)

	// Create a new xgraphics.Image. It automatically creates an X pixmap for
	// you, and handles drawing to windows in the XDraw, XPaint and
	// XSurfaceSet functions.
	// N.B. An error is possible since X pixmap allocation can fail.
	canvas := xgraphics.New(X, image.Rect(0, 0, width, height))

	// Color in the background color.
	canvas.For(func(x, y int) xgraphics.BGRA {
		return bg
	})

	// Use the convenience function XShowExtra to create and map the
	// canvas window.
	// XShowExtra will also set the surface window of canvas for us.
	// We also use XShowExtra to set the name of the window and to quit the
	// main event loop when the window is closed.
	win := canvas.XShowExtra("Pointer painting", true)

	// Listen for pointer motion events and key press events.
	win.Listen(xproto.EventMaskButtonPress | xproto.EventMaskButtonRelease |
		xproto.EventMaskKeyPress)

	// The mousebind drag function runs three callbacks: one when the drag is
	// first started, another at each "step" in the drag, and a final one when
	// the drag is done.
	// The button sequence (in this case '1') is pressed, the first callback
	// is executed. If the first return value is true, the drag continues
	// and a pointer grab is initiated with the cursor id specified in the
	// second return value (use 0 to keep the cursor unchanged).
	// If it's false, the drag stops.
	// Note that Drag will automatically compress MotionNotify events.
	mousebind.Drag(X, win.Id, win.Id, "1", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			drawPencil(canvas, win, ex, ey)
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			drawPencil(canvas, win, ex, ey)
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {})

	mousebind.Drag(X, win.Id, win.Id, "3", false,
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) (bool, xproto.Cursor) {
			drawGopher(canvas, gopher, win, ex, ey)
			return true, 0
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {
			drawGopher(canvas, gopher, win, ex, ey)
		},
		func(X *xgbutil.XUtil, rx, ry, ex, ey int) {})

	// Bind to the clear key specified, and just redraw the bg color.
	keybind.KeyPressFun(
		func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
			clearCanvas(canvas, win)
		}).Connect(X, win.Id, clearKey, false)

	// Bind a callback to each key specified in the 'pencils' color map.
	// The response is to simply switch the pencil color.
	for key, clr := range pencils {
		c := clr
		keybind.KeyPressFun(
			func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
				log.Printf("Changing pencil color to: %#v", c)
				pencil = c
			}).Connect(X, win.Id, key, false)
	}

	// Output some basic directions.
	fmt.Println("Use the left or right buttons on your mouse to paint " +
		"squares and gophers.")
	fmt.Println("Pressing numbers 1, 2, 3, 4, 5 or 6 will switch your pencil " +
		"color.")
	fmt.Println("Pressing 'c' will clear the canvas.")

	xevent.Main(X)
}
Example #2
0
func main() {
	// Connect to the X server using the DISPLAY environment variable.
	X, err := xgbutil.NewConn()
	if err != nil {
		log.Fatal(err)
	}

	// Nice names for the modifier keys (same ones used by xmodmap).
	// This slice corresponds to the keybind.Modifiers slice (except for
	// the last 'Any' modifier element).
	nice := []string{
		"shift", "lock", "control", "mod1", "mod2", "mod3", "mod4", "mod5",
	}

	// Whenever one uses the keybind package, Initialize should always be
	// called first. In this case, it initializes the key and modifier maps.
	keybind.Initialize(X)

	// Get the current modifier map.
	// The map is actually a table, where rows correspond to modifiers, and
	// columns correspond to the keys that activate that modifier.
	modMap := keybind.ModMapGet(X)

	// The number of keycodes allowed per modifier (i.e., the number of
	// columns in the modifier map).
	kPerMod := int(modMap.KeycodesPerModifier)

	// Get the number of allowable keysyms per keycode.
	// This is used to search for a valid keysym for a particular keycode.
	symsPerKc := int(keybind.KeyMapGet(X).KeysymsPerKeycode)

	// Imitate everything...
	fmt.Printf("xmodmap:  up to %d keys per modifier, "+
		"(keycodes in parentheses):\n\n", kPerMod)

	// Iterate through all keyboard modifiers defined in xgb/xproto
	// except the 'Any' modifier (which is last).
	for mmi := range keybind.Modifiers[:len(keybind.Modifiers)-1] {
		niceName := nice[mmi]
		keys := make([]string, 0, kPerMod)

		// row is the row for the 'mmi' modifier in the modifier mapping table.
		row := mmi * kPerMod

		// Iterate over each keycode in the modifier map for this modifier.
		for _, kc := range modMap.Keycodes[row : row+kPerMod] {
			// If this entry doesn't have a keycode (i.e., it's zero), we
			// have to skip it.
			if kc == 0 {
				continue
			}

			// Look for the first valid keysym in the keyboard map corresponding
			// to this keycode. If one can't be found, output "BadKey."
			var ksym xproto.Keysym = 0
			for column := 0; column < symsPerKc; column++ {
				ksym = keybind.KeysymGet(X, kc, byte(column))
				if ksym != 0 {
					break
				}
			}

			if ksym == 0 {
				keys = append(keys, fmt.Sprintf("BadKey (0x%x)", kc))
			} else {
				keys = append(keys,
					fmt.Sprintf("%s (0x%x)", keybind.KeysymToStr(ksym), kc))
			}
		}

		fmt.Printf("%-12s%s\n", niceName, strings.Join(keys, ",  "))
	}
	fmt.Println("")
}