Files
codegirl-games/agentbox/internal/environment/dockerx11/input.go
T
2026-08-18 06:03:59 +00:00

96 lines
2.2 KiB
Go

package dockerx11
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
"time"
"agentbox/internal/environment"
)
func (environmentBackend *Environment) SendInput(
ctx context.Context,
action environment.InputAction,
) error {
var xdotoolArguments []string
switch action.Type {
case environment.KeyDown:
if action.Key == "" {
return errors.New("key_down requires key")
}
xdotoolArguments = []string{"keydown", toX11KeyName(action.Key)}
case environment.KeyUp:
if action.Key == "" {
return errors.New("key_up requires key")
}
xdotoolArguments = []string{"keyup", toX11KeyName(action.Key)}
case environment.MouseMove:
xdotoolArguments = []string{
"mousemove",
strconv.Itoa(action.X),
strconv.Itoa(action.Y),
}
case environment.MouseDown:
xdotoolArguments = []string{"mousedown", strconv.Itoa(action.Button)}
case environment.MouseUp:
xdotoolArguments = []string{"mouseup", strconv.Itoa(action.Button)}
case environment.Wait:
if action.DurationMS < 0 {
return errors.New("wait duration cannot be negative")
}
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(time.Duration(action.DurationMS) * time.Millisecond):
return nil
}
default:
return fmt.Errorf("unsupported input action %q", action.Type)
}
dockerArguments := []string{
"exec",
environmentBackend.containerName,
"xdotool",
}
dockerArguments = append(dockerArguments, xdotoolArguments...)
if _, err := environmentBackend.runDocker(ctx, dockerArguments...); err != nil {
return fmt.Errorf("send %s: %w", action.Type, err)
}
return nil
}
// toX11KeyName keeps X11 spellings out of the public action API. Agents can use
// logical names such as RIGHT even though xdotool expects Right.
func toX11KeyName(logicalName string) string {
switch strings.ToUpper(logicalName) {
case "LEFT":
return "Left"
case "RIGHT":
return "Right"
case "UP":
return "Up"
case "DOWN":
return "Down"
case "ENTER", "RETURN":
return "Return"
case "ESC", "ESCAPE":
return "Escape"
case "SPACE":
return "space"
case "TAB":
return "Tab"
case "BACKSPACE":
return "BackSpace"
case "DELETE":
return "Delete"
}
if len(logicalName) == 1 {
return strings.ToLower(logicalName)
}
return logicalName
}