Audio plugin host https://kx.studio/carla
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.

666 lines
14KB

  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * For a full copy of the license see the LGPL.txt file
  15. */
  16. #include "AppPrivate.hpp"
  17. #include "../Widget.hpp"
  18. #include "../Window.hpp"
  19. #include "pugl/pugl.h"
  20. #if DGL_OS_WINDOWS
  21. # include "pugl/pugl_win.cpp"
  22. #elif DGL_OS_MAC
  23. extern "C" {
  24. # include "pugl/pugl_osx_extended.h"
  25. }
  26. #elif DGL_OS_LINUX
  27. extern "C" {
  28. # include "pugl/pugl_x11.c"
  29. }
  30. #else
  31. # error Unsupported platform!
  32. #endif
  33. #include <cassert>
  34. #define FOR_EACH_WIDGET(it) \
  35. for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it)
  36. #define FOR_EACH_WIDGET_INV(rit) \
  37. for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit)
  38. START_NAMESPACE_DGL
  39. Window* dgl_lastUiParent = nullptr;
  40. // -------------------------------------------------
  41. // Window Private
  42. class Window::Private
  43. {
  44. public:
  45. Private(Window* self, App* app, App::Private* appPriv, Private* parent, intptr_t parentId = 0)
  46. : kApp(app),
  47. kAppPriv(appPriv),
  48. kSelf(self),
  49. kView(puglCreate(parentId, "Window", 100, 100, false, (parentId != 0))),
  50. fParent(parent),
  51. fChildFocus(nullptr),
  52. fVisible((parentId != 0)),
  53. fOnModal(false),
  54. fResizable(false),
  55. #if DGL_OS_WINDOWS
  56. hwnd(0)
  57. #elif DGL_OS_LINUX
  58. xDisplay(nullptr),
  59. xWindow(0)
  60. #else
  61. _dummy(0)
  62. #endif
  63. {
  64. if (kView == nullptr)
  65. return;
  66. // we can't have both
  67. if (parent != nullptr)
  68. {
  69. assert(parentId == 0);
  70. }
  71. puglSetHandle(kView, this);
  72. puglSetDisplayFunc(kView, onDisplayCallback);
  73. puglSetKeyboardFunc(kView, onKeyboardCallback);
  74. puglSetMotionFunc(kView, onMotionCallback);
  75. puglSetMouseFunc(kView, onMouseCallback);
  76. puglSetScrollFunc(kView, onScrollCallback);
  77. puglSetSpecialFunc(kView, onSpecialCallback);
  78. puglSetReshapeFunc(kView, onReshapeCallback);
  79. puglSetCloseFunc(kView, onCloseCallback);
  80. #if DGL_OS_WINDOWS
  81. PuglInternals* impl = kView->impl;
  82. hwnd = impl->hwnd;
  83. #elif DGL_OS_LINUX
  84. PuglInternals* impl = kView->impl;
  85. xDisplay = impl->display;
  86. xWindow = impl->win;
  87. if (parent != nullptr && parentId == 0)
  88. {
  89. PuglInternals* parentImpl = parent->kView->impl;
  90. XSetTransientForHint(xDisplay, xWindow, parentImpl->win);
  91. XFlush(xDisplay);
  92. }
  93. #endif
  94. kAppPriv->addWindow(kSelf);
  95. }
  96. ~Private()
  97. {
  98. fOnModal = false;
  99. fWidgets.clear();
  100. if (kView != nullptr)
  101. {
  102. kAppPriv->removeWindow(kSelf);
  103. puglDestroy(kView);
  104. }
  105. }
  106. void exec_init()
  107. {
  108. fOnModal = true;
  109. assert(fParent != nullptr);
  110. if (fParent != nullptr)
  111. {
  112. fParent->fChildFocus = this;
  113. #if DGL_OS_WINDOWS
  114. // Center this window
  115. PuglInternals* parentImpl = fParent->kView->impl;
  116. RECT curRect;
  117. RECT parentRect;
  118. GetWindowRect(hwnd, &curRect);
  119. GetWindowRect(parentImpl->hwnd, &parentRect);
  120. int x = parentRect.left+(parentRect.right-curRect.right)/2;
  121. int y = parentRect.top+(parentRect.bottom-curRect.bottom)/2;
  122. SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  123. UpdateWindow(hwnd);
  124. #endif
  125. fParent->show();
  126. }
  127. show();
  128. }
  129. void exec_fini()
  130. {
  131. fOnModal = false;
  132. if (fParent != nullptr)
  133. fParent->fChildFocus = nullptr;
  134. }
  135. void exec(bool block)
  136. {
  137. exec_init();
  138. if (block)
  139. {
  140. while (fVisible && fOnModal)
  141. {
  142. // idle()
  143. puglProcessEvents(kView);
  144. if (fParent != nullptr)
  145. fParent->idle();
  146. dgl_msleep(10);
  147. }
  148. exec_fini();
  149. }
  150. else
  151. {
  152. idle();
  153. }
  154. }
  155. void focus()
  156. {
  157. #if DGL_OS_WINDOWS
  158. SetForegroundWindow(hwnd);
  159. SetActiveWindow(hwnd);
  160. SetFocus(hwnd);
  161. #elif DGL_OS_MAC
  162. puglImplFocus(kView);
  163. #elif DGL_OS_LINUX
  164. XRaiseWindow(xDisplay, xWindow);
  165. XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime);
  166. XFlush(xDisplay);
  167. #endif
  168. }
  169. void idle()
  170. {
  171. puglProcessEvents(kView);
  172. if (fVisible && fOnModal && fParent != nullptr)
  173. fParent->idle();
  174. }
  175. void repaint()
  176. {
  177. puglPostRedisplay(kView);
  178. }
  179. void show()
  180. {
  181. setVisible(true);
  182. }
  183. void hide()
  184. {
  185. setVisible(false);
  186. }
  187. void close()
  188. {
  189. setVisible(false, true);
  190. }
  191. bool isVisible()
  192. {
  193. return fVisible;
  194. }
  195. void setResizable(bool yesNo)
  196. {
  197. if (fResizable == yesNo)
  198. return;
  199. fResizable = yesNo;
  200. //setSize();
  201. }
  202. void setVisible(bool yesNo, bool closed = false)
  203. {
  204. if (fVisible == yesNo)
  205. return;
  206. fVisible = yesNo;
  207. #if DGL_OS_WINDOWS
  208. if (yesNo)
  209. {
  210. ShowWindow(hwnd, WS_VISIBLE);
  211. ShowWindow(hwnd, SW_RESTORE);
  212. //SetForegroundWindow(hwnd);
  213. }
  214. else
  215. {
  216. ShowWindow(hwnd, SW_HIDE);
  217. }
  218. UpdateWindow(hwnd);
  219. #elif DGL_OS_MAC
  220. puglImplSetVisible(kView, yesNo);
  221. #elif DGL_OS_LINUX
  222. if (yesNo)
  223. XMapRaised(xDisplay, xWindow);
  224. else
  225. XUnmapWindow(xDisplay, xWindow);
  226. XFlush(xDisplay);
  227. #endif
  228. if (yesNo)
  229. {
  230. kAppPriv->oneShown();
  231. }
  232. else
  233. {
  234. if (fOnModal)
  235. exec_fini();
  236. if (closed)
  237. kAppPriv->oneHidden();
  238. }
  239. }
  240. void setSize(unsigned int width, unsigned int height)
  241. {
  242. kView->width = width;
  243. kView->height = height;
  244. #if DGL_OS_WINDOWS
  245. int winFlags = WS_POPUPWINDOW | WS_CAPTION;
  246. if (fResizable)
  247. winFlags |= WS_SIZEBOX;
  248. RECT wr = { 0, 0, (long)width, (long)height };
  249. AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
  250. SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
  251. UpdateWindow(hwnd);
  252. #elif DGL_OS_MAC
  253. puglImplSetSize(kView, width, height);
  254. #elif DGL_OS_LINUX
  255. XResizeWindow(xDisplay, xWindow, width, height);
  256. if (! fResizable)
  257. {
  258. XSizeHints sizeHints;
  259. memset(&sizeHints, 0, sizeof(sizeHints));
  260. sizeHints.flags = PMinSize|PMaxSize;
  261. sizeHints.min_width = width;
  262. sizeHints.min_height = height;
  263. sizeHints.max_width = width;
  264. sizeHints.max_height = height;
  265. XSetNormalHints(xDisplay, xWindow, &sizeHints);
  266. }
  267. XFlush(xDisplay);
  268. #endif
  269. repaint();
  270. }
  271. void setWindowTitle(const char* title)
  272. {
  273. #if DGL_OS_WINDOWS
  274. SetWindowTextA(hwnd, title);
  275. #elif DGL_OS_MAC
  276. puglImplSetTitle(kView, title);
  277. #elif DGL_OS_LINUX
  278. XStoreName(xDisplay, xWindow, title);
  279. XFlush(xDisplay);
  280. #endif
  281. }
  282. App* getApp() const
  283. {
  284. return kApp;
  285. }
  286. int getModifiers() const
  287. {
  288. return puglGetModifiers(kView);
  289. }
  290. intptr_t getWindowId() const
  291. {
  292. return puglGetNativeWindow(kView);
  293. }
  294. void addWidget(Widget* widget)
  295. {
  296. fWidgets.push_back(widget);
  297. }
  298. void removeWidget(Widget* widget)
  299. {
  300. fWidgets.remove(widget);
  301. }
  302. protected:
  303. void onDisplay()
  304. {
  305. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  306. FOR_EACH_WIDGET(it)
  307. {
  308. Widget* const widget(*it);
  309. if (widget->isVisible())
  310. widget->onDisplay();
  311. }
  312. }
  313. void onKeyboard(bool press, uint32_t key)
  314. {
  315. if (fChildFocus != nullptr)
  316. return fChildFocus->focus();
  317. FOR_EACH_WIDGET_INV(rit)
  318. {
  319. Widget* const widget(*rit);
  320. if (widget->isVisible())
  321. {
  322. if (widget->onKeyboard(press, key))
  323. break;
  324. }
  325. }
  326. }
  327. void onMouse(int button, bool press, int x, int y)
  328. {
  329. if (fChildFocus != nullptr)
  330. return fChildFocus->focus();
  331. FOR_EACH_WIDGET_INV(rit)
  332. {
  333. Widget* const widget(*rit);
  334. if (widget->isVisible())
  335. {
  336. if (widget->onMouse(button, press, x, y))
  337. break;
  338. }
  339. }
  340. }
  341. void onMotion(int x, int y)
  342. {
  343. if (fChildFocus != nullptr)
  344. return;
  345. FOR_EACH_WIDGET_INV(rit)
  346. {
  347. Widget* const widget(*rit);
  348. if (widget->isVisible())
  349. {
  350. if (widget->onMotion(x, y))
  351. break;
  352. }
  353. }
  354. }
  355. void onScroll(float dx, float dy)
  356. {
  357. if (fChildFocus != nullptr)
  358. return;
  359. FOR_EACH_WIDGET_INV(rit)
  360. {
  361. Widget* const widget(*rit);
  362. if (widget->isVisible())
  363. {
  364. if (widget->onScroll(dx, dy))
  365. break;
  366. }
  367. }
  368. }
  369. void onSpecial(bool press, Key key)
  370. {
  371. if (fChildFocus != nullptr)
  372. return;
  373. FOR_EACH_WIDGET_INV(rit)
  374. {
  375. Widget* const widget(*rit);
  376. if (widget->isVisible())
  377. {
  378. if (widget->onSpecial(press, key))
  379. break;
  380. }
  381. }
  382. }
  383. void onReshape(int width, int height)
  384. {
  385. FOR_EACH_WIDGET(it)
  386. {
  387. Widget* const widget(*it);
  388. widget->onReshape(width, height);
  389. }
  390. }
  391. void onClose()
  392. {
  393. fOnModal = false;
  394. if (fChildFocus != nullptr)
  395. fChildFocus->onClose();
  396. FOR_EACH_WIDGET(it)
  397. {
  398. Widget* const widget(*it);
  399. widget->onClose();
  400. }
  401. close();
  402. }
  403. private:
  404. App* const kApp;
  405. App::Private* const kAppPriv;
  406. Window* const kSelf;
  407. PuglView* const kView;
  408. Private* fParent;
  409. Private* fChildFocus;
  410. bool fVisible;
  411. bool fOnModal;
  412. bool fResizable;
  413. std::list<Widget*> fWidgets;
  414. #if DGL_OS_WINDOWS
  415. HWND hwnd;
  416. #elif DGL_OS_LINUX
  417. Display* xDisplay;
  418. ::Window xWindow;
  419. #else
  420. int _dummy;
  421. #endif
  422. // Callbacks
  423. #define handlePtr ((Private*)puglGetHandle(view))
  424. static void onDisplayCallback(PuglView* view)
  425. {
  426. handlePtr->onDisplay();
  427. }
  428. static void onKeyboardCallback(PuglView* view, bool press, uint32_t key)
  429. {
  430. handlePtr->onKeyboard(press, key);
  431. }
  432. static void onMouseCallback(PuglView* view, int button, bool press, int x, int y)
  433. {
  434. handlePtr->onMouse(button, press, x, y);
  435. }
  436. static void onMotionCallback(PuglView* view, int x, int y)
  437. {
  438. handlePtr->onMotion(x, y);
  439. }
  440. static void onScrollCallback(PuglView* view, float dx, float dy)
  441. {
  442. handlePtr->onScroll(dx, dy);
  443. }
  444. static void onSpecialCallback(PuglView* view, bool press, PuglKey key)
  445. {
  446. handlePtr->onSpecial(press, static_cast<Key>(key));
  447. }
  448. static void onReshapeCallback(PuglView* view, int width, int height)
  449. {
  450. handlePtr->onReshape(width, height);
  451. }
  452. static void onCloseCallback(PuglView* view)
  453. {
  454. handlePtr->onClose();
  455. }
  456. #undef handlePtr
  457. };
  458. // -------------------------------------------------
  459. // Window
  460. Window::Window(App* app, Window* parent)
  461. : kPrivate(new Private(this, app, app->kPrivate, (parent != nullptr) ? parent->kPrivate : nullptr))
  462. {
  463. dgl_lastUiParent = this;
  464. }
  465. Window::Window(App* app, intptr_t parentId)
  466. : kPrivate(new Private(this, app, app->kPrivate, nullptr, parentId))
  467. {
  468. dgl_lastUiParent = this;
  469. }
  470. Window::~Window()
  471. {
  472. delete kPrivate;
  473. }
  474. void Window::exec(bool lock)
  475. {
  476. kPrivate->exec(lock);
  477. }
  478. void Window::focus()
  479. {
  480. kPrivate->focus();
  481. }
  482. void Window::idle()
  483. {
  484. kPrivate->idle();
  485. }
  486. void Window::repaint()
  487. {
  488. kPrivate->repaint();
  489. }
  490. bool Window::isVisible()
  491. {
  492. return kPrivate->isVisible();
  493. }
  494. void Window::setResizable(bool yesNo)
  495. {
  496. kPrivate->setResizable(yesNo);
  497. }
  498. void Window::setVisible(bool yesNo)
  499. {
  500. kPrivate->setVisible(yesNo);
  501. }
  502. void Window::setSize(unsigned int width, unsigned int height)
  503. {
  504. kPrivate->setSize(width, height);
  505. }
  506. void Window::setWindowTitle(const char* title)
  507. {
  508. kPrivate->setWindowTitle(title);
  509. }
  510. App* Window::getApp() const
  511. {
  512. return kPrivate->getApp();
  513. }
  514. int Window::getModifiers() const
  515. {
  516. return kPrivate->getModifiers();
  517. }
  518. intptr_t Window::getWindowId() const
  519. {
  520. return kPrivate->getWindowId();
  521. }
  522. void Window::addWidget(Widget* widget)
  523. {
  524. kPrivate->addWidget(widget);
  525. }
  526. void Window::removeWidget(Widget* widget)
  527. {
  528. kPrivate->removeWidget(widget);
  529. }
  530. void Window::show()
  531. {
  532. setVisible(true);
  533. }
  534. void Window::hide()
  535. {
  536. setVisible(false);
  537. }
  538. void Window::close()
  539. {
  540. kPrivate->close();
  541. }
  542. // -------------------------------------------------
  543. END_NAMESPACE_DGL