gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/io/pointer/pointer.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package pointer 4 5 import ( 6 "strings" 7 "time" 8 9 "gioui.org/f32" 10 "gioui.org/internal/ops" 11 "gioui.org/io/event" 12 "gioui.org/io/key" 13 "gioui.org/op" 14 ) 15 16 // Event is a pointer event. 17 type Event struct { 18 Kind Kind 19 Source Source 20 // PointerID is the id for the pointer and can be used 21 // to track a particular pointer from Press to 22 // Release or Cancel. 23 PointerID ID 24 // Priority is the priority of the receiving handler 25 // for this event. 26 Priority Priority 27 // Time is when the event was received. The 28 // timestamp is relative to an undefined base. 29 Time time.Duration 30 // Buttons are the set of pressed mouse buttons for this event. 31 Buttons Buttons 32 // Position is the coordinates of the event in the local coordinate 33 // system of the receiving tag. The transformation from global window 34 // coordinates to local coordinates is performed by the inverse of 35 // the effective transformation of the tag. 36 Position f32.Point 37 // Scroll is the scroll amount, if any. 38 Scroll f32.Point 39 // Modifiers is the set of active modifiers when 40 // the mouse button was pressed. 41 Modifiers key.Modifiers 42 } 43 44 // PassOp sets the pass-through mode. InputOps added while the pass-through 45 // mode is set don't block events to siblings. 46 type PassOp struct { 47 } 48 49 // PassStack represents a PassOp on the pass stack. 50 type PassStack struct { 51 ops *ops.Ops 52 id ops.StackID 53 macroID uint32 54 } 55 56 // Filter matches every [Event] that target the Tag and whose kind is 57 // included in Kinds. Note that only tags specified in [event.Op] can 58 // be targeted by pointer events. 59 type Filter struct { 60 Target event.Tag 61 // Kinds is a bitwise-or of event types to match. 62 Kinds Kind 63 // ScrollX and ScrollY constrain the range of scrolling events delivered 64 // to Target. Specifically, any Event e delivered to Tag will satisfy 65 // 66 // ScrollX.Min <= e.Scroll.X <= ScrollX.Max (horizontal axis) 67 // ScrollY.Min <= e.Scroll.Y <= ScrollY.Max (vertical axis) 68 ScrollX ScrollRange 69 ScrollY ScrollRange 70 } 71 72 // ScrollRange describes the range of scrolling distances in an 73 // axis. 74 type ScrollRange struct { 75 Min, Max int 76 } 77 78 // GrabCmd requests a pointer grab on the pointer identified by ID. 79 type GrabCmd struct { 80 Tag event.Tag 81 ID ID 82 } 83 84 type ID uint16 85 86 // Kind of an Event. 87 type Kind uint 88 89 // Priority of an Event. 90 type Priority uint8 91 92 // Source of an Event. 93 type Source uint8 94 95 // Buttons is a set of mouse buttons 96 type Buttons uint8 97 98 // Cursor denotes a pre-defined cursor shape. Its Add method adds an 99 // operation that sets the cursor shape for the current clip area. 100 type Cursor byte 101 102 // The cursors correspond to CSS pointer naming. 103 const ( 104 // CursorDefault is the default cursor. 105 CursorDefault Cursor = iota 106 // CursorNone hides the cursor. To show it again, use any other cursor. 107 CursorNone 108 // CursorText is for selecting and inserting text. 109 CursorText 110 // CursorVerticalText is for selecting and inserting vertical text. 111 CursorVerticalText 112 // CursorPointer is for a link. 113 // Usually displayed as a pointing hand. 114 CursorPointer 115 // CursorCrosshair is for a precise location. 116 CursorCrosshair 117 // CursorAllScroll is for indicating scrolling in all directions. 118 // Usually displayed as arrows to all four directions. 119 CursorAllScroll 120 // CursorColResize is for vertical resize. 121 // Usually displayed as a vertical bar with arrows pointing east and west. 122 CursorColResize 123 // CursorRowResize is for horizontal resize. 124 // Usually displayed as a horizontal bar with arrows pointing north and south. 125 CursorRowResize 126 // CursorGrab is for content that can be grabbed (dragged to be moved). 127 // Usually displayed as an open hand. 128 CursorGrab 129 // CursorGrabbing is for content that is being grabbed (dragged to be moved). 130 // Usually displayed as a closed hand. 131 CursorGrabbing 132 // CursorNotAllowed is shown when the request action cannot be carried out. 133 // Usually displayed as a circle with a line through. 134 CursorNotAllowed 135 // CursorWait is shown when the program is busy and user cannot interact. 136 // Usually displayed as a hourglass or the system equivalent. 137 CursorWait 138 // CursorProgress is shown when the program is busy, but the user can still interact. 139 // Usually displayed as a default cursor with a hourglass. 140 CursorProgress 141 // CursorNorthWestResize is for top-left corner resizing. 142 // Usually displayed as an arrow towards north-west. 143 CursorNorthWestResize 144 // CursorNorthEastResize is for top-right corner resizing. 145 // Usually displayed as an arrow towards north-east. 146 CursorNorthEastResize 147 // CursorSouthWestResize is for bottom-left corner resizing. 148 // Usually displayed as an arrow towards south-west. 149 CursorSouthWestResize 150 // CursorSouthEastResize is for bottom-right corner resizing. 151 // Usually displayed as an arrow towards south-east. 152 CursorSouthEastResize 153 // CursorNorthSouth is for top-bottom resizing. 154 // Usually displayed as a bi-directional arrow towards north-south. 155 CursorNorthSouthResize 156 // CursorEastWestResize is for left-right resizing. 157 // Usually displayed as a bi-directional arrow towards east-west. 158 CursorEastWestResize 159 // CursorWestResize is for left resizing. 160 // Usually displayed as an arrow towards west. 161 CursorWestResize 162 // CursorEastResize is for right resizing. 163 // Usually displayed as an arrow towards east. 164 CursorEastResize 165 // CursorNorthResize is for top resizing. 166 // Usually displayed as an arrow towards north. 167 CursorNorthResize 168 // CursorSouthResize is for bottom resizing. 169 // Usually displayed as an arrow towards south. 170 CursorSouthResize 171 // CursorNorthEastSouthWestResize is for top-right to bottom-left diagonal resizing. 172 // Usually displayed as a double ended arrow on the corresponding diagonal. 173 CursorNorthEastSouthWestResize 174 // CursorNorthWestSouthEastResize is for top-left to bottom-right diagonal resizing. 175 // Usually displayed as a double ended arrow on the corresponding diagonal. 176 CursorNorthWestSouthEastResize 177 ) 178 179 const ( 180 // A Cancel event is generated when the current gesture is 181 // interrupted by other handlers or the system. 182 Cancel Kind = 1 << iota 183 // Press of a pointer. 184 Press 185 // Release of a pointer. 186 Release 187 // Move of a pointer. 188 Move 189 // Drag of a pointer. 190 Drag 191 // Pointer enters an area watching for pointer input 192 Enter 193 // Pointer leaves an area watching for pointer input 194 Leave 195 // Scroll of a pointer. 196 Scroll 197 ) 198 199 const ( 200 // Mouse generated event. 201 Mouse Source = iota 202 // Touch generated event. 203 Touch 204 ) 205 206 const ( 207 // Shared priority is for handlers that 208 // are part of a matching set larger than 1. 209 Shared Priority = iota 210 // Foremost priority is like Shared, but the 211 // handler is the foremost of the matching set. 212 Foremost 213 // Grabbed is used for matching sets of size 1. 214 Grabbed 215 ) 216 217 const ( 218 // ButtonPrimary is the primary button, usually the left button for a 219 // right-handed user. 220 ButtonPrimary Buttons = 1 << iota 221 // ButtonSecondary is the secondary button, usually the right button for a 222 // right-handed user. 223 ButtonSecondary 224 // ButtonTertiary is the tertiary button, usually the middle button. 225 ButtonTertiary 226 ) 227 228 func (s ScrollRange) Union(s2 ScrollRange) ScrollRange { 229 return ScrollRange{ 230 Min: min(s.Min, s2.Min), 231 Max: max(s.Max, s2.Max), 232 } 233 } 234 235 // Push the current pass mode to the pass stack and set the pass mode. 236 func (p PassOp) Push(o *op.Ops) PassStack { 237 id, mid := ops.PushOp(&o.Internal, ops.PassStack) 238 data := ops.Write(&o.Internal, ops.TypePassLen) 239 data[0] = byte(ops.TypePass) 240 return PassStack{ops: &o.Internal, id: id, macroID: mid} 241 } 242 243 func (p PassStack) Pop() { 244 ops.PopOp(p.ops, ops.PassStack, p.id, p.macroID) 245 data := ops.Write(p.ops, ops.TypePopPassLen) 246 data[0] = byte(ops.TypePopPass) 247 } 248 249 func (op Cursor) Add(o *op.Ops) { 250 data := ops.Write(&o.Internal, ops.TypeCursorLen) 251 data[0] = byte(ops.TypeCursor) 252 data[1] = byte(op) 253 } 254 255 func (t Kind) String() string { 256 if t == Cancel { 257 return "Cancel" 258 } 259 var buf strings.Builder 260 for tt := Kind(1); tt > 0; tt <<= 1 { 261 if t&tt > 0 { 262 if buf.Len() > 0 { 263 buf.WriteByte('|') 264 } 265 buf.WriteString((t & tt).string()) 266 } 267 } 268 return buf.String() 269 } 270 271 func (t Kind) string() string { 272 switch t { 273 case Press: 274 return "Press" 275 case Release: 276 return "Release" 277 case Cancel: 278 return "Cancel" 279 case Move: 280 return "Move" 281 case Drag: 282 return "Drag" 283 case Enter: 284 return "Enter" 285 case Leave: 286 return "Leave" 287 case Scroll: 288 return "Scroll" 289 default: 290 panic("unknown Type") 291 } 292 } 293 294 func (p Priority) String() string { 295 switch p { 296 case Shared: 297 return "Shared" 298 case Foremost: 299 return "Foremost" 300 case Grabbed: 301 return "Grabbed" 302 default: 303 panic("unknown priority") 304 } 305 } 306 307 func (s Source) String() string { 308 switch s { 309 case Mouse: 310 return "Mouse" 311 case Touch: 312 return "Touch" 313 default: 314 panic("unknown source") 315 } 316 } 317 318 // Contain reports whether the set b contains 319 // all of the buttons. 320 func (b Buttons) Contain(buttons Buttons) bool { 321 return b&buttons == buttons 322 } 323 324 func (b Buttons) String() string { 325 var strs []string 326 if b.Contain(ButtonPrimary) { 327 strs = append(strs, "ButtonPrimary") 328 } 329 if b.Contain(ButtonSecondary) { 330 strs = append(strs, "ButtonSecondary") 331 } 332 if b.Contain(ButtonTertiary) { 333 strs = append(strs, "ButtonTertiary") 334 } 335 return strings.Join(strs, "|") 336 } 337 338 func (c Cursor) String() string { 339 switch c { 340 case CursorDefault: 341 return "Default" 342 case CursorNone: 343 return "None" 344 case CursorText: 345 return "Text" 346 case CursorVerticalText: 347 return "VerticalText" 348 case CursorPointer: 349 return "Pointer" 350 case CursorCrosshair: 351 return "Crosshair" 352 case CursorAllScroll: 353 return "AllScroll" 354 case CursorColResize: 355 return "ColResize" 356 case CursorRowResize: 357 return "RowResize" 358 case CursorGrab: 359 return "Grab" 360 case CursorGrabbing: 361 return "Grabbing" 362 case CursorNotAllowed: 363 return "NotAllowed" 364 case CursorWait: 365 return "Wait" 366 case CursorProgress: 367 return "Progress" 368 case CursorNorthWestResize: 369 return "NorthWestResize" 370 case CursorNorthEastResize: 371 return "NorthEastResize" 372 case CursorSouthWestResize: 373 return "SouthWestResize" 374 case CursorSouthEastResize: 375 return "SouthEastResize" 376 case CursorNorthSouthResize: 377 return "NorthSouthResize" 378 case CursorEastWestResize: 379 return "EastWestResize" 380 case CursorWestResize: 381 return "WestResize" 382 case CursorEastResize: 383 return "EastResize" 384 case CursorNorthResize: 385 return "NorthResize" 386 case CursorSouthResize: 387 return "SouthResize" 388 case CursorNorthEastSouthWestResize: 389 return "NorthEastSouthWestResize" 390 case CursorNorthWestSouthEastResize: 391 return "NorthWestSouthEastResize" 392 default: 393 panic("unknown Type") 394 } 395 } 396 397 func (Event) ImplementsEvent() {} 398 399 func (GrabCmd) ImplementsCommand() {} 400 401 func (Filter) ImplementsFilter() {}