//go:build windows // Windows window capture using BitBlt and DXGI APIs. package backends import ( "fmt" "image" "unsafe" "git.cloonar.com/openclawd/iso-bot/pkg/engine/capture" ) // Win32Config holds configuration for Windows window capture. type Win32Config struct { // WindowTitle is the exact window title to capture. WindowTitle string `yaml:"window_title"` // WindowClass is the window class name (alternative to title). WindowClass string `yaml:"window_class"` // UseDirectX enables DXGI-based capture for better performance. // Falls back to GDI BitBlt if DXGI fails. UseDirectX bool `yaml:"use_directx"` // CaptureCursor includes the mouse cursor in captured frames. CaptureCursor bool `yaml:"capture_cursor"` } // Win32Source captures from a Windows window using Win32 APIs. type Win32Source struct { config Win32Config windowHWND uintptr width int height int } // NewWin32Source creates a Windows window capture source. func NewWin32Source(configMap map[string]interface{}) (capture.Source, error) { var config Win32Config // 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 dx, ok := configMap["use_directx"].(bool); ok { config.UseDirectX = dx } if cursor, ok := configMap["capture_cursor"].(bool); ok { config.CaptureCursor = cursor } // Validate config if config.WindowTitle == "" && config.WindowClass == "" { return nil, fmt.Errorf("either window_title or window_class must be specified") } return &Win32Source{ config: config, }, nil } // Name returns a description of this capture source. func (w *Win32Source) Name() string { if w.config.WindowTitle != "" { return fmt.Sprintf("Win32 Window: %s", w.config.WindowTitle) } return fmt.Sprintf("Win32 Window Class: %s", w.config.WindowClass) } // Capture grabs a single frame from the window. func (w *Win32Source) Capture() (image.Image, error) { // TODO: Implement Win32 window capture // 1. Find window handle using FindWindow/FindWindowEx // 2. Get window dimensions with GetWindowRect // 3. Create compatible DC and bitmap // 4. Use BitBlt or DXGI to capture window content // 5. Convert to Go image.Image return nil, fmt.Errorf("Win32 capture not implemented yet") } // CaptureRegion grabs a sub-region of the window. func (w *Win32Source) CaptureRegion(r capture.Region) (image.Image, error) { // TODO: Implement region capture // Use BitBlt with source coordinates offset by region.X, region.Y return nil, fmt.Errorf("Win32 region capture not implemented yet") } // Size returns the window dimensions. func (w *Win32Source) Size() (width, height int) { // TODO: Get actual window size from GetWindowRect return w.width, w.height } // Close releases Win32 resources. func (w *Win32Source) Close() error { // TODO: Release DCs, bitmaps, and other Win32 handles return nil } // findWindow locates a window by title or class name. func (w *Win32Source) findWindow() (uintptr, error) { // TODO: Use FindWindow/FindWindowEx APIs // Handle both window title and class name searches return 0, fmt.Errorf("window lookup not implemented") } // getDXGIOutput attempts to capture using DXGI Desktop Duplication API. func (w *Win32Source) getDXGIOutput() (image.Image, error) { // TODO: Implement DXGI Desktop Duplication // 1. Create DXGI factory and enumerate adapters/outputs // 2. Create output duplication interface // 3. Acquire next frame // 4. Map texture and copy to Go image return nil, fmt.Errorf("DXGI capture not implemented") } // getBitBltOutput captures using traditional GDI BitBlt. func (w *Win32Source) getBitBltOutput() (image.Image, error) { // TODO: Implement BitBlt capture // 1. Get window DC with GetWindowDC // 2. Create compatible DC and bitmap // 3. BitBlt window content to bitmap // 4. Get bitmap bits and convert to image.RGBA return nil, fmt.Errorf("BitBlt capture not implemented") }