| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- package tea
- import (
- "bytes"
- "errors"
- )
- // MouseMsg contains information about a mouse event and is sent to a program's
- // update function when mouse activity occurs. Note that the mouse must first
- // be enabled in order for the mouse events to be received.
- type MouseMsg MouseEvent
- // MouseEvent represents a mouse event, which could be a click, a scroll wheel
- // movement, a cursor movement, or a combination.
- type MouseEvent struct {
- X int
- Y int
- Type MouseEventType
- Alt bool
- Ctrl bool
- }
- // String returns a string representation of a mouse event.
- func (m MouseEvent) String() (s string) {
- if m.Ctrl {
- s += "ctrl+"
- }
- if m.Alt {
- s += "alt+"
- }
- s += mouseEventTypes[m.Type]
- return s
- }
- // MouseEventType indicates the type of mouse event occurring.
- type MouseEventType int
- // Mouse event types.
- const (
- MouseUnknown MouseEventType = iota
- MouseLeft
- MouseRight
- MouseMiddle
- MouseRelease
- MouseWheelUp
- MouseWheelDown
- MouseMotion
- )
- var mouseEventTypes = map[MouseEventType]string{
- MouseUnknown: "unknown",
- MouseLeft: "left",
- MouseRight: "right",
- MouseMiddle: "middle",
- MouseRelease: "release",
- MouseWheelUp: "wheel up",
- MouseWheelDown: "wheel down",
- MouseMotion: "motion",
- }
- // Parse X10-encoded mouse events; the simplest kind. The last release of X10
- // was December 1986, by the way.
- //
- // X10 mouse events look like:
- //
- // ESC [M Cb Cx Cy
- //
- // See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking
- func parseX10MouseEvents(buf []byte) ([]MouseEvent, error) {
- var r []MouseEvent
- seq := []byte("\x1b[M")
- if !bytes.Contains(buf, seq) {
- return r, errors.New("not an X10 mouse event")
- }
- for _, v := range bytes.Split(buf, seq) {
- if len(v) == 0 {
- continue
- }
- if len(v) != 3 {
- return r, errors.New("not an X10 mouse event")
- }
- var m MouseEvent
- const byteOffset = 32
- e := v[0] - byteOffset
- const (
- bitShift = 0b0000_0100
- bitAlt = 0b0000_1000
- bitCtrl = 0b0001_0000
- bitMotion = 0b0010_0000
- bitWheel = 0b0100_0000
- bitsMask = 0b0000_0011
- bitsLeft = 0b0000_0000
- bitsMiddle = 0b0000_0001
- bitsRight = 0b0000_0010
- bitsRelease = 0b0000_0011
- bitsWheelUp = 0b0000_0000
- bitsWheelDown = 0b0000_0001
- )
- if e&bitWheel != 0 {
- // Check the low two bits.
- switch e & bitsMask {
- case bitsWheelUp:
- m.Type = MouseWheelUp
- case bitsWheelDown:
- m.Type = MouseWheelDown
- }
- } else {
- // Check the low two bits.
- // We do not separate clicking and dragging.
- switch e & bitsMask {
- case bitsLeft:
- m.Type = MouseLeft
- case bitsMiddle:
- m.Type = MouseMiddle
- case bitsRight:
- m.Type = MouseRight
- case bitsRelease:
- if e&bitMotion != 0 {
- m.Type = MouseMotion
- } else {
- m.Type = MouseRelease
- }
- }
- }
- if e&bitAlt != 0 {
- m.Alt = true
- }
- if e&bitCtrl != 0 {
- m.Ctrl = true
- }
- // (1,1) is the upper left. We subtract 1 to normalize it to (0,0).
- m.X = int(v[1]) - byteOffset - 1
- m.Y = int(v[2]) - byteOffset - 1
- r = append(r, m)
- }
- return r, nil
- }
|