BsMacOSDropTarget.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "String/BsUnicode.h"
  4. #include "Platform/BsPlatform.h"
  5. #include "Platform/BsDropTarget.h"
  6. #include "RenderAPI/BsRenderWindow.h"
  7. #include "Math/BsRect2I.h"
  8. #include "Private/MacOS/BsMacOSDropTarget.h"
  9. #include "Private/MacOS/BsMacOSWindow.h"
  10. namespace bs
  11. {
  12. Vector<CocoaDragAndDrop::DropArea> CocoaDragAndDrop::sDropAreas;
  13. Mutex CocoaDragAndDrop::sMutex;
  14. Vector<CocoaDragAndDrop::DragAndDropOp> CocoaDragAndDrop::sQueuedOperations;
  15. Vector<CocoaDragAndDrop::DropAreaOp> CocoaDragAndDrop::sQueuedAreaOperations;
  16. DropTarget::DropTarget(const RenderWindow* ownerWindow, const Rect2I& area)
  17. : mArea(area), mActive(false), mOwnerWindow(ownerWindow), mDropType(DropTargetType::None)
  18. {
  19. CocoaDragAndDrop::registerDropTarget(this);
  20. }
  21. DropTarget::~DropTarget()
  22. {
  23. CocoaDragAndDrop::unregisterDropTarget(this);
  24. _clear();
  25. }
  26. void DropTarget::setArea(const Rect2I& area)
  27. {
  28. mArea = area;
  29. CocoaDragAndDrop::updateDropTarget(this);
  30. }
  31. void CocoaDragAndDrop::registerDropTarget(DropTarget* target)
  32. {
  33. Lock lock(sMutex);
  34. sQueuedAreaOperations.push_back(DropAreaOp(target, DropAreaOpType::Register, target->getArea()));
  35. }
  36. void CocoaDragAndDrop::unregisterDropTarget(DropTarget* target)
  37. {
  38. Lock lock(sMutex);
  39. sQueuedAreaOperations.push_back(DropAreaOp(target, DropAreaOpType::Unregister));
  40. }
  41. void CocoaDragAndDrop::updateDropTarget(DropTarget* target)
  42. {
  43. Lock lock(sMutex);
  44. sQueuedAreaOperations.push_back(DropAreaOp(target, DropAreaOpType::Update, target->getArea()));
  45. }
  46. void CocoaDragAndDrop::update()
  47. {
  48. Vector<DragAndDropOp> operations;
  49. {
  50. Lock lock(sMutex);
  51. std::swap(operations, sQueuedOperations);
  52. }
  53. for(auto& op : operations)
  54. {
  55. switch(op.type)
  56. {
  57. case DragAndDropOpType::Enter:
  58. op.target->onEnter(op.position.x, op.position.y);
  59. break;
  60. case DragAndDropOpType::DragOver:
  61. op.target->onDragOver(op.position.x, op.position.y);
  62. break;
  63. case DragAndDropOpType::Drop:
  64. op.target->_setFileList(op.fileList);
  65. op.target->onDrop(op.position.x, op.position.y);
  66. break;
  67. case DragAndDropOpType::Leave:
  68. op.target->_clear();
  69. op.target->onLeave();
  70. break;
  71. }
  72. }
  73. }
  74. void CocoaDragAndDrop::coreUpdate()
  75. {
  76. // First handle any queued registration/unregistration
  77. {
  78. Lock lock(sMutex);
  79. for(auto& entry : sQueuedAreaOperations)
  80. {
  81. CocoaWindow* areaWindow;
  82. entry.target->_getOwnerWindow()->getCustomAttribute("COCOA_WINDOW", &areaWindow);
  83. switch(entry.type)
  84. {
  85. case DropAreaOpType::Register:
  86. sDropAreas.push_back(DropArea(entry.target, entry.area));
  87. areaWindow->_registerForDragAndDrop();
  88. break;
  89. case DropAreaOpType::Unregister:
  90. // Remove any operations queued for this target
  91. for(auto iter = sQueuedOperations.begin(); iter !=sQueuedOperations.end();)
  92. {
  93. if(iter->target == entry.target)
  94. iter = sQueuedOperations.erase(iter);
  95. else
  96. ++iter;
  97. }
  98. // Remove the area
  99. {
  100. auto iterFind = std::find_if(sDropAreas.begin(), sDropAreas.end(), [&](const DropArea& area)
  101. {
  102. return area.target == entry.target;
  103. });
  104. sDropAreas.erase(iterFind);
  105. }
  106. areaWindow->_unregisterForDragAndDrop();
  107. break;
  108. case DropAreaOpType::Update:
  109. {
  110. auto iterFind = std::find_if(sDropAreas.begin(), sDropAreas.end(), [&](const DropArea& area)
  111. {
  112. return area.target == entry.target;
  113. });
  114. if (iterFind != sDropAreas.end())
  115. iterFind->area = entry.area;
  116. }
  117. break;
  118. }
  119. }
  120. sQueuedAreaOperations.clear();
  121. }
  122. }
  123. bool CocoaDragAndDrop::_notifyDragEntered(CocoaWindow* window, const Vector2I& position)
  124. {
  125. bool eventAccepted = false;
  126. for(auto& entry : sDropAreas)
  127. {
  128. CocoaWindow* areaWindow;
  129. entry.target->_getOwnerWindow()->getCustomAttribute("COCOA_WINDOW", &areaWindow);
  130. if(areaWindow != window)
  131. continue;
  132. if(entry.area.contains(position))
  133. {
  134. if(!entry.target->_isActive())
  135. {
  136. Lock lock(sMutex);
  137. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::Enter, entry.target,
  138. position));
  139. entry.target->_setActive(true);
  140. }
  141. eventAccepted = true;
  142. }
  143. }
  144. return eventAccepted;
  145. }
  146. bool CocoaDragAndDrop::_notifyDragMoved(CocoaWindow* window, const Vector2I& position)
  147. {
  148. bool eventAccepted = false;
  149. for(auto& entry : sDropAreas)
  150. {
  151. CocoaWindow* areaWindow;
  152. entry.target->_getOwnerWindow()->getCustomAttribute("COCOA_WINDOW", &areaWindow);
  153. if (areaWindow != window)
  154. continue;
  155. if (entry.area.contains(position))
  156. {
  157. if (entry.target->_isActive())
  158. {
  159. Lock lock(sMutex);
  160. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::DragOver, entry.target, position));
  161. } else
  162. {
  163. Lock lock(sMutex);
  164. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::Enter, entry.target, position));
  165. }
  166. entry.target->_setActive(true);
  167. eventAccepted = true;
  168. }
  169. else
  170. {
  171. // Cursor left previously active target's area
  172. if (entry.target->_isActive())
  173. {
  174. {
  175. Lock lock(sMutex);
  176. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::Leave, entry.target));
  177. }
  178. entry.target->_setActive(false);
  179. }
  180. }
  181. }
  182. return eventAccepted;
  183. }
  184. void CocoaDragAndDrop::_notifyDragLeft(CocoaWindow* window)
  185. {
  186. for(auto& entry : sDropAreas)
  187. {
  188. CocoaWindow* areaWindow;
  189. entry.target->_getOwnerWindow()->getCustomAttribute("COCOA_WINDOW", &areaWindow);
  190. if (areaWindow != window)
  191. continue;
  192. if(entry.target->_isActive())
  193. {
  194. {
  195. Lock lock(sMutex);
  196. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::Leave, entry.target));
  197. }
  198. entry.target->_setActive(false);
  199. }
  200. }
  201. }
  202. bool CocoaDragAndDrop::_notifyDragDropped(CocoaWindow* window, const Vector2I& position, const Vector<Path>& paths)
  203. {
  204. bool eventAccepted = false;
  205. for(auto& entry : sDropAreas)
  206. {
  207. CocoaWindow* areaWindow;
  208. entry.target->_getOwnerWindow()->getCustomAttribute("COCOA_WINDOW", &areaWindow);
  209. if(areaWindow != window)
  210. continue;
  211. if(!entry.target->_isActive())
  212. continue;
  213. Lock lock(sMutex);
  214. sQueuedOperations.push_back(DragAndDropOp(DragAndDropOpType::Drop, entry.target, position, paths));
  215. eventAccepted = true;
  216. entry.target->_setActive(false);
  217. }
  218. return eventAccepted;
  219. }
  220. }