You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
6.7KB

  1. #include <event.hpp>
  2. #include <widget/Widget.hpp>
  3. #include <app.hpp>
  4. #include <window.hpp>
  5. namespace rack {
  6. namespace event {
  7. void State::setHovered(widget::Widget* w) {
  8. if (w == hoveredWidget)
  9. return;
  10. if (hoveredWidget) {
  11. // Leave
  12. Leave eLeave;
  13. hoveredWidget->onLeave(eLeave);
  14. hoveredWidget = NULL;
  15. }
  16. if (w) {
  17. // Enter
  18. Context cEnter;
  19. cEnter.target = w;
  20. Enter eEnter;
  21. eEnter.context = &cEnter;
  22. w->onEnter(eEnter);
  23. hoveredWidget = cEnter.target;
  24. }
  25. }
  26. void State::setDragged(widget::Widget* w, int button) {
  27. if (w == draggedWidget)
  28. return;
  29. if (draggedWidget) {
  30. // DragEnd
  31. DragEnd eDragEnd;
  32. eDragEnd.button = dragButton;
  33. draggedWidget->onDragEnd(eDragEnd);
  34. draggedWidget = NULL;
  35. }
  36. dragButton = button;
  37. if (w) {
  38. // DragStart
  39. Context cDragStart;
  40. cDragStart.target = w;
  41. DragStart eDragStart;
  42. eDragStart.context = &cDragStart;
  43. eDragStart.button = dragButton;
  44. w->onDragStart(eDragStart);
  45. draggedWidget = cDragStart.target;
  46. }
  47. }
  48. void State::setDragHovered(widget::Widget* w) {
  49. if (w == dragHoveredWidget)
  50. return;
  51. if (dragHoveredWidget) {
  52. // DragLeave
  53. DragLeave eDragLeave;
  54. eDragLeave.button = dragButton;
  55. eDragLeave.origin = draggedWidget;
  56. dragHoveredWidget->onDragLeave(eDragLeave);
  57. dragHoveredWidget = NULL;
  58. }
  59. if (w) {
  60. // DragEnter
  61. Context cDragEnter;
  62. cDragEnter.target = w;
  63. DragEnter eDragEnter;
  64. eDragEnter.context = &cDragEnter;
  65. eDragEnter.button = dragButton;
  66. eDragEnter.origin = draggedWidget;
  67. w->onDragEnter(eDragEnter);
  68. dragHoveredWidget = cDragEnter.target;
  69. }
  70. }
  71. void State::setSelected(widget::Widget* w) {
  72. if (w == selectedWidget)
  73. return;
  74. if (selectedWidget) {
  75. // Deselect
  76. Deselect eDeselect;
  77. selectedWidget->onDeselect(eDeselect);
  78. selectedWidget = NULL;
  79. }
  80. if (w) {
  81. // Select
  82. Context cSelect;
  83. cSelect.target = w;
  84. Select eSelect;
  85. eSelect.context = &cSelect;
  86. w->onSelect(eSelect);
  87. selectedWidget = cSelect.target;
  88. }
  89. }
  90. void State::finalizeWidget(widget::Widget* w) {
  91. if (hoveredWidget == w)
  92. setHovered(NULL);
  93. if (draggedWidget == w)
  94. setDragged(NULL, 0);
  95. if (dragHoveredWidget == w)
  96. setDragHovered(NULL);
  97. if (selectedWidget == w)
  98. setSelected(NULL);
  99. if (lastClickedWidget == w)
  100. lastClickedWidget = NULL;
  101. }
  102. bool State::handleButton(math::Vec pos, int button, int action, int mods) {
  103. // Button
  104. Context cButton;
  105. Button eButton;
  106. eButton.context = &cButton;
  107. eButton.pos = pos;
  108. eButton.button = button;
  109. eButton.action = action;
  110. eButton.mods = mods;
  111. rootWidget->onButton(eButton);
  112. widget::Widget* clickedWidget = cButton.target;
  113. if (action == GLFW_PRESS) {
  114. setDragged(clickedWidget, button);
  115. }
  116. if (action == GLFW_RELEASE) {
  117. setDragHovered(NULL);
  118. if (clickedWidget && draggedWidget) {
  119. // DragDrop
  120. DragDrop eDragDrop;
  121. eDragDrop.button = dragButton;
  122. eDragDrop.origin = draggedWidget;
  123. clickedWidget->onDragDrop(eDragDrop);
  124. }
  125. setDragged(NULL, 0);
  126. }
  127. if (button == GLFW_MOUSE_BUTTON_LEFT) {
  128. if (action == GLFW_PRESS) {
  129. setSelected(clickedWidget);
  130. }
  131. if (action == GLFW_PRESS) {
  132. const double doubleClickDuration = 0.3;
  133. double clickTime = glfwGetTime();
  134. if (clickedWidget
  135. && clickTime - lastClickTime <= doubleClickDuration
  136. && lastClickedWidget == clickedWidget) {
  137. // DoubleClick
  138. DoubleClick eDoubleClick;
  139. clickedWidget->onDoubleClick(eDoubleClick);
  140. // Reset double click
  141. lastClickTime = -INFINITY;
  142. lastClickedWidget = NULL;
  143. }
  144. else {
  145. lastClickTime = clickTime;
  146. lastClickedWidget = clickedWidget;
  147. }
  148. }
  149. }
  150. return !!clickedWidget;
  151. }
  152. bool State::handleHover(math::Vec pos, math::Vec mouseDelta) {
  153. // Fake a key RACK_HELD event for each held key
  154. int mods = APP->window->getMods();
  155. for (int key : heldKeys) {
  156. int scancode = glfwGetKeyScancode(key);
  157. handleKey(pos, key, scancode, RACK_HELD, mods);
  158. }
  159. if (draggedWidget) {
  160. // DragMove
  161. DragMove eDragMove;
  162. eDragMove.button = dragButton;
  163. eDragMove.mouseDelta = mouseDelta;
  164. draggedWidget->onDragMove(eDragMove);
  165. // DragHover
  166. Context cDragHover;
  167. DragHover eDragHover;
  168. eDragHover.context = &cDragHover;
  169. eDragHover.button = dragButton;
  170. eDragHover.pos = pos;
  171. eDragHover.mouseDelta = mouseDelta;
  172. eDragHover.origin = draggedWidget;
  173. rootWidget->onDragHover(eDragHover);
  174. setDragHovered(cDragHover.target);
  175. if (cDragHover.target)
  176. return true;
  177. }
  178. // Hover
  179. Context cHover;
  180. Hover eHover;
  181. eHover.context = &cHover;
  182. eHover.pos = pos;
  183. eHover.mouseDelta = mouseDelta;
  184. rootWidget->onHover(eHover);
  185. setHovered(cHover.target);
  186. return !!cHover.target;
  187. }
  188. bool State::handleLeave() {
  189. heldKeys.clear();
  190. setDragHovered(NULL);
  191. setHovered(NULL);
  192. return true;
  193. }
  194. bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) {
  195. // HoverScroll
  196. Context cHoverScroll;
  197. HoverScroll eHoverScroll;
  198. eHoverScroll.context = &cHoverScroll;
  199. eHoverScroll.pos = pos;
  200. eHoverScroll.scrollDelta = scrollDelta;
  201. rootWidget->onHoverScroll(eHoverScroll);
  202. return !!cHoverScroll.target;
  203. }
  204. bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) {
  205. // PathDrop
  206. Context cPathDrop;
  207. PathDrop ePathDrop(paths);
  208. ePathDrop.context = &cPathDrop;
  209. ePathDrop.pos = pos;
  210. rootWidget->onPathDrop(ePathDrop);
  211. return !!cPathDrop.target;
  212. }
  213. bool State::handleText(math::Vec pos, int codepoint) {
  214. if (selectedWidget) {
  215. // SelectText
  216. Context cSelectText;
  217. SelectText eSelectText;
  218. eSelectText.context = &cSelectText;
  219. eSelectText.codepoint = codepoint;
  220. selectedWidget->onSelectText(eSelectText);
  221. if (cSelectText.target)
  222. return true;
  223. }
  224. // HoverText
  225. Context cHoverText;
  226. HoverText eHoverText;
  227. eHoverText.context = &cHoverText;
  228. eHoverText.pos = pos;
  229. eHoverText.codepoint = codepoint;
  230. rootWidget->onHoverText(eHoverText);
  231. return !!cHoverText.target;
  232. }
  233. bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods) {
  234. // Update heldKey state
  235. if (action == GLFW_PRESS) {
  236. heldKeys.insert(key);
  237. }
  238. else if (action == GLFW_RELEASE) {
  239. auto it = heldKeys.find(key);
  240. if (it != heldKeys.end())
  241. heldKeys.erase(it);
  242. }
  243. if (selectedWidget) {
  244. // SelectKey
  245. Context cSelectKey;
  246. SelectKey eSelectKey;
  247. eSelectKey.context = &cSelectKey;
  248. eSelectKey.key = key;
  249. eSelectKey.scancode = scancode;
  250. eSelectKey.action = action;
  251. eSelectKey.mods = mods;
  252. selectedWidget->onSelectKey(eSelectKey);
  253. if (cSelectKey.target)
  254. return true;
  255. }
  256. // HoverKey
  257. Context cHoverKey;
  258. HoverKey eHoverKey;
  259. eHoverKey.context = &cHoverKey;
  260. eHoverKey.pos = pos;
  261. eHoverKey.key = key;
  262. eHoverKey.scancode = scancode;
  263. eHoverKey.action = action;
  264. eHoverKey.mods = mods;
  265. rootWidget->onHoverKey(eHoverKey);
  266. return !!cHoverKey.target;
  267. }
  268. bool State::handleZoom() {
  269. // Zoom
  270. Context cZoom;
  271. Zoom eZoom;
  272. eZoom.context = &cZoom;
  273. rootWidget->onZoom(eZoom);
  274. return true;
  275. }
  276. } // namespace event
  277. } // namespace rack