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.

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