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.

915 lines
20KB

  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 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 "../App.hpp"
  17. #include "../Widget.hpp"
  18. #include "../Window.hpp"
  19. #include <cassert>
  20. #include <cstdio>
  21. #include <list>
  22. #include "pugl/pugl.h"
  23. #if DGL_OS_WINDOWS
  24. # include "pugl/pugl_win.cpp"
  25. #elif DGL_OS_MAC
  26. # include "pugl/pugl_osx_extended.h"
  27. extern "C" {
  28. struct PuglViewImpl {
  29. int width;
  30. int height;
  31. };}
  32. #elif DGL_OS_LINUX
  33. extern "C" {
  34. # include "pugl/pugl_x11.c"
  35. }
  36. #else
  37. # error Unsupported platform
  38. #endif
  39. #define FOR_EACH_WIDGET(it) \
  40. for (std::list<Widget*>::iterator it = fWidgets.begin(); it != fWidgets.end(); ++it)
  41. #define FOR_EACH_WIDGET_INV(rit) \
  42. for (std::list<Widget*>::reverse_iterator rit = fWidgets.rbegin(); rit != fWidgets.rend(); ++rit)
  43. #ifdef DEBUG
  44. # define DBG(msg) std::fprintf(stderr, "%s", msg);
  45. # define DBGp(...) std::fprintf(stderr, __VA_ARGS__);
  46. # define DBGF std::fflush(stderr);
  47. #else
  48. # define DBG(msg)
  49. # define DBGp(...)
  50. # define DBGF
  51. #endif
  52. START_NAMESPACE_DGL
  53. Window* dgl_lastUiParent = nullptr;
  54. // -----------------------------------------------------------------------
  55. // Window Private
  56. class Window::PrivateData
  57. {
  58. public:
  59. PrivateData(App& app, Window* const self)
  60. : fApp(app),
  61. fSelf(self),
  62. fView(puglCreate(0, "Window", 100, 100, true, false)),
  63. fFirstInit(true),
  64. fVisible(false),
  65. fResizable(true),
  66. fUsingEmbed(false),
  67. #if DGL_OS_WINDOWS
  68. hwnd(0)
  69. #elif DGL_OS_LINUX
  70. xDisplay(nullptr),
  71. xWindow(0)
  72. #else
  73. _dummy('\0')
  74. #endif
  75. {
  76. DBG("Creating window without parent..."); DBGF;
  77. init();
  78. }
  79. PrivateData(App& app, Window* const self, Window& parent)
  80. : fApp(app),
  81. fSelf(self),
  82. fView(puglCreate(0, "Window", 100, 100, true, false)),
  83. fFirstInit(true),
  84. fVisible(false),
  85. fResizable(true),
  86. fUsingEmbed(false),
  87. fModal(parent.pData),
  88. #if DGL_OS_WINDOWS
  89. hwnd(0)
  90. #elif DGL_OS_LINUX
  91. xDisplay(nullptr),
  92. xWindow(0)
  93. #else
  94. _dummy('\0')
  95. #endif
  96. {
  97. DBG("Creating window with parent..."); DBGF;
  98. init();
  99. #if DGL_OS_LINUX
  100. const PuglInternals* const parentImpl(parent.pData->fView->impl);
  101. XSetTransientForHint(xDisplay, xWindow, parentImpl->win);
  102. #endif
  103. }
  104. PrivateData(App& app, Window* const self, const intptr_t parentId)
  105. : fApp(app),
  106. fSelf(self),
  107. fView(puglCreate(parentId, "Window", 100, 100, true, true)),
  108. fFirstInit(true),
  109. fVisible(true),
  110. fResizable(false),
  111. fUsingEmbed(true),
  112. #if DGL_OS_WINDOWS
  113. hwnd(0)
  114. #elif DGL_OS_LINUX
  115. xDisplay(nullptr),
  116. xWindow(0)
  117. #else
  118. _dummy('\0')
  119. #endif
  120. {
  121. DBG("Creating embedded window..."); DBGF;
  122. init();
  123. DBG("NOTE: Embed window is always visible and non-resizable\n");
  124. fApp._oneShown();
  125. fFirstInit = false;
  126. }
  127. void init()
  128. {
  129. if (fSelf == nullptr || fView == nullptr)
  130. {
  131. DBG("Failed!\n");
  132. dgl_lastUiParent = nullptr;
  133. return;
  134. }
  135. dgl_lastUiParent = fSelf;
  136. puglSetHandle(fView, this);
  137. puglSetDisplayFunc(fView, onDisplayCallback);
  138. puglSetKeyboardFunc(fView, onKeyboardCallback);
  139. puglSetMotionFunc(fView, onMotionCallback);
  140. puglSetMouseFunc(fView, onMouseCallback);
  141. puglSetScrollFunc(fView, onScrollCallback);
  142. puglSetSpecialFunc(fView, onSpecialCallback);
  143. puglSetReshapeFunc(fView, onReshapeCallback);
  144. puglSetCloseFunc(fView, onCloseCallback);
  145. #if DGL_OS_WINDOWS
  146. PuglInternals* impl = fView->impl;
  147. hwnd = impl->hwnd;
  148. assert(hwnd != 0);
  149. #elif DGL_OS_LINUX
  150. PuglInternals* impl = fView->impl;
  151. xDisplay = impl->display;
  152. xWindow = impl->win;
  153. assert(xWindow != 0);
  154. #endif
  155. DBG("Success!\n");
  156. // process any initial events
  157. puglProcessEvents(fView);
  158. fApp._addWindow(fSelf);
  159. }
  160. ~PrivateData()
  161. {
  162. DBG("Destroying window..."); DBGF;
  163. //fOnModal = false;
  164. fWidgets.clear();
  165. if (fSelf != nullptr)
  166. {
  167. fApp._removeWindow(fSelf);
  168. fSelf = nullptr;
  169. }
  170. if (fView != nullptr)
  171. {
  172. puglDestroy(fView);
  173. fView = nullptr;
  174. }
  175. #if DGL_OS_WINDOWS
  176. hwnd = 0;
  177. #elif DGL_OS_LINUX
  178. xDisplay = nullptr;
  179. xWindow = 0;
  180. #endif
  181. DBG("Success!\n");
  182. }
  183. // TESTING
  184. void setTransient(const intptr_t win)
  185. {
  186. #if DGL_OS_LINUX
  187. XSetTransientForHint(xDisplay, xWindow, (::Window)win);
  188. XFlush(xDisplay);
  189. #else
  190. return; (void)win;
  191. #endif
  192. }
  193. // -------------------------------------------------------------------
  194. void close()
  195. {
  196. DBG("Window close\n");
  197. setVisible(false);
  198. if (! fFirstInit)
  199. {
  200. fApp._oneHidden();
  201. fFirstInit = true;
  202. }
  203. }
  204. void exec(const bool lockWait)
  205. {
  206. DBG("Window exec\n");
  207. exec_init();
  208. if (lockWait)
  209. {
  210. for (; fVisible && fModal.enabled;)
  211. {
  212. // idle()
  213. puglProcessEvents(fView);
  214. if (fModal.parent != nullptr)
  215. fModal.parent->idle();
  216. msleep(10);
  217. }
  218. exec_fini();
  219. }
  220. else
  221. {
  222. idle();
  223. }
  224. }
  225. // -------------------------------------------------------------------
  226. void focus()
  227. {
  228. DBG("Window focus\n");
  229. #if DGL_OS_WINDOWS
  230. SetForegroundWindow(hwnd);
  231. SetActiveWindow(hwnd);
  232. SetFocus(hwnd);
  233. #elif DGL_OS_MAC
  234. puglImplFocus(fView);
  235. #elif DGL_OS_LINUX
  236. XRaiseWindow(xDisplay, xWindow);
  237. XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime);
  238. XFlush(xDisplay);
  239. #endif
  240. }
  241. void repaint()
  242. {
  243. //DBG("Window repaint\n");
  244. puglPostRedisplay(fView);
  245. }
  246. // -------------------------------------------------------------------
  247. bool isVisible() const noexcept
  248. {
  249. return fVisible;
  250. }
  251. void setVisible(const bool yesNo)
  252. {
  253. if (fVisible == yesNo)
  254. {
  255. DBG("Window setVisible matches current state, ignoring request\n");
  256. return;
  257. }
  258. if (fUsingEmbed)
  259. {
  260. DBG("Window setVisible cannot be called when embedded\n");
  261. return;
  262. }
  263. DBG("Window setVisible called\n");
  264. fVisible = yesNo;
  265. if (yesNo && fFirstInit)
  266. setSize(fView->width, fView->height, true);
  267. #if DGL_OS_WINDOWS
  268. if (yesNo)
  269. ShowWindow(hwnd, fFirstInit ? SW_SHOWNORMAL : SW_RESTORE);
  270. else
  271. ShowWindow(hwnd, SW_HIDE);
  272. UpdateWindow(hwnd);
  273. #elif DGL_OS_MAC
  274. puglImplSetVisible(fView, yesNo);
  275. #elif DGL_OS_LINUX
  276. if (yesNo)
  277. XMapRaised(xDisplay, xWindow);
  278. else
  279. XUnmapWindow(xDisplay, xWindow);
  280. XFlush(xDisplay);
  281. #endif
  282. if (yesNo)
  283. {
  284. if (fFirstInit)
  285. {
  286. fApp._oneShown();
  287. fFirstInit = false;
  288. }
  289. }
  290. else if (fModal.enabled)
  291. exec_fini();
  292. }
  293. // -------------------------------------------------------------------
  294. bool isResizable() const noexcept
  295. {
  296. return fResizable;
  297. }
  298. void setResizable(const bool yesNo)
  299. {
  300. if (fResizable == yesNo)
  301. {
  302. DBG("Window setResizable matches current state, ignoring request\n");
  303. return;
  304. }
  305. if (fUsingEmbed)
  306. {
  307. DBG("Window setResizable cannot be called when embedded\n");
  308. return;
  309. }
  310. DBG("Window setResizable called\n");
  311. fResizable = yesNo;
  312. setSize(fView->width, fView->height, true);
  313. }
  314. // -------------------------------------------------------------------
  315. int getWidth() const noexcept
  316. {
  317. return fView->width;
  318. }
  319. int getHeight() const noexcept
  320. {
  321. return fView->height;
  322. }
  323. Size<int> getSize() const noexcept
  324. {
  325. return Size<int>(fView->width, fView->height);
  326. }
  327. void setSize(unsigned int width, unsigned int height, const bool forced = false)
  328. {
  329. if (width == 0 || height == 0)
  330. {
  331. DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height);
  332. return;
  333. }
  334. if (fView->width == static_cast<int>(width) && fView->height == static_cast<int>(height) && ! forced)
  335. {
  336. DBG("Window setSize matches current size, ignoring request\n");
  337. return;
  338. }
  339. fView->width = width;
  340. fView->height = height;
  341. DBGp("Window setSize called %s\n", forced ? "(forced)" : "(not forced)");
  342. #if DGL_OS_WINDOWS
  343. int winFlags = WS_POPUPWINDOW | WS_CAPTION;
  344. if (fResizable)
  345. winFlags |= WS_SIZEBOX;
  346. RECT wr = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
  347. AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
  348. SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
  349. if (! forced)
  350. UpdateWindow(hwnd);
  351. #elif DGL_OS_MAC
  352. puglImplSetSize(fView, width, height, forced);
  353. #elif DGL_OS_LINUX
  354. XResizeWindow(xDisplay, xWindow, width, height);
  355. if (! fResizable)
  356. {
  357. XSizeHints sizeHints;
  358. memset(&sizeHints, 0, sizeof(sizeHints));
  359. sizeHints.flags = PMinSize|PMaxSize;
  360. sizeHints.min_width = width;
  361. sizeHints.min_height = height;
  362. sizeHints.max_width = width;
  363. sizeHints.max_height = height;
  364. XSetNormalHints(xDisplay, xWindow, &sizeHints);
  365. }
  366. if (! forced)
  367. XFlush(xDisplay);
  368. #endif
  369. repaint();
  370. }
  371. // -------------------------------------------------------------------
  372. void setTitle(const char* const title)
  373. {
  374. DBGp("Window setTitle \"%s\"\n", title);
  375. #if DGL_OS_WINDOWS
  376. SetWindowTextA(hwnd, title);
  377. #elif DGL_OS_MAC
  378. puglImplSetTitle(fView, title);
  379. #elif DGL_OS_LINUX
  380. XStoreName(xDisplay, xWindow, title);
  381. #endif
  382. }
  383. App& getApp() const noexcept
  384. {
  385. return fApp;
  386. }
  387. int getModifiers() const
  388. {
  389. return puglGetModifiers(fView);
  390. }
  391. uint32_t getEventTimestamp() const
  392. {
  393. return puglGetEventTimestamp(fView);
  394. }
  395. intptr_t getWindowId() const
  396. {
  397. return puglGetNativeWindow(fView);
  398. }
  399. // -------------------------------------------------------------------
  400. void addWidget(Widget* const widget)
  401. {
  402. fWidgets.push_back(widget);
  403. }
  404. void removeWidget(Widget* const widget)
  405. {
  406. fWidgets.remove(widget);
  407. }
  408. void idle()
  409. {
  410. puglProcessEvents(fView);
  411. if (fModal.enabled && fModal.parent != nullptr)
  412. fModal.parent->idle();
  413. }
  414. // -------------------------------------------------------------------
  415. void exec_init()
  416. {
  417. DBG("Window modal loop starting..."); DBGF;
  418. assert(fModal.parent != nullptr);
  419. if (fModal.parent == nullptr)
  420. {
  421. DBG("Failed, there's no modal parent!\n");
  422. return setVisible(true);
  423. }
  424. fModal.enabled = true;
  425. fModal.parent->fModal.childFocus = this;
  426. #if DGL_OS_WINDOWS
  427. // Center this window
  428. PuglInternals* const parentImpl = fModal.parent->fView->impl;
  429. RECT curRect;
  430. RECT parentRect;
  431. GetWindowRect(hwnd, &curRect);
  432. GetWindowRect(parentImpl->hwnd, &parentRect);
  433. int x = parentRect.left+(parentRect.right-curRect.right)/2;
  434. int y = parentRect.top +(parentRect.bottom-curRect.bottom)/2;
  435. SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  436. UpdateWindow(hwnd);
  437. #endif
  438. fModal.parent->setVisible(true);
  439. setVisible(true);
  440. DBG("Ok\n");
  441. }
  442. void exec_fini()
  443. {
  444. DBG("Window modal loop stopping..."); DBGF;
  445. fModal.enabled = false;
  446. if (fModal.parent != nullptr)
  447. fModal.parent->fModal.childFocus = nullptr;
  448. DBG("Ok\n");
  449. }
  450. // -------------------------------------------------------------------
  451. protected:
  452. void onDisplay()
  453. {
  454. //DBG("PUGL: onDisplay\n");
  455. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  456. FOR_EACH_WIDGET(it)
  457. {
  458. Widget* const widget(*it);
  459. if (widget->isVisible())
  460. widget->onDisplay();
  461. }
  462. }
  463. void onKeyboard(const bool press, const uint32_t key)
  464. {
  465. DBGp("PUGL: onKeyboard : %i %i\n", press, key);
  466. if (fModal.childFocus != nullptr)
  467. return fModal.childFocus->focus();
  468. FOR_EACH_WIDGET_INV(rit)
  469. {
  470. Widget* const widget(*rit);
  471. if (widget->isVisible() && widget->onKeyboard(press, key))
  472. break;
  473. }
  474. }
  475. void onMouse(const int button, const bool press, const int x, const int y)
  476. {
  477. DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y);
  478. if (fModal.childFocus != nullptr)
  479. return fModal.childFocus->focus();
  480. FOR_EACH_WIDGET_INV(rit)
  481. {
  482. Widget* const widget(*rit);
  483. if (widget->isVisible() && widget->onMouse(button, press, x, y))
  484. break;
  485. }
  486. }
  487. void onMotion(const int x, const int y)
  488. {
  489. DBGp("PUGL: onMotion : %i %i\n", x, y);
  490. if (fModal.childFocus != nullptr)
  491. return;
  492. FOR_EACH_WIDGET_INV(rit)
  493. {
  494. Widget* const widget(*rit);
  495. if (widget->isVisible() && widget->onMotion(x, y))
  496. break;
  497. }
  498. }
  499. void onScroll(const int x, const int y, const float dx, const float dy)
  500. {
  501. DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy);
  502. if (fModal.childFocus != nullptr)
  503. return;
  504. FOR_EACH_WIDGET_INV(rit)
  505. {
  506. Widget* const widget(*rit);
  507. if (widget->isVisible() && widget->onScroll(x, y, dx, dy))
  508. break;
  509. }
  510. }
  511. void onSpecial(const bool press, const Key key)
  512. {
  513. DBGp("PUGL: onSpecial : %i %i\n", press, key);
  514. if (fModal.childFocus != nullptr)
  515. return;
  516. FOR_EACH_WIDGET_INV(rit)
  517. {
  518. Widget* const widget(*rit);
  519. if (widget->isVisible() && widget->onSpecial(press, key))
  520. break;
  521. }
  522. }
  523. void onReshape(const int width, const int height)
  524. {
  525. DBGp("PUGL: onReshape : %i %i\n", width, height);
  526. FOR_EACH_WIDGET(it)
  527. {
  528. Widget* const widget(*it);
  529. widget->onReshape(width, height);
  530. }
  531. }
  532. void onClose()
  533. {
  534. DBG("PUGL: onClose\n");
  535. if (fModal.enabled && fModal.parent != nullptr)
  536. exec_fini();
  537. if (fModal.childFocus != nullptr)
  538. fModal.childFocus->onClose();
  539. FOR_EACH_WIDGET(it)
  540. {
  541. Widget* const widget(*it);
  542. widget->onClose();
  543. }
  544. close();
  545. }
  546. // -------------------------------------------------------------------
  547. private:
  548. App& fApp;
  549. Window* fSelf;
  550. PuglView* fView;
  551. bool fFirstInit;
  552. bool fVisible;
  553. bool fResizable;
  554. bool fUsingEmbed;
  555. std::list<Widget*> fWidgets;
  556. struct Modal {
  557. bool enabled;
  558. PrivateData* parent;
  559. PrivateData* childFocus;
  560. Modal()
  561. : enabled(false),
  562. parent(nullptr),
  563. childFocus(nullptr) {}
  564. Modal(PrivateData* const p)
  565. : enabled(false),
  566. parent(p),
  567. childFocus(nullptr) {}
  568. ~Modal()
  569. {
  570. assert(! enabled);
  571. assert(childFocus == nullptr);
  572. }
  573. } fModal;
  574. #if DGL_OS_WINDOWS
  575. HWND hwnd;
  576. #elif DGL_OS_LINUX
  577. Display* xDisplay;
  578. ::Window xWindow;
  579. #else
  580. char _dummy;
  581. #endif
  582. // -------------------------------------------------------------------
  583. // Callbacks
  584. #define handlePtr ((PrivateData*)puglGetHandle(view))
  585. static void onDisplayCallback(PuglView* view)
  586. {
  587. handlePtr->onDisplay();
  588. }
  589. static void onKeyboardCallback(PuglView* view, bool press, uint32_t key)
  590. {
  591. handlePtr->onKeyboard(press, key);
  592. }
  593. static void onMouseCallback(PuglView* view, int button, bool press, int x, int y)
  594. {
  595. handlePtr->onMouse(button, press, x, y);
  596. }
  597. static void onMotionCallback(PuglView* view, int x, int y)
  598. {
  599. handlePtr->onMotion(x, y);
  600. }
  601. static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy)
  602. {
  603. handlePtr->onScroll(x, y, dx, dy);
  604. }
  605. static void onSpecialCallback(PuglView* view, bool press, PuglKey key)
  606. {
  607. handlePtr->onSpecial(press, static_cast<Key>(key));
  608. }
  609. static void onReshapeCallback(PuglView* view, int width, int height)
  610. {
  611. handlePtr->onReshape(width, height);
  612. }
  613. static void onCloseCallback(PuglView* view)
  614. {
  615. handlePtr->onClose();
  616. }
  617. #undef handlePtr
  618. };
  619. // -----------------------------------------------------------------------
  620. // Window
  621. Window::Window(App& app)
  622. : pData(new PrivateData(app, this))
  623. {
  624. }
  625. Window::Window(App& app, Window& parent)
  626. : pData(new PrivateData(app, this, parent))
  627. {
  628. }
  629. Window::Window(App& app, intptr_t parentId)
  630. : pData(new PrivateData(app, this, parentId))
  631. {
  632. }
  633. Window::~Window()
  634. {
  635. delete pData;
  636. }
  637. void Window::setTransient(const intptr_t win)
  638. {
  639. pData->setTransient(win);
  640. }
  641. void Window::show()
  642. {
  643. pData->setVisible(true);
  644. }
  645. void Window::hide()
  646. {
  647. pData->setVisible(false);
  648. }
  649. void Window::close()
  650. {
  651. pData->close();
  652. }
  653. void Window::exec(bool lockWait)
  654. {
  655. pData->exec(lockWait);
  656. }
  657. void Window::focus()
  658. {
  659. pData->focus();
  660. }
  661. void Window::repaint()
  662. {
  663. pData->repaint();
  664. }
  665. bool Window::isVisible() const noexcept
  666. {
  667. return pData->isVisible();
  668. }
  669. void Window::setVisible(bool yesNo)
  670. {
  671. pData->setVisible(yesNo);
  672. }
  673. bool Window::isResizable() const noexcept
  674. {
  675. return pData->isResizable();
  676. }
  677. void Window::setResizable(bool yesNo)
  678. {
  679. pData->setResizable(yesNo);
  680. }
  681. int Window::getWidth() const noexcept
  682. {
  683. return pData->getWidth();
  684. }
  685. int Window::getHeight() const noexcept
  686. {
  687. return pData->getHeight();
  688. }
  689. Size<int> Window::getSize() const noexcept
  690. {
  691. return pData->getSize();
  692. }
  693. void Window::setSize(unsigned int width, unsigned int height)
  694. {
  695. pData->setSize(width, height);
  696. }
  697. void Window::setTitle(const char* title)
  698. {
  699. pData->setTitle(title);
  700. }
  701. App& Window::getApp() const noexcept
  702. {
  703. return pData->getApp();
  704. }
  705. int Window::getModifiers() const
  706. {
  707. return pData->getModifiers();
  708. }
  709. uint32_t Window::getEventTimestamp() const
  710. {
  711. return pData->getEventTimestamp();
  712. }
  713. intptr_t Window::getWindowId() const
  714. {
  715. return pData->getWindowId();
  716. }
  717. void Window::_addWidget(Widget* const widget)
  718. {
  719. pData->addWidget(widget);
  720. }
  721. void Window::_removeWidget(Widget* const widget)
  722. {
  723. pData->removeWidget(widget);
  724. }
  725. void Window::_idle()
  726. {
  727. pData->idle();
  728. }
  729. // -----------------------------------------------------------------------
  730. END_NAMESPACE_DGL
  731. #undef DBG
  732. #undef DBGF