github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/io/key/key.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 /* 4 Package key implements key and text events and operations. 5 6 The InputOp operations is used for declaring key input handlers. Use 7 an implementation of the Queue interface from package ui to receive 8 events. 9 */ 10 package key 11 12 import ( 13 "fmt" 14 "strings" 15 16 "github.com/cybriq/giocore/internal/opconst" 17 "github.com/cybriq/giocore/io/event" 18 "github.com/cybriq/giocore/op" 19 ) 20 21 // InputOp declares a handler ready for key events. 22 // Key events are in general only delivered to the 23 // focused key handler. 24 type InputOp struct { 25 Tag event.Tag 26 Hint InputHint 27 } 28 29 // SoftKeyboardOp shows or hide the on-screen keyboard, if available. 30 // It replaces any previous SoftKeyboardOp. 31 type SoftKeyboardOp struct { 32 Show bool 33 } 34 35 // FocusOp sets or clears the keyboard focus. It replaces any previous 36 // FocusOp in the same frame. 37 type FocusOp struct { 38 // Tag is the new focus. The focus is cleared if Tag is nil, or if Tag 39 // has no InputOp in the same frame. 40 Tag event.Tag 41 } 42 43 // A FocusEvent is generated when a handler gains or loses 44 // focus. 45 type FocusEvent struct { 46 Focus bool 47 } 48 49 // An Event is generated when a key is pressed. For text input 50 // use EditEvent. 51 type Event struct { 52 // Name of the key. For letters, the upper case form is used, via 53 // unicode.ToUpper. The shift modifier is taken into account, all other 54 // modifiers are ignored. For example, the "shift-1" and "ctrl-shift-1" 55 // combinations both give the Name "!" with the US keyboard layout. 56 Name string 57 // Modifiers is the set of active modifiers when the key was pressed. 58 Modifiers Modifiers 59 // State is the state of the key when the event was fired. 60 State State 61 } 62 63 // An EditEvent is generated when text is input. 64 type EditEvent struct { 65 Text string 66 } 67 68 // InputHint changes the on-screen-keyboard type. That hints the 69 // type of data that might be entered by the user. 70 type InputHint uint8 71 72 const ( 73 // HintAny hints that any input is expected. 74 HintAny InputHint = iota 75 // HintText hints that text input is expected. It may activate auto-correction and suggestions. 76 HintText 77 // HintNumeric hints that numeric input is expected. It may activate shortcuts for 0-9, "." and ",". 78 HintNumeric 79 // HintEmail hints that email input is expected. It may activate shortcuts for common email characters, such as "@" and ".com". 80 HintEmail 81 // HintURL hints that URL input is expected. It may activate shortcuts for common URL fragments such as "/" and ".com". 82 HintURL 83 // HintTelephone hints that telephone number input is expected. It may activate shortcuts for 0-9, "#" and "*". 84 HintTelephone 85 ) 86 87 // State is the state of a key during an event. 88 type State uint8 89 90 const ( 91 // Press is the state of a pressed key. 92 Press State = iota 93 // Release is the state of a key that has been released. 94 // 95 // Note: release events are only implemented on the following platforms: 96 // macOS, Linux, Windows, WebAssembly. 97 Release 98 ) 99 100 // Modifiers 101 type Modifiers uint32 102 103 const ( 104 // ModCtrl is the ctrl modifier key. 105 ModCtrl Modifiers = 1 << iota 106 // ModCommand is the command modifier key 107 // found on Apple keyboards. 108 ModCommand 109 // ModShift is the shift modifier key. 110 ModShift 111 // ModAlt is the alt modifier key, or the option 112 // key on Apple keyboards. 113 ModAlt 114 // ModSuper is the "logo" modifier key, often 115 // represented by a Windows logo. 116 ModSuper 117 ) 118 119 const ( 120 // Names for special keys. 121 NameLeftArrow = "←" 122 NameRightArrow = "→" 123 NameUpArrow = "↑" 124 NameDownArrow = "↓" 125 NameReturn = "⏎" 126 NameEnter = "⌤" 127 NameEscape = "⎋" 128 NameHome = "⇱" 129 NameEnd = "⇲" 130 NameDeleteBackward = "⌫" 131 NameDeleteForward = "⌦" 132 NamePageUp = "⇞" 133 NamePageDown = "⇟" 134 NameTab = "⇥" 135 NameSpace = "Space" 136 ) 137 138 // Contain reports whether m contains all modifiers 139 // in m2. 140 func (m Modifiers) Contain(m2 Modifiers) bool { 141 return m&m2 == m2 142 } 143 144 func (h InputOp) Add(o *op.Ops) { 145 if h.Tag == nil { 146 panic("Tag must be non-nil") 147 } 148 data := o.Write1(opconst.TypeKeyInputLen, h.Tag) 149 data[0] = byte(opconst.TypeKeyInput) 150 data[1] = byte(h.Hint) 151 } 152 153 func (h SoftKeyboardOp) Add(o *op.Ops) { 154 data := o.Write(opconst.TypeKeySoftKeyboardLen) 155 data[0] = byte(opconst.TypeKeySoftKeyboard) 156 if h.Show { 157 data[1] = 1 158 } 159 } 160 161 func (h FocusOp) Add(o *op.Ops) { 162 data := o.Write1(opconst.TypeKeyFocusLen, h.Tag) 163 data[0] = byte(opconst.TypeKeyFocus) 164 } 165 166 func (EditEvent) ImplementsEvent() {} 167 func (Event) ImplementsEvent() {} 168 func (FocusEvent) ImplementsEvent() {} 169 170 func (e Event) String() string { 171 return fmt.Sprintf("%v %v %v}", e.Name, e.Modifiers, e.State) 172 } 173 174 func (m Modifiers) String() string { 175 var strs []string 176 if m.Contain(ModCtrl) { 177 strs = append(strs, "ModCtrl") 178 } 179 if m.Contain(ModCommand) { 180 strs = append(strs, "ModCommand") 181 } 182 if m.Contain(ModShift) { 183 strs = append(strs, "ModShift") 184 } 185 if m.Contain(ModAlt) { 186 strs = append(strs, "ModAlt") 187 } 188 if m.Contain(ModSuper) { 189 strs = append(strs, "ModSuper") 190 } 191 return strings.Join(strs, "|") 192 } 193 194 func (s State) String() string { 195 switch s { 196 case Press: 197 return "Press" 198 case Release: 199 return "Release" 200 default: 201 panic("invalid State") 202 } 203 }