You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
2.7 KiB
140 lines
2.7 KiB
1 year ago
|
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)
|
||
|
}
|
||
|
}
|
||
|
}
|