github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/io/pointer/pointer.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  package pointer
     4  
     5  import (
     6  	"encoding/binary"
     7  	"image"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/gop9/olt/gio/f32"
    12  	"github.com/gop9/olt/gio/internal/opconst"
    13  	"github.com/gop9/olt/gio/io/event"
    14  	"github.com/gop9/olt/gio/io/key"
    15  	"github.com/gop9/olt/gio/op"
    16  )
    17  
    18  // Event is a pointer event.
    19  type Event struct {
    20  	Type   Type
    21  	Source Source
    22  	// PointerID is the id for the pointer and can be used
    23  	// to track a particular pointer from Press to
    24  	// Release or Cancel.
    25  	PointerID ID
    26  	// Priority is the priority of the receiving handler
    27  	// for this event.
    28  	Priority Priority
    29  	// Time is when the event was received. The
    30  	// timestamp is relative to an undefined base.
    31  	Time time.Duration
    32  	// Buttons are the set of pressed mouse buttons for this event.
    33  	Buttons Buttons
    34  	// Hit is set when the event was within the registered
    35  	// area for the handler. Hit can be false when a pointer
    36  	// was pressed within the hit area, and then dragged
    37  	// outside it.
    38  	Hit bool
    39  	// Position is the position of the event, relative to
    40  	// the current transformation, as set by op.TransformOp.
    41  	Position f32.Point
    42  	// Scroll is the scroll amount, if any.
    43  	Scroll f32.Point
    44  	// Modifiers is the set of active modifiers when
    45  	// the mouse button was pressed.
    46  	Modifiers key.Modifiers
    47  }
    48  
    49  // AreaOp updates the hit area to the intersection of the current
    50  // hit area and the area. The area is transformed before applying
    51  // it.
    52  type AreaOp struct {
    53  	kind areaKind
    54  	rect image.Rectangle
    55  }
    56  
    57  // InputOp declares an input handler ready for pointer
    58  // events.
    59  type InputOp struct {
    60  	Key event.Key
    61  	// Grab, if set, request that the handler get
    62  	// Grabbed priority.
    63  	Grab bool
    64  }
    65  
    66  // PassOp sets the pass-through mode.
    67  type PassOp struct {
    68  	Pass bool
    69  }
    70  
    71  type ID uint16
    72  
    73  // Type of an Event.
    74  type Type uint8
    75  
    76  // Priority of an Event.
    77  type Priority uint8
    78  
    79  // Source of an Event.
    80  type Source uint8
    81  
    82  // Buttons is a set of mouse buttons
    83  type Buttons uint8
    84  
    85  // Must match app/internal/input.areaKind
    86  type areaKind uint8
    87  
    88  const (
    89  	// A Cancel event is generated when the current gesture is
    90  	// interrupted by other handlers or the system.
    91  	Cancel Type = iota
    92  	// Press of a pointer.
    93  	Press
    94  	// Release of a pointer.
    95  	Release
    96  	// Move of a pointer.
    97  	Move
    98  )
    99  
   100  const (
   101  	// Mouse generated event.
   102  	Mouse Source = iota
   103  	// Touch generated event.
   104  	Touch
   105  )
   106  
   107  const (
   108  	// Shared priority is for handlers that
   109  	// are part of a matching set larger than 1.
   110  	Shared Priority = iota
   111  	// Grabbed is used for matching sets of size 1.
   112  	Grabbed
   113  )
   114  
   115  const (
   116  	ButtonLeft Buttons = 1 << iota
   117  	ButtonRight
   118  	ButtonMiddle
   119  )
   120  
   121  const (
   122  	areaRect areaKind = iota
   123  	areaEllipse
   124  )
   125  
   126  // Rect constructs a rectangular hit area.
   127  func Rect(size image.Rectangle) AreaOp {
   128  	return AreaOp{
   129  		kind: areaRect,
   130  		rect: size,
   131  	}
   132  }
   133  
   134  // Ellipse constructs an ellipsoid hit area.
   135  func Ellipse(size image.Rectangle) AreaOp {
   136  	return AreaOp{
   137  		kind: areaEllipse,
   138  		rect: size,
   139  	}
   140  }
   141  
   142  func (op AreaOp) Add(o *op.Ops) {
   143  	data := o.Write(opconst.TypeAreaLen)
   144  	data[0] = byte(opconst.TypeArea)
   145  	data[1] = byte(op.kind)
   146  	bo := binary.LittleEndian
   147  	bo.PutUint32(data[2:], uint32(op.rect.Min.X))
   148  	bo.PutUint32(data[6:], uint32(op.rect.Min.Y))
   149  	bo.PutUint32(data[10:], uint32(op.rect.Max.X))
   150  	bo.PutUint32(data[14:], uint32(op.rect.Max.Y))
   151  }
   152  
   153  func (h InputOp) Add(o *op.Ops) {
   154  	data := o.Write(opconst.TypePointerInputLen, h.Key)
   155  	data[0] = byte(opconst.TypePointerInput)
   156  	if h.Grab {
   157  		data[1] = 1
   158  	}
   159  }
   160  
   161  func (op PassOp) Add(o *op.Ops) {
   162  	data := o.Write(opconst.TypePassLen)
   163  	data[0] = byte(opconst.TypePass)
   164  	if op.Pass {
   165  		data[1] = 1
   166  	}
   167  }
   168  
   169  func (t Type) String() string {
   170  	switch t {
   171  	case Press:
   172  		return "Press"
   173  	case Release:
   174  		return "Release"
   175  	case Cancel:
   176  		return "Cancel"
   177  	case Move:
   178  		return "Move"
   179  	default:
   180  		panic("unknown Type")
   181  	}
   182  }
   183  
   184  func (p Priority) String() string {
   185  	switch p {
   186  	case Shared:
   187  		return "Shared"
   188  	case Grabbed:
   189  		return "Grabbed"
   190  	default:
   191  		panic("unknown priority")
   192  	}
   193  }
   194  
   195  func (s Source) String() string {
   196  	switch s {
   197  	case Mouse:
   198  		return "Mouse"
   199  	case Touch:
   200  		return "Touch"
   201  	default:
   202  		panic("unknown source")
   203  	}
   204  }
   205  
   206  // Contain reports whether the set b contains
   207  // all of the buttons.
   208  func (b Buttons) Contain(buttons Buttons) bool {
   209  	return b&buttons == buttons
   210  }
   211  
   212  func (b Buttons) String() string {
   213  	var strs []string
   214  	if b.Contain(ButtonLeft) {
   215  		strs = append(strs, "ButtonLeft")
   216  	}
   217  	if b.Contain(ButtonRight) {
   218  		strs = append(strs, "ButtonRight")
   219  	}
   220  	if b.Contain(ButtonMiddle) {
   221  		strs = append(strs, "ButtonMiddle")
   222  	}
   223  	return strings.Join(strs, "|")
   224  }
   225  
   226  func (Event) ImplementsEvent() {}