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.

349 lines
7.7KB

  1. #include <event.hpp>
  2. #include <widget/Widget.hpp>
  3. #include <context.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. // Trigger Leave event
  12. Leave eLeave;
  13. hoveredWidget->onLeave(eLeave);
  14. hoveredWidget = NULL;
  15. }
  16. if (w) {
  17. // Trigger Enter event
  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. // Trigger DragEnd event
  31. DragEnd eDragEnd;
  32. eDragEnd.button = dragButton;
  33. draggedWidget->onDragEnd(eDragEnd);
  34. draggedWidget = NULL;
  35. }
  36. dragButton = button;
  37. if (w) {
  38. // Trigger DragStart event
  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. // Trigger DragLeave event
  53. DragLeave eDragLeave;
  54. eDragLeave.button = dragButton;
  55. eDragLeave.origin = draggedWidget;
  56. dragHoveredWidget->onDragLeave(eDragLeave);
  57. dragHoveredWidget = NULL;
  58. }
  59. if (w) {
  60. // Trigger DragEnter event
  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. // Trigger Deselect event
  76. Deselect eDeselect;
  77. selectedWidget->onDeselect(eDeselect);
  78. selectedWidget = NULL;
  79. }
  80. if (w) {
  81. // Trigger Select event
  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. bool cursorLocked = APP->window->isCursorLocked();
  104. widget::Widget* clickedWidget = NULL;
  105. if (!cursorLocked) {
  106. // Trigger Button event
  107. Context cButton;
  108. Button eButton;
  109. eButton.context = &cButton;
  110. eButton.pos = pos;
  111. eButton.button = button;
  112. eButton.action = action;
  113. eButton.mods = mods;
  114. rootWidget->onButton(eButton);
  115. clickedWidget = cButton.target;
  116. }
  117. if (action == GLFW_PRESS) {
  118. setDragged(clickedWidget, button);
  119. }
  120. if (action == GLFW_RELEASE) {
  121. setDragHovered(NULL);
  122. if (clickedWidget && draggedWidget) {
  123. // Trigger DragDrop event
  124. DragDrop eDragDrop;
  125. eDragDrop.button = dragButton;
  126. eDragDrop.origin = draggedWidget;
  127. clickedWidget->onDragDrop(eDragDrop);
  128. }
  129. setDragged(NULL, 0);
  130. }
  131. if (button == GLFW_MOUSE_BUTTON_LEFT) {
  132. if (action == GLFW_PRESS) {
  133. setSelected(clickedWidget);
  134. }
  135. if (action == GLFW_PRESS) {
  136. const double doubleClickDuration = 0.3;
  137. double clickTime = glfwGetTime();
  138. if (clickedWidget
  139. && clickTime - lastClickTime <= doubleClickDuration
  140. && lastClickedWidget == clickedWidget) {
  141. // Trigger DoubleClick event
  142. DoubleClick eDoubleClick;
  143. clickedWidget->onDoubleClick(eDoubleClick);
  144. // Reset double click
  145. lastClickTime = -INFINITY;
  146. lastClickedWidget = NULL;
  147. }
  148. else {
  149. lastClickTime = clickTime;
  150. lastClickedWidget = clickedWidget;
  151. }
  152. }
  153. }
  154. return !!clickedWidget;
  155. }
  156. bool State::handleHover(math::Vec pos, math::Vec mouseDelta) {
  157. bool cursorLocked = APP->window->isCursorLocked();
  158. // Fake a key RACK_HELD event for each held key
  159. if (!cursorLocked) {
  160. int mods = APP->window->getMods();
  161. for (int key : heldKeys) {
  162. int scancode = glfwGetKeyScancode(key);
  163. handleKey(pos, key, scancode, RACK_HELD, mods);
  164. }
  165. }
  166. if (draggedWidget) {
  167. bool dragHovered = false;
  168. if (!cursorLocked) {
  169. // Trigger DragHover event
  170. Context cDragHover;
  171. DragHover eDragHover;
  172. eDragHover.context = &cDragHover;
  173. eDragHover.button = dragButton;
  174. eDragHover.pos = pos;
  175. eDragHover.mouseDelta = mouseDelta;
  176. eDragHover.origin = draggedWidget;
  177. rootWidget->onDragHover(eDragHover);
  178. setDragHovered(cDragHover.target);
  179. // If consumed, don't continue after DragMove so Hover is not triggered.
  180. if (cDragHover.target)
  181. dragHovered = true;
  182. }
  183. // Trigger DragMove event
  184. DragMove eDragMove;
  185. eDragMove.button = dragButton;
  186. eDragMove.mouseDelta = mouseDelta;
  187. draggedWidget->onDragMove(eDragMove);
  188. if (dragHovered)
  189. return true;
  190. }
  191. if (!cursorLocked) {
  192. // Trigger Hover event
  193. Context cHover;
  194. Hover eHover;
  195. eHover.context = &cHover;
  196. eHover.pos = pos;
  197. eHover.mouseDelta = mouseDelta;
  198. rootWidget->onHover(eHover);
  199. setHovered(cHover.target);
  200. if (cHover.target)
  201. return true;
  202. }
  203. return false;
  204. }
  205. bool State::handleLeave() {
  206. heldKeys.clear();
  207. // When leaving the window, don't un-hover widgets because the mouse might be dragging.
  208. // setDragHovered(NULL);
  209. // setHovered(NULL);
  210. return true;
  211. }
  212. bool State::handleScroll(math::Vec pos, math::Vec scrollDelta) {
  213. // Trigger HoverScroll event
  214. Context cHoverScroll;
  215. HoverScroll eHoverScroll;
  216. eHoverScroll.context = &cHoverScroll;
  217. eHoverScroll.pos = pos;
  218. eHoverScroll.scrollDelta = scrollDelta;
  219. rootWidget->onHoverScroll(eHoverScroll);
  220. return !!cHoverScroll.target;
  221. }
  222. bool State::handleDrop(math::Vec pos, const std::vector<std::string>& paths) {
  223. // Trigger PathDrop event
  224. Context cPathDrop;
  225. PathDrop ePathDrop(paths);
  226. ePathDrop.context = &cPathDrop;
  227. ePathDrop.pos = pos;
  228. rootWidget->onPathDrop(ePathDrop);
  229. return !!cPathDrop.target;
  230. }
  231. bool State::handleText(math::Vec pos, int codepoint) {
  232. if (selectedWidget) {
  233. // Trigger SelectText event
  234. Context cSelectText;
  235. SelectText eSelectText;
  236. eSelectText.context = &cSelectText;
  237. eSelectText.codepoint = codepoint;
  238. selectedWidget->onSelectText(eSelectText);
  239. if (cSelectText.target)
  240. return true;
  241. }
  242. // Trigger HoverText event
  243. Context cHoverText;
  244. HoverText eHoverText;
  245. eHoverText.context = &cHoverText;
  246. eHoverText.pos = pos;
  247. eHoverText.codepoint = codepoint;
  248. rootWidget->onHoverText(eHoverText);
  249. return !!cHoverText.target;
  250. }
  251. bool State::handleKey(math::Vec pos, int key, int scancode, int action, int mods) {
  252. // Update heldKey state
  253. if (action == GLFW_PRESS) {
  254. heldKeys.insert(key);
  255. }
  256. else if (action == GLFW_RELEASE) {
  257. auto it = heldKeys.find(key);
  258. if (it != heldKeys.end())
  259. heldKeys.erase(it);
  260. }
  261. if (selectedWidget) {
  262. // Trigger SelectKey event
  263. Context cSelectKey;
  264. SelectKey eSelectKey;
  265. eSelectKey.context = &cSelectKey;
  266. eSelectKey.key = key;
  267. eSelectKey.scancode = scancode;
  268. const char* keyName = glfwGetKeyName(key, scancode);
  269. if (keyName)
  270. eSelectKey.keyName = keyName;
  271. eSelectKey.action = action;
  272. eSelectKey.mods = mods;
  273. selectedWidget->onSelectKey(eSelectKey);
  274. if (cSelectKey.target)
  275. return true;
  276. }
  277. // Trigger HoverKey event
  278. Context cHoverKey;
  279. HoverKey eHoverKey;
  280. eHoverKey.context = &cHoverKey;
  281. eHoverKey.pos = pos;
  282. eHoverKey.key = key;
  283. eHoverKey.scancode = scancode;
  284. const char* keyName = glfwGetKeyName(key, scancode);
  285. if (keyName)
  286. eHoverKey.keyName = keyName;
  287. eHoverKey.action = action;
  288. eHoverKey.mods = mods;
  289. rootWidget->onHoverKey(eHoverKey);
  290. return !!cHoverKey.target;
  291. }
  292. bool State::handleDirty() {
  293. // Trigger Dirty event
  294. Context cDirty;
  295. Dirty eDirty;
  296. eDirty.context = &cDirty;
  297. rootWidget->onDirty(eDirty);
  298. return true;
  299. }
  300. } // namespace event
  301. } // namespace rack