mouse.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package ansi
  2. import (
  3. "fmt"
  4. )
  5. // MouseButton represents the button that was pressed during a mouse message.
  6. type MouseButton byte
  7. // Mouse event buttons
  8. //
  9. // This is based on X11 mouse button codes.
  10. //
  11. // 1 = left button
  12. // 2 = middle button (pressing the scroll wheel)
  13. // 3 = right button
  14. // 4 = turn scroll wheel up
  15. // 5 = turn scroll wheel down
  16. // 6 = push scroll wheel left
  17. // 7 = push scroll wheel right
  18. // 8 = 4th button (aka browser backward button)
  19. // 9 = 5th button (aka browser forward button)
  20. // 10
  21. // 11
  22. //
  23. // Other buttons are not supported.
  24. const (
  25. MouseNone MouseButton = iota
  26. MouseLeft
  27. MouseMiddle
  28. MouseRight
  29. MouseWheelUp
  30. MouseWheelDown
  31. MouseWheelLeft
  32. MouseWheelRight
  33. MouseBackward
  34. MouseForward
  35. MouseButton10
  36. MouseButton11
  37. MouseRelease = MouseNone
  38. )
  39. var mouseButtons = map[MouseButton]string{
  40. MouseNone: "none",
  41. MouseLeft: "left",
  42. MouseMiddle: "middle",
  43. MouseRight: "right",
  44. MouseWheelUp: "wheelup",
  45. MouseWheelDown: "wheeldown",
  46. MouseWheelLeft: "wheelleft",
  47. MouseWheelRight: "wheelright",
  48. MouseBackward: "backward",
  49. MouseForward: "forward",
  50. MouseButton10: "button10",
  51. MouseButton11: "button11",
  52. }
  53. // String returns a string representation of the mouse button.
  54. func (b MouseButton) String() string {
  55. return mouseButtons[b]
  56. }
  57. // Button returns a byte representing a mouse button.
  58. // The button is a bitmask of the following leftmost values:
  59. //
  60. // - The first two bits are the button number:
  61. // 0 = left button, wheel up, or button no. 8 aka (backwards)
  62. // 1 = middle button, wheel down, or button no. 9 aka (forwards)
  63. // 2 = right button, wheel left, or button no. 10
  64. // 3 = release event, wheel right, or button no. 11
  65. //
  66. // - The third bit indicates whether the shift key was pressed.
  67. //
  68. // - The fourth bit indicates the alt key was pressed.
  69. //
  70. // - The fifth bit indicates the control key was pressed.
  71. //
  72. // - The sixth bit indicates motion events. Combined with button number 3, i.e.
  73. // release event, it represents a drag event.
  74. //
  75. // - The seventh bit indicates a wheel event.
  76. //
  77. // - The eighth bit indicates additional buttons.
  78. //
  79. // If button is [MouseNone], and motion is false, this returns a release event.
  80. // If button is undefined, this function returns 0xff.
  81. func (b MouseButton) Button(motion, shift, alt, ctrl bool) (m byte) {
  82. // mouse bit shifts
  83. const (
  84. bitShift = 0b0000_0100
  85. bitAlt = 0b0000_1000
  86. bitCtrl = 0b0001_0000
  87. bitMotion = 0b0010_0000
  88. bitWheel = 0b0100_0000
  89. bitAdd = 0b1000_0000 // additional buttons 8-11
  90. bitsMask = 0b0000_0011
  91. )
  92. if b == MouseNone {
  93. m = bitsMask
  94. } else if b >= MouseLeft && b <= MouseRight {
  95. m = byte(b - MouseLeft)
  96. } else if b >= MouseWheelUp && b <= MouseWheelRight {
  97. m = byte(b - MouseWheelUp)
  98. m |= bitWheel
  99. } else if b >= MouseBackward && b <= MouseButton11 {
  100. m = byte(b - MouseBackward)
  101. m |= bitAdd
  102. } else {
  103. m = 0xff // invalid button
  104. }
  105. if shift {
  106. m |= bitShift
  107. }
  108. if alt {
  109. m |= bitAlt
  110. }
  111. if ctrl {
  112. m |= bitCtrl
  113. }
  114. if motion {
  115. m |= bitMotion
  116. }
  117. return
  118. }
  119. // x10Offset is the offset for X10 mouse events.
  120. // See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
  121. const x10Offset = 32
  122. // MouseX10 returns an escape sequence representing a mouse event in X10 mode.
  123. // Note that this requires the terminal support X10 mouse modes.
  124. //
  125. // CSI M Cb Cx Cy
  126. //
  127. // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
  128. func MouseX10(b byte, x, y int) string {
  129. return "\x1b[M" + string(b+x10Offset) + string(byte(x)+x10Offset+1) + string(byte(y)+x10Offset+1)
  130. }
  131. // MouseSgr returns an escape sequence representing a mouse event in SGR mode.
  132. //
  133. // CSI < Cb ; Cx ; Cy M
  134. // CSI < Cb ; Cx ; Cy m (release)
  135. //
  136. // See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking
  137. func MouseSgr(b byte, x, y int, release bool) string {
  138. s := 'M'
  139. if release {
  140. s = 'm'
  141. }
  142. if x < 0 {
  143. x = -x
  144. }
  145. if y < 0 {
  146. y = -y
  147. }
  148. return fmt.Sprintf("\x1b[<%d;%d;%d%c", b, x+1, y+1, s)
  149. }