mirror of
https://github.com/m1k1o/neko.git
synced 2024-07-24 14:40:50 +12:00
Xorg input driver (#53)
* add xf86 input driver. * cleanup. * rewrite to unix socket PoC. * add input rebuild. * lint & docs. * add input driver struct. * comments, lint, socket name from config. * add touch events to webrtc. * switch to uint32. * misc update logging & linting, * fix screen size * set touchscreen as core pointer. * add touch to ws control. * SendCoreEvents. * extract to own xinput folder. * add debounce. * switch pressure to uint8. * check buffer size. * send touch events with system init.
This commit is contained in:
31
pkg/xinput/dummy.go
Normal file
31
pkg/xinput/dummy.go
Normal file
@ -0,0 +1,31 @@
|
||||
package xinput
|
||||
|
||||
import "time"
|
||||
|
||||
type dummy struct{}
|
||||
|
||||
func NewDummy() Driver {
|
||||
return &dummy{}
|
||||
}
|
||||
|
||||
func (d *dummy) Connect() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dummy) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dummy) Debounce(duration time.Duration) {}
|
||||
|
||||
func (d *dummy) TouchBegin(touchId uint32, x, y int, pressure uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dummy) TouchUpdate(touchId uint32, x, y int, pressure uint8) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dummy) TouchEnd(touchId uint32, x, y int, pressure uint8) error {
|
||||
return nil
|
||||
}
|
61
pkg/xinput/types.go
Normal file
61
pkg/xinput/types.go
Normal file
@ -0,0 +1,61 @@
|
||||
package xinput
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
// absolute coordinates used in driver
|
||||
AbsX = 0xffff
|
||||
AbsY = 0xffff
|
||||
)
|
||||
|
||||
const (
|
||||
XI_TouchBegin = 18
|
||||
XI_TouchUpdate = 19
|
||||
XI_TouchEnd = 20
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
_type uint16
|
||||
touchId uint32
|
||||
x int32 // can be negative?
|
||||
y int32 // can be negative?
|
||||
pressure uint8
|
||||
}
|
||||
|
||||
func (msg *Message) Unpack(buffer []byte) {
|
||||
msg._type = uint16(buffer[0])
|
||||
msg.touchId = uint32(buffer[1]) | (uint32(buffer[2]) << 8)
|
||||
msg.x = int32(buffer[3]) | (int32(buffer[4]) << 8) | (int32(buffer[5]) << 16) | (int32(buffer[6]) << 24)
|
||||
msg.y = int32(buffer[7]) | (int32(buffer[8]) << 8) | (int32(buffer[9]) << 16) | (int32(buffer[10]) << 24)
|
||||
msg.pressure = uint8(buffer[11])
|
||||
}
|
||||
|
||||
func (msg *Message) Pack() []byte {
|
||||
var buffer [12]byte
|
||||
|
||||
buffer[0] = byte(msg._type)
|
||||
buffer[1] = byte(msg.touchId)
|
||||
buffer[2] = byte(msg.touchId >> 8)
|
||||
buffer[3] = byte(msg.x)
|
||||
buffer[4] = byte(msg.x >> 8)
|
||||
buffer[5] = byte(msg.x >> 16)
|
||||
buffer[6] = byte(msg.x >> 24)
|
||||
buffer[7] = byte(msg.y)
|
||||
buffer[8] = byte(msg.y >> 8)
|
||||
buffer[9] = byte(msg.y >> 16)
|
||||
buffer[10] = byte(msg.y >> 24)
|
||||
buffer[11] = byte(msg.pressure)
|
||||
|
||||
return buffer[:]
|
||||
}
|
||||
|
||||
type Driver interface {
|
||||
Connect() error
|
||||
Close() error
|
||||
// release touches, that were not updated for duration
|
||||
Debounce(duration time.Duration)
|
||||
// touch events
|
||||
TouchBegin(touchId uint32, x, y int, pressure uint8) error
|
||||
TouchUpdate(touchId uint32, x, y int, pressure uint8) error
|
||||
TouchEnd(touchId uint32, x, y int, pressure uint8) error
|
||||
}
|
122
pkg/xinput/xinput.go
Normal file
122
pkg/xinput/xinput.go
Normal file
@ -0,0 +1,122 @@
|
||||
/* custom xf86 input driver communication protocol */
|
||||
package xinput
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type driver struct {
|
||||
mu sync.Mutex
|
||||
socket string
|
||||
conn net.Conn
|
||||
|
||||
debounceTouchIds map[uint32]time.Time
|
||||
}
|
||||
|
||||
func NewDriver(socket string) Driver {
|
||||
return &driver{
|
||||
socket: socket,
|
||||
|
||||
debounceTouchIds: make(map[uint32]time.Time),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) Connect() error {
|
||||
c, err := net.Dial("unix", d.socket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.conn = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Close() error {
|
||||
return d.conn.Close()
|
||||
}
|
||||
|
||||
func (d *driver) Debounce(duration time.Duration) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
t := time.Now()
|
||||
for touchId, start := range d.debounceTouchIds {
|
||||
if t.Sub(start) < duration {
|
||||
continue
|
||||
}
|
||||
|
||||
msg := Message{
|
||||
_type: XI_TouchEnd,
|
||||
touchId: touchId,
|
||||
x: -1,
|
||||
y: -1,
|
||||
}
|
||||
_, _ = d.conn.Write(msg.Pack())
|
||||
delete(d.debounceTouchIds, touchId)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *driver) TouchBegin(touchId uint32, x, y int, pressure uint8) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if _, ok := d.debounceTouchIds[touchId]; ok {
|
||||
return fmt.Errorf("debounced touch id %v", touchId)
|
||||
}
|
||||
|
||||
d.debounceTouchIds[touchId] = time.Now()
|
||||
|
||||
msg := Message{
|
||||
_type: XI_TouchBegin,
|
||||
touchId: touchId,
|
||||
x: int32(x),
|
||||
y: int32(y),
|
||||
pressure: pressure,
|
||||
}
|
||||
_, err := d.conn.Write(msg.Pack())
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) TouchUpdate(touchId uint32, x, y int, pressure uint8) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if _, ok := d.debounceTouchIds[touchId]; !ok {
|
||||
return fmt.Errorf("unknown touch id %v", touchId)
|
||||
}
|
||||
|
||||
d.debounceTouchIds[touchId] = time.Now()
|
||||
|
||||
msg := Message{
|
||||
_type: XI_TouchUpdate,
|
||||
touchId: touchId,
|
||||
x: int32(x),
|
||||
y: int32(y),
|
||||
pressure: pressure,
|
||||
}
|
||||
_, err := d.conn.Write(msg.Pack())
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *driver) TouchEnd(touchId uint32, x, y int, pressure uint8) error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if _, ok := d.debounceTouchIds[touchId]; !ok {
|
||||
return fmt.Errorf("unknown touch id %v", touchId)
|
||||
}
|
||||
|
||||
delete(d.debounceTouchIds, touchId)
|
||||
|
||||
msg := Message{
|
||||
_type: XI_TouchEnd,
|
||||
touchId: touchId,
|
||||
x: int32(x),
|
||||
y: int32(y),
|
||||
pressure: pressure,
|
||||
}
|
||||
_, err := d.conn.Write(msg.Pack())
|
||||
return err
|
||||
}
|
Reference in New Issue
Block a user