package xinput import ( "slices" "maps" "edge-infra.dev/pkg/sds/display/displaymanager/applier/xorg/command" "edge-infra.dev/pkg/sds/display/displaymanager/applier/xorg/command/runner" "edge-infra.dev/pkg/sds/lib/xorg" ) const ( xinputPath = "/usr/bin/xinput" mapToOutputCmd = "map-to-output" ) // Command is able to build an xinput command to configure input devices and run it. type Command interface { command.Command MapToOutput(outputID xorg.OutputID, inputID xorg.InputDeviceID) } // NewXinputCommand returns a new xinput.Command implementation. func NewXinputCommand(r runner.Runner) Command { return &xinputCmd{ cmdRunner: r, displayCmds: displayCmds{}, } } // Map of display IDs to the display's xinit commands type displayCmds map[xorg.OutputID][][]string type xinputCmd struct { cmdRunner runner.Runner displayCmds } func (x *xinputCmd) Path() string { return xinputPath } func (x *xinputCmd) Run() error { // iterate over the sorted keys for consistent output outputIDs := slices.Collect(maps.Keys(x.displayCmds)) slices.Sort(outputIDs) for _, outputID := range outputIDs { for _, args := range x.displayCmds[outputID] { if err := x.cmdRunner.Run(xinputPath, args...); err != nil { return err } } } return nil } func (x *xinputCmd) MapToOutput(outputID xorg.OutputID, inputID xorg.InputDeviceID) { // e.g. xinput map-to-output "Elo Touch Solutions" HDMI1 x.displayCmds[outputID] = append( x.displayCmds[outputID], []string{mapToOutputCmd, inputID.String(), outputID.String()}, ) }