main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package mouse_demo
  3. import (
  4. "fmt"
  5. "strconv"
  6. "kitty/tools/tui/loop"
  7. )
  8. var _ = fmt.Print
  9. func Run(args []string) (rc int, err error) {
  10. all_pointer_shapes := []loop.PointerShape{
  11. // start all pointer shapes (auto generated by gen-key-constants.py do not edit)
  12. loop.DEFAULT_POINTER,
  13. loop.TEXT_POINTER,
  14. loop.POINTER_POINTER,
  15. loop.HELP_POINTER,
  16. loop.WAIT_POINTER,
  17. loop.PROGRESS_POINTER,
  18. loop.CROSSHAIR_POINTER,
  19. loop.CELL_POINTER,
  20. loop.VERTICAL_TEXT_POINTER,
  21. loop.MOVE_POINTER,
  22. loop.E_RESIZE_POINTER,
  23. loop.NE_RESIZE_POINTER,
  24. loop.NW_RESIZE_POINTER,
  25. loop.N_RESIZE_POINTER,
  26. loop.SE_RESIZE_POINTER,
  27. loop.SW_RESIZE_POINTER,
  28. loop.S_RESIZE_POINTER,
  29. loop.W_RESIZE_POINTER,
  30. loop.EW_RESIZE_POINTER,
  31. loop.NS_RESIZE_POINTER,
  32. loop.NESW_RESIZE_POINTER,
  33. loop.NWSE_RESIZE_POINTER,
  34. loop.ZOOM_IN_POINTER,
  35. loop.ZOOM_OUT_POINTER,
  36. loop.ALIAS_POINTER,
  37. loop.COPY_POINTER,
  38. loop.NOT_ALLOWED_POINTER,
  39. loop.NO_DROP_POINTER,
  40. loop.GRAB_POINTER,
  41. loop.GRABBING_POINTER,
  42. // end all pointer shapes
  43. }
  44. all_pointer_shape_names := make([]string, len(all_pointer_shapes))
  45. col_width := 0
  46. for i, p := range all_pointer_shapes {
  47. all_pointer_shape_names[i] = p.String()
  48. col_width = max(col_width, len(all_pointer_shape_names[i]))
  49. }
  50. col_width += 1
  51. lp, err := loop.New()
  52. if err != nil {
  53. return 1, err
  54. }
  55. lp.MouseTrackingMode(loop.FULL_MOUSE_TRACKING)
  56. var current_mouse_event *loop.MouseEvent
  57. draw_screen := func() {
  58. lp.StartAtomicUpdate()
  59. defer lp.EndAtomicUpdate()
  60. lp.AllowLineWrapping(false)
  61. defer lp.AllowLineWrapping(true)
  62. if current_mouse_event == nil {
  63. lp.ClearScreen()
  64. lp.Println(`Move the mouse or click to see mouse events`)
  65. return
  66. }
  67. lp.ClearScreen()
  68. lp.Printf("Position: %d, %d (pixels)\r\n", current_mouse_event.Pixel.X, current_mouse_event.Pixel.Y)
  69. lp.Printf("Cell : %d, %d\r\n", current_mouse_event.Cell.X, current_mouse_event.Cell.Y)
  70. lp.Printf("Type : %s\r\n", current_mouse_event.Event_type)
  71. y := 3
  72. if current_mouse_event.Buttons != loop.NO_MOUSE_BUTTON {
  73. lp.Println(current_mouse_event.Buttons.String())
  74. y += 1
  75. }
  76. if mods := current_mouse_event.Mods.String(); mods != "" {
  77. lp.Printf("Modifiers: %s\r\n", mods)
  78. y += 1
  79. }
  80. lp.Println("Hover the mouse over the names below to see the shapes")
  81. y += 1
  82. sw := 80
  83. sh := 24
  84. if s, err := lp.ScreenSize(); err == nil {
  85. sw = int(s.WidthCells)
  86. sh = int(s.HeightCells)
  87. }
  88. num_cols := max(1, sw/col_width)
  89. pos := 0
  90. colfmt := "%-" + strconv.Itoa(col_width) + "s"
  91. is_on_name := false
  92. var ps loop.PointerShape
  93. for y < sh && pos < len(all_pointer_shapes) {
  94. is_row := y == current_mouse_event.Cell.Y
  95. for c := 0; c < num_cols && pos < len(all_pointer_shapes); c++ {
  96. name := all_pointer_shape_names[pos]
  97. is_hovered := false
  98. if is_row {
  99. start_x := c * col_width
  100. x := current_mouse_event.Cell.X
  101. if x < start_x+len(name) && x >= start_x {
  102. is_on_name = true
  103. is_hovered = true
  104. ps = all_pointer_shapes[pos]
  105. }
  106. }
  107. if is_hovered {
  108. lp.QueueWriteString("\x1b[31m")
  109. }
  110. lp.Printf(colfmt, name)
  111. lp.QueueWriteString("\x1b[m")
  112. pos++
  113. }
  114. y += 1
  115. lp.Println()
  116. }
  117. lp.PopPointerShape()
  118. if is_on_name {
  119. lp.PushPointerShape(ps)
  120. }
  121. }
  122. lp.OnInitialize = func() (string, error) {
  123. lp.SetWindowTitle("kitty mouse features demo")
  124. lp.SetCursorVisible(false)
  125. draw_screen()
  126. return "", nil
  127. }
  128. lp.OnFinalize = func() string {
  129. lp.SetCursorVisible(true)
  130. return ""
  131. }
  132. lp.OnMouseEvent = func(ev *loop.MouseEvent) error {
  133. current_mouse_event = ev
  134. draw_screen()
  135. return nil
  136. }
  137. lp.OnKeyEvent = func(ev *loop.KeyEvent) error {
  138. if ev.MatchesPressOrRepeat("esc") || ev.MatchesPressOrRepeat("ctrl+c") {
  139. lp.Quit(0)
  140. }
  141. return nil
  142. }
  143. lp.OnResize = func(old_size loop.ScreenSize, new_size loop.ScreenSize) error {
  144. draw_screen()
  145. return nil
  146. }
  147. err = lp.Run()
  148. if err != nil {
  149. rc = 1
  150. }
  151. return
  152. }