Example #1
0
// GetFormat searches SetupInfo for a Format matching the depth provided.
func GetFormat(X *xgbutil.XUtil, depth byte) *xproto.Format {
	for _, pixForm := range X.Setup().PixmapFormats {
		if pixForm.Depth == depth {
			return &pixForm
		}
	}
	return nil
}
Example #2
0
// checkCompatibility reads info in the X setup info struct and emits
// messages to stderr if they don't correspond to values that xgraphics
// supports.
// The idea is that in the future, we'll support more values.
// The real reason for checkCompatibility is to make debugging easier. Without
// it, if the values weren't what we'd expect, we'd see garbled images in the
// best case, and probably BadLength errors in the worst case.
func checkCompatibility(X *xgbutil.XUtil) {
	s := X.Setup()
	scrn := X.Screen()
	failed := false

	if s.ImageByteOrder != xproto.ImageOrderLSBFirst {
		log.Printf("Your X server uses MSB image byte order. Unfortunately, " +
			"xgraphics currently requires LSB image byte order. You may see " +
			"weird things. Please report this.")
		failed = true
	}
	if s.BitmapFormatBitOrder != xproto.ImageOrderLSBFirst {
		log.Printf("Your X server uses MSB bitmap bit order. Unfortunately, " +
			"xgraphics currently requires LSB bitmap bit order. If you " +
			"aren't using X bitmaps, you should be able to proceed normally. " +
			"Please report this.")
		failed = true
	}
	if s.BitmapFormatScanlineUnit != 32 {
		log.Printf("xgraphics expects that the scanline unit is set to 32, "+
			"but your X server has it set to '%d'. "+
			"Namely, xgraphics hasn't been tested on other values. Things "+
			"may still work. Particularly, if you aren't using X bitmaps, "+
			"you should be completely unaffected. Please report this.",
			s.BitmapFormatScanlineUnit)
		failed = true
	}
	if scrn.RootDepth != 24 {
		log.Printf("xgraphics expects that the root window has a depth of 24, "+
			"but yours has depth '%d'. Its possible things will still work "+
			"if your value is 32, but will be unlikely to work with values "+
			"less than 24. Please report this.", scrn.RootDepth)
		failed = true
	}

	// Look for the default format for pixmaps and make sure bits per pixel
	// is 32.
	format := xgraphics.GetFormat(X, scrn.RootDepth)
	if format.BitsPerPixel != 32 {
		log.Printf("xgraphics expects that the bits per pixel for the root "+
			"window depth is 32. On your system, the root depth is %d and "+
			"the bits per pixel is %d. Things will most certainly not work. "+
			"Please report this.",
			scrn.RootDepth, format.BitsPerPixel)
		failed = true
	}

	// Give instructions on reporting the issue.
	if failed {
		log.Printf("Please report the aforementioned error message(s) at " +
			"https://github.com/BurntSushi/xgbutil. Please also include the " +
			"entire output of the `xdpyinfo` command in your report. Thanks!")
	} else {
		log.Printf("No compatibility issues detected.")
	}
}
Example #3
0
// minMaxKeycodeGet a simple accessor to the X setup info to return the
// minimum and maximum keycodes. They are typically 8 and 255, respectively.
func minMaxKeycodeGet(xu *xgbutil.XUtil) (xproto.Keycode, xproto.Keycode) {
	return xu.Setup().MinKeycode, xu.Setup().MaxKeycode
}
Example #4
0
// readDrawableData uses Format information to read data from an X pixmap
// into an xgraphics.Image.
// readPixmapData does not take into account all information possible to read
// X pixmaps and bitmaps. Of particular note is bit order/byte order.
func readDrawableData(X *xgbutil.XUtil, ximg *Image, did xproto.Drawable,
	imgData *xproto.GetImageReply, width, height int) error {

	format := GetFormat(X, imgData.Depth)
	if format == nil {
		return fmt.Errorf("Could not find valid format for pixmap %d "+
			"with depth %d", did, imgData.Depth)
	}

	switch format.Depth {
	case 1: // We read bitmaps in as alpha masks.
		if format.BitsPerPixel != 1 {
			return fmt.Errorf("The image returned for pixmap id %d with "+
				"depth %d has an unsupported value for bits-per-pixel: %d",
				did, format.Depth, format.BitsPerPixel)
		}

		// Calculate the padded width of our image data.
		pad := int(X.Setup().BitmapFormatScanlinePad)
		paddedWidth := width
		if width%pad != 0 {
			paddedWidth = width + pad - (width % pad)
		}

		// Process one scanline at a time. Each 'y' represents a
		// single scanline.
		for y := 0; y < height; y++ {
			// Each scanline has length 'width' padded to
			// BitmapFormatScanlinePad, which is found in the X setup info.
			// 'i' is the index to the starting byte of the yth scanline.
			i := y * paddedWidth / 8
			for x := 0; x < width; x++ {
				b := imgData.Data[i+x/8] >> uint(x%8)
				if b&1 > 0 { // opaque
					ximg.Set(x, y, BGRA{0x0, 0x0, 0x0, 0xff})
				} else { // transparent
					ximg.Set(x, y, BGRA{0xff, 0xff, 0xff, 0x0})
				}
			}
		}
	case 24:
		if format.BitsPerPixel != 24 && format.BitsPerPixel != 32 {
			return fmt.Errorf("The image returned for pixmap id %d has "+
				"an unsupported value for bits-per-pixel: %d",
				did, format.BitsPerPixel)
		}
		bytesPer := int(format.BitsPerPixel) / 8
		var i int
		ximg.For(func(x, y int) BGRA {
			i = y*width*bytesPer + x*bytesPer
			return BGRA{
				B: imgData.Data[i],
				G: imgData.Data[i+1],
				R: imgData.Data[i+2],
				A: 0xff,
			}
		})
	default:
		return fmt.Errorf("The image returned for pixmap id %d has an "+
			"unsupported value for depth: %d", did, format.Depth)
	}

	return nil
}