Collection of DPF-based plugins for packaging
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.

547 lines
13KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include "WindowPrivateData.hpp"
  17. #include "../TopLevelWidget.hpp"
  18. #include "pugl.hpp"
  19. START_NAMESPACE_DGL
  20. // -----------------------------------------------------------------------
  21. // ScopedGraphicsContext
  22. Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win)
  23. : window(win),
  24. ppData(nullptr),
  25. active(puglBackendEnter(window.pData->view)),
  26. reenter(false) {}
  27. Window::ScopedGraphicsContext::ScopedGraphicsContext(Window& win, Window& transientWin)
  28. : window(win),
  29. ppData(transientWin.pData),
  30. active(false),
  31. reenter(true)
  32. {
  33. puglBackendLeave(ppData->view);
  34. active = puglBackendEnter(window.pData->view);
  35. }
  36. Window::ScopedGraphicsContext::~ScopedGraphicsContext()
  37. {
  38. done();
  39. }
  40. void Window::ScopedGraphicsContext::done()
  41. {
  42. if (active)
  43. {
  44. puglBackendLeave(window.pData->view);
  45. active = false;
  46. }
  47. if (reenter)
  48. {
  49. reenter = false;
  50. DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,);
  51. puglBackendEnter(ppData->view);
  52. }
  53. }
  54. void Window::ScopedGraphicsContext::reinit()
  55. {
  56. DISTRHO_SAFE_ASSERT_RETURN(!active,);
  57. DISTRHO_SAFE_ASSERT_RETURN(!reenter,);
  58. DISTRHO_SAFE_ASSERT_RETURN(ppData != nullptr,);
  59. reenter = true;
  60. puglBackendLeave(ppData->view);
  61. active = puglBackendEnter(window.pData->view);
  62. }
  63. // -----------------------------------------------------------------------
  64. // Window
  65. Window::Window(Application& app)
  66. : pData(new PrivateData(app, this))
  67. {
  68. pData->initPost();
  69. }
  70. Window::Window(Application& app, Window& transientParentWindow)
  71. : pData(new PrivateData(app, this, transientParentWindow.pData))
  72. {
  73. pData->initPost();
  74. }
  75. Window::Window(Application& app,
  76. const uintptr_t parentWindowHandle,
  77. const double scaleFactor,
  78. const bool resizable)
  79. : pData(new PrivateData(app, this, parentWindowHandle, scaleFactor, resizable))
  80. {
  81. pData->initPost();
  82. }
  83. Window::Window(Application& app,
  84. const uintptr_t parentWindowHandle,
  85. const uint width,
  86. const uint height,
  87. const double scaleFactor,
  88. const bool resizable)
  89. : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, false))
  90. {
  91. pData->initPost();
  92. }
  93. Window::Window(Application& app,
  94. const uintptr_t parentWindowHandle,
  95. const uint width,
  96. const uint height,
  97. const double scaleFactor,
  98. const bool resizable,
  99. const bool isVST3,
  100. const bool doPostInit)
  101. : pData(new PrivateData(app, this, parentWindowHandle, width, height, scaleFactor, resizable, isVST3))
  102. {
  103. if (doPostInit)
  104. pData->initPost();
  105. }
  106. Window::~Window()
  107. {
  108. delete pData;
  109. }
  110. bool Window::isEmbed() const noexcept
  111. {
  112. return pData->isEmbed;
  113. }
  114. bool Window::isVisible() const noexcept
  115. {
  116. return pData->isVisible;
  117. }
  118. void Window::setVisible(const bool visible)
  119. {
  120. if (visible)
  121. pData->show();
  122. else
  123. pData->hide();
  124. }
  125. void Window::show()
  126. {
  127. pData->show();
  128. }
  129. void Window::hide()
  130. {
  131. pData->hide();
  132. }
  133. void Window::close()
  134. {
  135. pData->close();
  136. }
  137. bool Window::isResizable() const noexcept
  138. {
  139. return puglGetViewHint(pData->view, PUGL_RESIZABLE) == PUGL_TRUE;
  140. }
  141. void Window::setResizable(const bool resizable)
  142. {
  143. pData->setResizable(resizable);
  144. }
  145. int Window::getOffsetX() const noexcept
  146. {
  147. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
  148. return puglGetFrame(pData->view).x;
  149. }
  150. int Window::getOffsetY() const noexcept
  151. {
  152. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
  153. return puglGetFrame(pData->view).y;
  154. }
  155. Point<int> Window::getOffset() const noexcept
  156. {
  157. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Point<int>());
  158. const PuglRect rect = puglGetFrame(pData->view);
  159. return Point<int>(rect.x, rect.y);
  160. }
  161. void Window::setOffsetX(const int x)
  162. {
  163. setOffset(x, getOffsetY());
  164. }
  165. void Window::setOffsetY(const int y)
  166. {
  167. setOffset(getOffsetX(), y);
  168. }
  169. void Window::setOffset(const int x, const int y)
  170. {
  171. puglSetPosition(pData->view, x, y);
  172. }
  173. void Window::setOffset(const Point<int>& offset)
  174. {
  175. setOffset(offset.getX(), offset.getY());
  176. }
  177. uint Window::getWidth() const noexcept
  178. {
  179. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
  180. const double width = puglGetFrame(pData->view).width;
  181. DISTRHO_SAFE_ASSERT_RETURN(width >= 0.0, 0);
  182. return static_cast<uint>(width + 0.5);
  183. }
  184. uint Window::getHeight() const noexcept
  185. {
  186. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, 0);
  187. const double height = puglGetFrame(pData->view).height;
  188. DISTRHO_SAFE_ASSERT_RETURN(height >= 0.0, 0);
  189. return static_cast<uint>(height + 0.5);
  190. }
  191. Size<uint> Window::getSize() const noexcept
  192. {
  193. DISTRHO_SAFE_ASSERT_RETURN(pData->view != nullptr, Size<uint>());
  194. const PuglRect rect = puglGetFrame(pData->view);
  195. DISTRHO_SAFE_ASSERT_RETURN(rect.width >= 0.0, Size<uint>());
  196. DISTRHO_SAFE_ASSERT_RETURN(rect.height >= 0.0, Size<uint>());
  197. return Size<uint>(static_cast<uint>(rect.width + 0.5),
  198. static_cast<uint>(rect.height + 0.5));
  199. }
  200. void Window::setWidth(const uint width)
  201. {
  202. setSize(width, getHeight());
  203. }
  204. void Window::setHeight(const uint height)
  205. {
  206. setSize(getWidth(), height);
  207. }
  208. void Window::setSize(uint width, uint height)
  209. {
  210. DISTRHO_SAFE_ASSERT_UINT2_RETURN(width > 1 && height > 1, width, height,);
  211. if (pData->isEmbed)
  212. {
  213. const double scaleFactor = pData->scaleFactor;
  214. uint minWidth = pData->minWidth;
  215. uint minHeight = pData->minHeight;
  216. if (pData->autoScaling && scaleFactor != 1.0)
  217. {
  218. minWidth *= scaleFactor;
  219. minHeight *= scaleFactor;
  220. }
  221. // handle geometry constraints here
  222. if (width < minWidth)
  223. width = minWidth;
  224. if (height < minHeight)
  225. height = minHeight;
  226. if (pData->keepAspectRatio)
  227. {
  228. const double ratio = static_cast<double>(pData->minWidth)
  229. / static_cast<double>(pData->minHeight);
  230. const double reqRatio = static_cast<double>(width)
  231. / static_cast<double>(height);
  232. if (d_isNotEqual(ratio, reqRatio))
  233. {
  234. // fix width
  235. if (reqRatio > ratio)
  236. width = static_cast<uint>(height * ratio + 0.5);
  237. // fix height
  238. else
  239. height = static_cast<uint>(static_cast<double>(width) / ratio + 0.5);
  240. }
  241. }
  242. }
  243. if (pData->usesSizeRequest)
  244. {
  245. DISTRHO_SAFE_ASSERT_RETURN(pData->topLevelWidgets.size() != 0,);
  246. TopLevelWidget* const topLevelWidget = pData->topLevelWidgets.front();
  247. DISTRHO_SAFE_ASSERT_RETURN(topLevelWidget != nullptr,);
  248. topLevelWidget->requestSizeChange(width, height);
  249. }
  250. else
  251. {
  252. puglSetSizeAndDefault(pData->view, width, height);
  253. }
  254. }
  255. void Window::setSize(const Size<uint>& size)
  256. {
  257. setSize(size.getWidth(), size.getHeight());
  258. }
  259. const char* Window::getTitle() const noexcept
  260. {
  261. return puglGetWindowTitle(pData->view);
  262. }
  263. void Window::setTitle(const char* const title)
  264. {
  265. if (pData->view != nullptr)
  266. puglSetWindowTitle(pData->view, title);
  267. }
  268. bool Window::isIgnoringKeyRepeat() const noexcept
  269. {
  270. return puglGetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT) == PUGL_TRUE;
  271. }
  272. void Window::setIgnoringKeyRepeat(const bool ignore) noexcept
  273. {
  274. puglSetViewHint(pData->view, PUGL_IGNORE_KEY_REPEAT, ignore);
  275. }
  276. const void* Window::getClipboard(size_t& dataSize)
  277. {
  278. return pData->getClipboard(dataSize);
  279. }
  280. bool Window::setClipboard(const char* const mimeType, const void* const data, const size_t dataSize)
  281. {
  282. return puglSetClipboard(pData->view, mimeType != nullptr ? mimeType : "text/plain", data, dataSize) == PUGL_SUCCESS;
  283. }
  284. bool Window::setCursor(const MouseCursor cursor)
  285. {
  286. return puglSetCursor(pData->view, static_cast<PuglCursor>(cursor)) == PUGL_SUCCESS;
  287. }
  288. bool Window::addIdleCallback(IdleCallback* const callback, const uint timerFrequencyInMs)
  289. {
  290. DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false)
  291. return pData->addIdleCallback(callback, timerFrequencyInMs);
  292. }
  293. bool Window::removeIdleCallback(IdleCallback* const callback)
  294. {
  295. DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr, false)
  296. return pData->removeIdleCallback(callback);
  297. }
  298. Application& Window::getApp() const noexcept
  299. {
  300. return pData->app;
  301. }
  302. #ifndef DPF_TEST_WINDOW_CPP
  303. const GraphicsContext& Window::getGraphicsContext() const noexcept
  304. {
  305. return pData->getGraphicsContext();
  306. }
  307. #endif
  308. uintptr_t Window::getNativeWindowHandle() const noexcept
  309. {
  310. return puglGetNativeView(pData->view);
  311. }
  312. double Window::getScaleFactor() const noexcept
  313. {
  314. return pData->scaleFactor;
  315. }
  316. void Window::focus()
  317. {
  318. pData->focus();
  319. }
  320. #ifndef DGL_FILE_BROWSER_DISABLED
  321. bool Window::openFileBrowser(const FileBrowserOptions& options)
  322. {
  323. return pData->openFileBrowser(options);
  324. }
  325. #endif
  326. void Window::repaint() noexcept
  327. {
  328. if (pData->view == nullptr)
  329. return;
  330. puglPostRedisplay(pData->view);
  331. }
  332. void Window::repaint(const Rectangle<uint>& rect) noexcept
  333. {
  334. if (pData->view == nullptr)
  335. return;
  336. PuglRect prect = {
  337. static_cast<PuglCoord>(rect.getX()),
  338. static_cast<PuglCoord>(rect.getY()),
  339. static_cast<PuglSpan>(rect.getWidth()),
  340. static_cast<PuglSpan>(rect.getHeight()),
  341. };
  342. if (pData->autoScaling)
  343. {
  344. const double autoScaleFactor = pData->autoScaleFactor;
  345. prect.x *= autoScaleFactor;
  346. prect.y *= autoScaleFactor;
  347. prect.width *= autoScaleFactor;
  348. prect.height *= autoScaleFactor;
  349. }
  350. puglPostRedisplayRect(pData->view, prect);
  351. }
  352. void Window::renderToPicture(const char* const filename)
  353. {
  354. pData->filenameToRenderInto = strdup(filename);
  355. }
  356. void Window::runAsModal(bool blockWait)
  357. {
  358. pData->runAsModal(blockWait);
  359. }
  360. Size<uint> Window::getGeometryConstraints(bool& keepAspectRatio)
  361. {
  362. keepAspectRatio = pData->keepAspectRatio;
  363. return Size<uint>(pData->minWidth, pData->minHeight);
  364. }
  365. void Window::setGeometryConstraints(uint minimumWidth,
  366. uint minimumHeight,
  367. const bool keepAspectRatio,
  368. const bool automaticallyScale,
  369. const bool resizeNowIfAutoScaling)
  370. {
  371. DISTRHO_SAFE_ASSERT_RETURN(minimumWidth > 0,);
  372. DISTRHO_SAFE_ASSERT_RETURN(minimumHeight > 0,);
  373. pData->minWidth = minimumWidth;
  374. pData->minHeight = minimumHeight;
  375. pData->autoScaling = automaticallyScale;
  376. pData->keepAspectRatio = keepAspectRatio;
  377. if (pData->view == nullptr)
  378. return;
  379. const double scaleFactor = pData->scaleFactor;
  380. if (automaticallyScale && scaleFactor != 1.0)
  381. {
  382. minimumWidth *= scaleFactor;
  383. minimumHeight *= scaleFactor;
  384. }
  385. puglSetGeometryConstraints(pData->view, minimumWidth, minimumHeight, keepAspectRatio);
  386. if (scaleFactor != 1.0 && automaticallyScale && resizeNowIfAutoScaling)
  387. {
  388. const Size<uint> size(getSize());
  389. setSize(static_cast<uint>(size.getWidth() * scaleFactor + 0.5),
  390. static_cast<uint>(size.getHeight() * scaleFactor + 0.5));
  391. }
  392. }
  393. void Window::setTransientParent(const uintptr_t transientParentWindowHandle)
  394. {
  395. puglSetTransientParent(pData->view, transientParentWindowHandle);
  396. }
  397. std::vector<ClipboardDataOffer> Window::getClipboardDataOfferTypes()
  398. {
  399. std::vector<ClipboardDataOffer> offerTypes;
  400. if (const uint32_t numTypes = puglGetNumClipboardTypes(pData->view))
  401. {
  402. offerTypes.reserve(numTypes);
  403. for (uint32_t i=0; i<numTypes; ++i)
  404. {
  405. const ClipboardDataOffer offer = { i + 1, puglGetClipboardType(pData->view, i) };
  406. offerTypes.push_back(offer);
  407. }
  408. }
  409. return offerTypes;
  410. }
  411. uint32_t Window::onClipboardDataOffer()
  412. {
  413. std::vector<ClipboardDataOffer> offers(getClipboardDataOfferTypes());
  414. for (std::vector<ClipboardDataOffer>::iterator it=offers.begin(), end=offers.end(); it != end;++it)
  415. {
  416. const ClipboardDataOffer offer = *it;
  417. if (std::strcmp(offer.type, "text/plain") == 0)
  418. return offer.id;
  419. }
  420. return 0;
  421. }
  422. bool Window::onClose()
  423. {
  424. return true;
  425. }
  426. void Window::onFocus(bool, CrossingMode)
  427. {
  428. }
  429. void Window::onReshape(uint, uint)
  430. {
  431. puglFallbackOnResize(pData->view);
  432. }
  433. void Window::onScaleFactorChanged(double)
  434. {
  435. }
  436. #ifndef DGL_FILE_BROWSER_DISABLED
  437. void Window::onFileSelected(const char*)
  438. {
  439. }
  440. #endif
  441. // -----------------------------------------------------------------------
  442. END_NAMESPACE_DGL