//go:build linux // X11 window capture using XGetImage. package backends import ( "fmt" "image" "git.cloonar.com/openclawd/iso-bot/pkg/engine/capture" ) // X11Config holds configuration for X11 window capture. type X11Config struct { // WindowTitle is the window title to search for. WindowTitle string `yaml:"window_title"` // WindowClass is the WM_CLASS property to match. WindowClass string `yaml:"window_class"` // Display is the X11 display to connect to (e.g., ":0"). Display string `yaml:"display"` // IncludeDecorations captures window decorations (title bar, borders). IncludeDecorations bool `yaml:"include_decorations"` } // X11Source captures from an X11 window using XGetImage. type X11Source struct { config X11Config display uintptr // *Display window uint64 // Window ID width int height int } // NewX11Source creates an X11 window capture source. func NewX11Source(configMap map[string]interface{}) (capture.Source, error) { var config X11Config // Extract config from map if title, ok := configMap["window_title"].(string); ok { config.WindowTitle = title } if class, ok := configMap["window_class"].(string); ok { config.WindowClass = class } if display, ok := configMap["display"].(string); ok { config.Display = display } else { config.Display = ":0" // Default display } if decorations, ok := configMap["include_decorations"].(bool); ok { config.IncludeDecorations = decorations } // Validate config if config.WindowTitle == "" && config.WindowClass == "" { return nil, fmt.Errorf("either window_title or window_class must be specified") } return &X11Source{ config: config, }, nil } // Name returns a description of this capture source. func (x *X11Source) Name() string { if x.config.WindowTitle != "" { return fmt.Sprintf("X11 Window: %s", x.config.WindowTitle) } return fmt.Sprintf("X11 Window Class: %s", x.config.WindowClass) } // Capture grabs a single frame from the X11 window. func (x *X11Source) Capture() (image.Image, error) { // TODO: Implement X11 window capture // 1. Open X11 display connection // 2. Find window by title/class using XQueryTree and property queries // 3. Get window geometry with XGetGeometry // 4. Use XGetImage to capture window content // 5. Convert XImage to Go image.RGBA return nil, fmt.Errorf("X11 capture not implemented yet") } // CaptureRegion grabs a sub-region of the X11 window. func (x *X11Source) CaptureRegion(r capture.Region) (image.Image, error) { // TODO: Implement region capture // Use XGetImage with x, y, width, height parameters for the region return nil, fmt.Errorf("X11 region capture not implemented yet") } // Size returns the window dimensions. func (x *X11Source) Size() (width, height int) { // TODO: Get actual window size from XGetGeometry return x.width, x.height } // Close releases X11 resources. func (x *X11Source) Close() error { // TODO: Close X11 display connection and free resources return nil } // connectToDisplay opens a connection to the X11 display. func (x *X11Source) connectToDisplay() error { // TODO: Use XOpenDisplay to connect to X server // Store display pointer in x.display return fmt.Errorf("X11 display connection not implemented") } // findWindow searches for a window by title or class. func (x *X11Source) findWindow() (uint64, error) { // TODO: Implement window search // 1. Get root window with XDefaultRootWindow // 2. Recursively search window tree with XQueryTree // 3. For each window, check _NET_WM_NAME (title) and WM_CLASS properties // 4. Return matching window ID return 0, fmt.Errorf("X11 window search not implemented") } // getWindowGeometry retrieves window position and size. func (x *X11Source) getWindowGeometry() (int, int, int, int, error) { // TODO: Use XGetGeometry to get window bounds // Return x, y, width, height, error return 0, 0, 0, 0, fmt.Errorf("X11 geometry query not implemented") } // captureWindowImage captures the window content as an XImage. func (x *X11Source) captureWindowImage() (image.Image, error) { // TODO: Implement XGetImage capture // 1. Get window geometry // 2. Use XGetImage(display, window, x, y, width, height, AllPlanes, ZPixmap) // 3. Convert XImage pixel data to image.RGBA // 4. Handle different bit depths and byte orders return nil, fmt.Errorf("X11 image capture not implemented") }