diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..08504d9 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module gitea.beetbox.io/Alex/pv + +go 1.18 + +require github.com/linuxdeepin/go-x11-client v0.0.0-20221118020450-811d87e63fec + +require ( + github.com/stretchr/testify v1.8.1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..76749f3 --- /dev/null +++ b/go.sum @@ -0,0 +1,25 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/linuxdeepin/go-x11-client v0.0.0-20221118020450-811d87e63fec h1:CaVGU829QOYwWrKdvC06uMTXkrj4vwyH4UGAn92bdzE= +github.com/linuxdeepin/go-x11-client v0.0.0-20221118020450-811d87e63fec/go.mod h1:KwpmRZ47A/0a2l9V0V6aTlkuNaqy5j1fOqMFJONuIMY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go new file mode 100644 index 0000000..430ce45 --- /dev/null +++ b/main.go @@ -0,0 +1,139 @@ +package main + +import ( + "context" + "fmt" + "log" + "math" + "os" + "os/signal" + "syscall" + + "github.com/linuxdeepin/go-x11-client/util/cursor" + "github.com/linuxdeepin/go-x11-client/util/mousebind" + + x "github.com/linuxdeepin/go-x11-client" +) + +// Give names to the events we care about +const ( + Pressed uint8 = 4 + Released = 5 +) + +type dragger struct { + Done chan bool + events chan x.GenericEvent + ctx context.Context + pointerDown bool + start [2]int16 + end [2]int16 +} + +// NewDragger returns a new reference to a dragger. +// This dragger can only be used to watch one drag event. +func NewDragger(events chan x.GenericEvent, ctx context.Context) *dragger { + return &dragger{ + Done: make(chan bool, 1), + events: events, + ctx: ctx, + } +} + +// Watch begins the process of dragger watching for drag events +func (s *dragger) Watch() { + for { + select { + case generic := <-s.events: + s.handleEvent(generic) + break + case _ = <-s.ctx.Done(): + return + } + } +} + +func (s *dragger) handleEvent(generic x.GenericEvent) { + event, err := x.NewButtonPressEvent(generic) + if err != nil { + log.Fatal(err) + } + + code := generic.GetEventCode() + + if code == Pressed { + s.pointerDown = true + s.start = [2]int16{event.EventX, event.EventY} + } else { + s.end = [2]int16{event.EventX, event.EventY} + if s.pointerDown { + s.pointerDown = false + s.Done <- true + } else { + s.Done <- false + } + } +} + +// Distance returns the total distance of the drag event +func (s dragger) Distance() int { + diffx := int(s.start[0] - s.end[0]) + diffy := int(s.start[1] - s.end[1]) + distance := math.Sqrt(float64((diffx * diffx) + (diffy * diffy))) + return int(distance) +} + +func loadCursor(conn *x.Conn) (x.Cursor, error) { + img, err := cursor.LoadImage("default", "crosshair", 2) + if err != nil { + return x.CursorNone, err + } + + return img.LoadCursor(conn, "") +} + +func main() { + stop := make(chan os.Signal) + signal.Notify(stop, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) + + display, err := x.NewConnDisplay("") + if err != nil { + log.Fatal(err) + } + defer display.Close() + + screen := display.GetDefaultScreen() + + curs, err := loadCursor(display) + if err != nil { + log.Fatal(err) + } + + mask := uint16(x.EventMaskButtonPress | x.EventMaskButtonRelease) + err = mousebind.GrabPointer(display, screen.Root, mask, x.None, curs) + if err != nil { + log.Fatal(err) + } + + defer mousebind.UngrabPointer(display) + + eventChan := display.MakeAndAddEventChan(1) + + ctx, cancel := context.WithCancel(context.Background()) + dm := NewDragger(eventChan, ctx) + go dm.Watch() + + for { + select { + case v := <-dm.Done: + if v { + fmt.Println(dm.Distance()) + os.Exit(0) + } + break + case <-stop: + cancel() + os.Exit(0) + } + } +}