BsMacOSDropTarget.cpp 6.6 KB

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