129 lines
No EOL
3.9 KiB
Go
129 lines
No EOL
3.9 KiB
Go
//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")
|
|
} |