DISTRHO Plugin Framework
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.

975 lines
24KB

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