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.

1009 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 focus()
  241. {
  242. DBG("Window focus\n");
  243. #if defined(DISTRHO_OS_WINDOWS)
  244. SetForegroundWindow(hwnd);
  245. SetActiveWindow(hwnd);
  246. SetFocus(hwnd);
  247. #elif defined(DISTRHO_OS_MAC)
  248. // TODO
  249. //[NSApp activateIgnoringOtherApps:YES];
  250. //[xWindow makeKeyAndOrderFront:xWindow];
  251. #elif defined(DISTRHO_OS_LINUX)
  252. XRaiseWindow(xDisplay, xWindow);
  253. XSetInputFocus(xDisplay, xWindow, RevertToPointerRoot, CurrentTime);
  254. XFlush(xDisplay);
  255. #endif
  256. }
  257. void repaint()
  258. {
  259. //DBG("Window repaint\n");
  260. puglPostRedisplay(fView);
  261. }
  262. // -------------------------------------------------------------------
  263. bool isVisible() const noexcept
  264. {
  265. return fVisible;
  266. }
  267. void setVisible(const bool yesNo)
  268. {
  269. if (fVisible == yesNo)
  270. {
  271. DBG("Window setVisible matches current state, ignoring request\n");
  272. return;
  273. }
  274. if (fUsingEmbed)
  275. {
  276. DBG("Window setVisible cannot be called when embedded\n");
  277. return;
  278. }
  279. DBG("Window setVisible called\n");
  280. fVisible = yesNo;
  281. if (yesNo && fFirstInit)
  282. setSize(static_cast<uint>(fView->width), static_cast<uint>(fView->height), true);
  283. #if defined(DISTRHO_OS_WINDOWS)
  284. if (yesNo)
  285. ShowWindow(hwnd, fFirstInit ? SW_SHOWNORMAL : SW_RESTORE);
  286. else
  287. ShowWindow(hwnd, SW_HIDE);
  288. UpdateWindow(hwnd);
  289. #elif defined(DISTRHO_OS_MAC)
  290. if (yesNo)
  291. [xWindow setIsVisible:YES];
  292. else
  293. [xWindow setIsVisible:NO];
  294. #elif defined(DISTRHO_OS_LINUX)
  295. if (yesNo)
  296. XMapRaised(xDisplay, xWindow);
  297. else
  298. XUnmapWindow(xDisplay, xWindow);
  299. XFlush(xDisplay);
  300. #endif
  301. if (yesNo)
  302. {
  303. if (fFirstInit)
  304. {
  305. fApp.pData->oneShown();
  306. fFirstInit = false;
  307. }
  308. }
  309. else if (fModal.enabled)
  310. exec_fini();
  311. }
  312. // -------------------------------------------------------------------
  313. bool isResizable() const noexcept
  314. {
  315. return fResizable;
  316. }
  317. void setResizable(const bool yesNo)
  318. {
  319. if (fResizable == yesNo)
  320. {
  321. DBG("Window setResizable matches current state, ignoring request\n");
  322. return;
  323. }
  324. if (fUsingEmbed)
  325. {
  326. DBG("Window setResizable cannot be called when embedded\n");
  327. return;
  328. }
  329. DBG("Window setResizable called\n");
  330. fResizable = yesNo;
  331. setSize(static_cast<uint>(fView->width), static_cast<uint>(fView->height), true);
  332. }
  333. // -------------------------------------------------------------------
  334. int getWidth() const noexcept
  335. {
  336. return fView->width;
  337. }
  338. int getHeight() const noexcept
  339. {
  340. return fView->height;
  341. }
  342. Size<int> getSize() const noexcept
  343. {
  344. return Size<int>(fView->width, fView->height);
  345. }
  346. void setSize(uint width, uint height, const bool forced = false)
  347. {
  348. if (width == 0 || height == 0)
  349. {
  350. DBGp("Window setSize called with invalid value(s) %i %i, ignoring request\n", width, height);
  351. return;
  352. }
  353. if (fView->width == static_cast<int>(width) && fView->height == static_cast<int>(height) && ! forced)
  354. {
  355. DBGp("Window setSize matches current size, ignoring request (%i %i)\n", width, height);
  356. return;
  357. }
  358. fView->width = static_cast<int>(width);
  359. fView->height = static_cast<int>(height);
  360. DBGp("Window setSize called %s, size %i %i\n", forced ? "(forced)" : "(not forced)", width, height);
  361. #if defined(DISTRHO_OS_WINDOWS)
  362. int winFlags = WS_POPUPWINDOW | WS_CAPTION;
  363. if (fResizable)
  364. winFlags |= WS_SIZEBOX;
  365. RECT wr = { 0, 0, static_cast<long>(width), static_cast<long>(height) };
  366. AdjustWindowRectEx(&wr, winFlags, FALSE, WS_EX_TOPMOST);
  367. SetWindowPos(hwnd, 0, 0, 0, wr.right-wr.left, wr.bottom-wr.top, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
  368. if (! forced)
  369. UpdateWindow(hwnd);
  370. #elif defined(DISTRHO_OS_MAC)
  371. [xWindow setContentSize:NSMakeSize(width, height)];
  372. # if 0
  373. NSRect frame = [xWindow frame];
  374. frame.origin.y -= height - frame.size.height;
  375. frame.size.width = width;
  376. frame.size.height = height+20;
  377. //if (forced)
  378. // [xWindow setFrame:frame];
  379. //else
  380. [xWindow setFrame:frame display:YES animate:NO];
  381. # endif
  382. #elif defined(DISTRHO_OS_LINUX)
  383. XResizeWindow(xDisplay, xWindow, width, height);
  384. if (! fResizable)
  385. {
  386. XSizeHints sizeHints;
  387. memset(&sizeHints, 0, sizeof(sizeHints));
  388. sizeHints.flags = PSize|PMinSize|PMaxSize;
  389. sizeHints.width = static_cast<int>(width);
  390. sizeHints.height = static_cast<int>(height);
  391. sizeHints.min_width = static_cast<int>(width);
  392. sizeHints.min_height = static_cast<int>(height);
  393. sizeHints.max_width = static_cast<int>(width);
  394. sizeHints.max_height = static_cast<int>(height);
  395. XSetNormalHints(xDisplay, xWindow, &sizeHints);
  396. }
  397. if (! forced)
  398. XFlush(xDisplay);
  399. #endif
  400. repaint();
  401. }
  402. // -------------------------------------------------------------------
  403. void setTitle(const char* const title)
  404. {
  405. DBGp("Window setTitle \"%s\"\n", title);
  406. #if defined(DISTRHO_OS_WINDOWS)
  407. SetWindowTextA(hwnd, title);
  408. #elif defined(DISTRHO_OS_MAC)
  409. NSString* titleString = [[NSString alloc]
  410. initWithBytes:title
  411. length:strlen(title)
  412. encoding:NSUTF8StringEncoding];
  413. [xWindow setTitle:titleString];
  414. #elif defined(DISTRHO_OS_LINUX)
  415. XStoreName(xDisplay, xWindow, title);
  416. #endif
  417. }
  418. void setTransientWinId(const intptr_t winId)
  419. {
  420. #if defined(DISTRHO_OS_LINUX)
  421. XSetTransientForHint(xDisplay, xWindow, static_cast< ::Window>(winId));
  422. #else
  423. return;
  424. // unused
  425. (void)winId;
  426. #endif
  427. }
  428. // -------------------------------------------------------------------
  429. App& getApp() const noexcept
  430. {
  431. return fApp;
  432. }
  433. int getModifiers() const
  434. {
  435. return puglGetModifiers(fView);
  436. }
  437. uint getEventTimestamp() const
  438. {
  439. return puglGetEventTimestamp(fView);
  440. }
  441. intptr_t getWindowId() const
  442. {
  443. return puglGetNativeWindow(fView);
  444. }
  445. // -------------------------------------------------------------------
  446. void addWidget(Widget* const widget)
  447. {
  448. fWidgets.push_back(widget);
  449. }
  450. void removeWidget(Widget* const widget)
  451. {
  452. fWidgets.remove(widget);
  453. }
  454. void idle()
  455. {
  456. puglProcessEvents(fView);
  457. #ifdef DISTRHO_OS_MAC
  458. if (fNeedsIdle)
  459. {
  460. NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
  461. NSEvent* event;
  462. static const NSUInteger eventMask = (NSLeftMouseDownMask | NSLeftMouseUpMask |
  463. NSRightMouseDownMask | NSRightMouseUpMask |
  464. NSMouseMovedMask |
  465. NSLeftMouseDraggedMask | NSRightMouseDraggedMask |
  466. NSMouseEnteredMask | NSMouseExitedMask |
  467. NSKeyDownMask | NSKeyUpMask |
  468. NSFlagsChangedMask |
  469. NSCursorUpdateMask | NSScrollWheelMask);
  470. for (;;) {
  471. event = [xWindow
  472. nextEventMatchingMask:eventMask
  473. untilDate:[NSDate distantPast]
  474. inMode:NSEventTrackingRunLoopMode
  475. dequeue:YES];
  476. if (event == nil)
  477. break;
  478. [xWindow sendEvent: event];
  479. }
  480. [pool release];
  481. }
  482. #endif
  483. if (fModal.enabled && fModal.parent != nullptr)
  484. fModal.parent->idle();
  485. }
  486. // -------------------------------------------------------------------
  487. void exec_init()
  488. {
  489. DBG("Window modal loop starting..."); DBGF;
  490. DISTRHO_SAFE_ASSERT_RETURN(fModal.parent != nullptr, setVisible(true));
  491. fModal.enabled = true;
  492. fModal.parent->fModal.childFocus = this;
  493. #ifdef DISTRHO_OS_WINDOWS
  494. // Center this window
  495. PuglInternals* const parentImpl = fModal.parent->fView->impl;
  496. RECT curRect;
  497. RECT parentRect;
  498. GetWindowRect(hwnd, &curRect);
  499. GetWindowRect(parentImpl->hwnd, &parentRect);
  500. int x = parentRect.left+(parentRect.right-curRect.right)/2;
  501. int y = parentRect.top +(parentRect.bottom-curRect.bottom)/2;
  502. SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER);
  503. UpdateWindow(hwnd);
  504. #endif
  505. fModal.parent->setVisible(true);
  506. setVisible(true);
  507. DBG("Ok\n");
  508. }
  509. void exec_fini()
  510. {
  511. DBG("Window modal loop stopping..."); DBGF;
  512. fModal.enabled = false;
  513. if (fModal.parent != nullptr)
  514. fModal.parent->fModal.childFocus = nullptr;
  515. DBG("Ok\n");
  516. }
  517. // -------------------------------------------------------------------
  518. void onDisplay()
  519. {
  520. //DBG("PUGL: onDisplay\n");
  521. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  522. glLoadIdentity();
  523. FOR_EACH_WIDGET(it)
  524. {
  525. Widget* const widget(*it);
  526. if (widget->isVisible())
  527. widget->onDisplay();
  528. }
  529. }
  530. void onKeyboard(const bool press, const uint key)
  531. {
  532. DBGp("PUGL: onKeyboard : %i %i\n", press, key);
  533. if (fModal.childFocus != nullptr)
  534. return fModal.childFocus->focus();
  535. FOR_EACH_WIDGET_INV(rit)
  536. {
  537. Widget* const widget(*rit);
  538. if (widget->isVisible() && widget->onKeyboard(press, key))
  539. break;
  540. }
  541. }
  542. void onMouse(const int button, const bool press, const int x, const int y)
  543. {
  544. DBGp("PUGL: onMouse : %i %i %i %i\n", button, press, x, y);
  545. if (fModal.childFocus != nullptr)
  546. return fModal.childFocus->focus();
  547. FOR_EACH_WIDGET_INV(rit)
  548. {
  549. Widget* const widget(*rit);
  550. if (widget->isVisible() && widget->onMouse(button, press, x, y))
  551. break;
  552. }
  553. }
  554. void onMotion(const int x, const int y)
  555. {
  556. DBGp("PUGL: onMotion : %i %i\n", x, y);
  557. if (fModal.childFocus != nullptr)
  558. return;
  559. FOR_EACH_WIDGET_INV(rit)
  560. {
  561. Widget* const widget(*rit);
  562. if (widget->isVisible() && widget->onMotion(x, y))
  563. break;
  564. }
  565. }
  566. void onScroll(const int x, const int y, const float dx, const float dy)
  567. {
  568. DBGp("PUGL: onScroll : %i %i %f %f\n", x, y, dx, dy);
  569. if (fModal.childFocus != nullptr)
  570. return;
  571. FOR_EACH_WIDGET_INV(rit)
  572. {
  573. Widget* const widget(*rit);
  574. if (widget->isVisible() && widget->onScroll(x, y, dx, dy))
  575. break;
  576. }
  577. }
  578. void onSpecial(const bool press, const Key key)
  579. {
  580. DBGp("PUGL: onSpecial : %i %i\n", press, key);
  581. if (fModal.childFocus != nullptr)
  582. return;
  583. FOR_EACH_WIDGET_INV(rit)
  584. {
  585. Widget* const widget(*rit);
  586. if (widget->isVisible() && widget->onSpecial(press, key))
  587. break;
  588. }
  589. }
  590. void onReshape(const int width, const int height)
  591. {
  592. DBGp("PUGL: onReshape : %i %i\n", width, height);
  593. FOR_EACH_WIDGET(it)
  594. {
  595. Widget* const widget(*it);
  596. widget->onReshape(width, height);
  597. }
  598. }
  599. void onClose()
  600. {
  601. DBG("PUGL: onClose\n");
  602. if (fModal.enabled && fModal.parent != nullptr)
  603. exec_fini();
  604. if (fModal.childFocus != nullptr)
  605. fModal.childFocus->onClose();
  606. FOR_EACH_WIDGET(it)
  607. {
  608. Widget* const widget(*it);
  609. widget->onClose();
  610. }
  611. close();
  612. }
  613. // -------------------------------------------------------------------
  614. App& fApp;
  615. Window* fSelf;
  616. PuglView* fView;
  617. bool fFirstInit;
  618. bool fVisible;
  619. bool fResizable;
  620. bool fUsingEmbed;
  621. std::list<Widget*> fWidgets;
  622. struct Modal {
  623. bool enabled;
  624. PrivateData* parent;
  625. PrivateData* childFocus;
  626. Modal()
  627. : enabled(false),
  628. parent(nullptr),
  629. childFocus(nullptr) {}
  630. Modal(PrivateData* const p)
  631. : enabled(false),
  632. parent(p),
  633. childFocus(nullptr) {}
  634. ~Modal()
  635. {
  636. DISTRHO_SAFE_ASSERT(! enabled);
  637. DISTRHO_SAFE_ASSERT(childFocus == nullptr);
  638. }
  639. } fModal;
  640. #if defined(DISTRHO_OS_WINDOWS)
  641. HWND hwnd;
  642. #elif defined(DISTRHO_OS_LINUX)
  643. Display* xDisplay;
  644. ::Window xWindow;
  645. #elif defined(DISTRHO_OS_MAC)
  646. bool fNeedsIdle;
  647. id xWindow;
  648. #else
  649. char _dummy;
  650. #endif
  651. // -------------------------------------------------------------------
  652. // Callbacks
  653. #define handlePtr ((PrivateData*)puglGetHandle(view))
  654. static void onDisplayCallback(PuglView* view)
  655. {
  656. handlePtr->onDisplay();
  657. }
  658. static void onKeyboardCallback(PuglView* view, bool press, uint32_t key)
  659. {
  660. handlePtr->onKeyboard(press, key);
  661. }
  662. static void onMouseCallback(PuglView* view, int button, bool press, int x, int y)
  663. {
  664. handlePtr->onMouse(button, press, x, y);
  665. }
  666. static void onMotionCallback(PuglView* view, int x, int y)
  667. {
  668. handlePtr->onMotion(x, y);
  669. }
  670. static void onScrollCallback(PuglView* view, int x, int y, float dx, float dy)
  671. {
  672. handlePtr->onScroll(x, y, dx, dy);
  673. }
  674. static void onSpecialCallback(PuglView* view, bool press, PuglKey key)
  675. {
  676. handlePtr->onSpecial(press, static_cast<Key>(key));
  677. }
  678. static void onReshapeCallback(PuglView* view, int width, int height)
  679. {
  680. handlePtr->onReshape(width, height);
  681. }
  682. static void onCloseCallback(PuglView* view)
  683. {
  684. handlePtr->onClose();
  685. }
  686. #undef handlePtr
  687. };
  688. // -----------------------------------------------------------------------
  689. // Window
  690. Window::Window(App& app)
  691. : pData(new PrivateData(app, this))
  692. {
  693. }
  694. Window::Window(App& app, Window& parent)
  695. : pData(new PrivateData(app, this, parent))
  696. {
  697. }
  698. Window::Window(App& app, intptr_t parentId)
  699. : pData(new PrivateData(app, this, parentId))
  700. {
  701. }
  702. Window::~Window()
  703. {
  704. delete pData;
  705. }
  706. void Window::show()
  707. {
  708. pData->setVisible(true);
  709. }
  710. void Window::hide()
  711. {
  712. pData->setVisible(false);
  713. }
  714. void Window::close()
  715. {
  716. pData->close();
  717. }
  718. void Window::exec(bool lockWait)
  719. {
  720. pData->exec(lockWait);
  721. }
  722. void Window::focus()
  723. {
  724. pData->focus();
  725. }
  726. void Window::repaint()
  727. {
  728. pData->repaint();
  729. }
  730. bool Window::isVisible() const noexcept
  731. {
  732. return pData->isVisible();
  733. }
  734. void Window::setVisible(bool yesNo)
  735. {
  736. pData->setVisible(yesNo);
  737. }
  738. bool Window::isResizable() const noexcept
  739. {
  740. return pData->isResizable();
  741. }
  742. void Window::setResizable(bool yesNo)
  743. {
  744. pData->setResizable(yesNo);
  745. }
  746. int Window::getWidth() const noexcept
  747. {
  748. return pData->getWidth();
  749. }
  750. int Window::getHeight() const noexcept
  751. {
  752. return pData->getHeight();
  753. }
  754. Size<int> Window::getSize() const noexcept
  755. {
  756. return pData->getSize();
  757. }
  758. void Window::setSize(uint width, uint height)
  759. {
  760. pData->setSize(width, height);
  761. }
  762. void Window::setTitle(const char* title)
  763. {
  764. pData->setTitle(title);
  765. }
  766. void Window::setTransientWinId(intptr_t winId)
  767. {
  768. pData->setTransientWinId(winId);
  769. }
  770. App& Window::getApp() const noexcept
  771. {
  772. return pData->getApp();
  773. }
  774. int Window::getModifiers() const
  775. {
  776. return pData->getModifiers();
  777. }
  778. uint Window::getEventTimestamp() const
  779. {
  780. return pData->getEventTimestamp();
  781. }
  782. intptr_t Window::getWindowId() const
  783. {
  784. return pData->getWindowId();
  785. }
  786. void Window::_addWidget(Widget* const widget)
  787. {
  788. pData->addWidget(widget);
  789. }
  790. void Window::_removeWidget(Widget* const widget)
  791. {
  792. pData->removeWidget(widget);
  793. }
  794. void Window::_idle()
  795. {
  796. pData->idle();
  797. }
  798. // -----------------------------------------------------------------------
  799. void Window::addIdleCallback(IdleCallback* const callback)
  800. {
  801. DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,)
  802. pData->fApp.pData->idleCallbacks.push_back(callback);
  803. }
  804. void Window::removeIdleCallback(IdleCallback* const callback)
  805. {
  806. DISTRHO_SAFE_ASSERT_RETURN(callback != nullptr,)
  807. pData->fApp.pData->idleCallbacks.remove(callback);
  808. }
  809. // -----------------------------------------------------------------------
  810. END_NAMESPACE_DGL
  811. #undef DBG
  812. #undef DBGF