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.

407 lines
11KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2020 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 "WindowPrivateData.hpp"
  17. #ifdef DGL_CAIRO
  18. # define PUGL_CAIRO
  19. # include "../Cairo.hpp"
  20. #endif
  21. #ifdef DGL_OPENGL
  22. # define PUGL_OPENGL
  23. # include "../OpenGL.hpp"
  24. #endif
  25. extern "C" {
  26. #include "pugl-upstream/src/implementation.c"
  27. #include "pugl-extra/extras.c"
  28. }
  29. #if defined(DISTRHO_OS_HAIKU)
  30. # define DGL_DEBUG_EVENTS
  31. # include "pugl-upstream/src/haiku.cpp"
  32. #elif defined(DISTRHO_OS_MAC)
  33. # define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE)
  34. # define PuglOpenGLView DISTRHO_JOIN_MACRO(PuglOpenGLView, DGL_NAMESPACE)
  35. # include "pugl-upstream/src/mac.m"
  36. #elif defined(DISTRHO_OS_WINDOWS)
  37. # include "ppugl-upstream/src/win.c"
  38. # undef max
  39. # undef min
  40. #else
  41. # define DGL_PUGL_USING_X11
  42. extern "C" {
  43. # include "pugl-upstream/src/x11.c"
  44. // # ifdef DGL_CAIRO
  45. // # include "pugl-upstream/src/x11_cairo.c"
  46. // # endif
  47. # ifdef DGL_OPENGL
  48. # include "pugl-upstream/src/x11_gl.c"
  49. # endif
  50. # define PUGL_DETAIL_X11_H_INCLUDED
  51. # include "pugl-extra/x11.c"
  52. }
  53. #endif
  54. #include <inttypes.h>
  55. #include <stdarg.h>
  56. #include <stdbool.h>
  57. #include <stdint.h>
  58. #include <stdio.h>
  59. #include <string.h>
  60. START_NAMESPACE_DGL
  61. // -----------------------------------------------------------------------
  62. void Window::PrivateData::init(const bool resizable)
  63. {
  64. if (fSelf == nullptr || fView == nullptr)
  65. {
  66. DGL_DBG("Failed!\n");
  67. return;
  68. }
  69. // #ifdef DGL_CAIRO
  70. // puglSetBackend(fView, puglCairoBackend());
  71. // #endif
  72. #ifdef DGL_OPENGL
  73. puglSetBackend(fView, puglGlBackend());
  74. #endif
  75. puglSetHandle(fView, this);
  76. puglSetViewHint(fView, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE);
  77. puglSetViewHint(fView, PUGL_IGNORE_KEY_REPEAT, PUGL_FALSE);
  78. puglSetEventFunc(fView, puglEventCallback);
  79. // #ifndef DGL_FILE_BROWSER_DISABLED
  80. // puglSetFileSelectedFunc(fView, fileBrowserSelectedCallback);
  81. // #endif
  82. fAppData->windows.push_back(fSelf);
  83. DGL_DBG("Success!\n");
  84. }
  85. void Window::PrivateData::setVisible(const bool visible)
  86. {
  87. if (fVisible == visible)
  88. {
  89. DGL_DBG("Window setVisible matches current state, ignoring request\n");
  90. return;
  91. }
  92. if (fUsingEmbed)
  93. {
  94. DGL_DBG("Window setVisible cannot be called when embedded\n");
  95. return;
  96. }
  97. DGL_DBG("Window setVisible called\n");
  98. fVisible = visible;
  99. if (visible)
  100. {
  101. #if 0 && defined(DISTRHO_OS_MAC)
  102. if (mWindow != nullptr)
  103. {
  104. if (mParentWindow != nullptr)
  105. [mParentWindow addChildWindow:mWindow
  106. ordered:NSWindowAbove];
  107. }
  108. #endif
  109. if (fFirstInit)
  110. {
  111. puglRealize(fView);
  112. #ifdef DISTRHO_OS_WINDOWS
  113. puglShowWindowCentered(fView);
  114. #else
  115. puglShowWindow(fView);
  116. #endif
  117. fAppData->oneWindowShown();
  118. fFirstInit = false;
  119. }
  120. else
  121. {
  122. #ifdef DISTRHO_OS_WINDOWS
  123. puglWin32RestoreWindow(fView);
  124. #else
  125. puglShowWindow(fView);
  126. #endif
  127. }
  128. }
  129. else
  130. {
  131. #if 0 && defined(DISTRHO_OS_MAC)
  132. if (mWindow != nullptr)
  133. {
  134. if (mParentWindow != nullptr)
  135. [mParentWindow removeChildWindow:mWindow];
  136. }
  137. #endif
  138. puglHideWindow(fView);
  139. // if (fModal.enabled)
  140. // exec_fini();
  141. }
  142. }
  143. void Window::PrivateData::windowSpecificIdle()
  144. {
  145. #if defined(DISTRHO_OS_WINDOWS) && !defined(DGL_FILE_BROWSER_DISABLED)
  146. if (fSelectedFile.isNotEmpty())
  147. {
  148. char* const buffer = fSelectedFile.getAndReleaseBuffer();
  149. fView->fileSelectedFunc(fView, buffer);
  150. std::free(buffer);
  151. }
  152. #endif
  153. if (fModal.enabled && fModal.parent != nullptr)
  154. fModal.parent->windowSpecificIdle();
  155. }
  156. // -----------------------------------------------------------------------
  157. static inline int
  158. printModifiers(const uint32_t mods)
  159. {
  160. return fprintf(stderr, "Modifiers:%s%s%s%s\n",
  161. (mods & PUGL_MOD_SHIFT) ? " Shift" : "",
  162. (mods & PUGL_MOD_CTRL) ? " Ctrl" : "",
  163. (mods & PUGL_MOD_ALT) ? " Alt" : "",
  164. (mods & PUGL_MOD_SUPER) ? " Super" : "");
  165. }
  166. static inline int
  167. printEvent(const PuglEvent* event, const char* prefix, const bool verbose)
  168. {
  169. #define FFMT "%6.1f"
  170. #define PFMT FFMT " " FFMT
  171. #define PRINT(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
  172. switch (event->type) {
  173. case PUGL_NOTHING:
  174. return 0;
  175. case PUGL_KEY_PRESS:
  176. return PRINT("%sKey press code %3u key U+%04X\n",
  177. prefix,
  178. event->key.keycode,
  179. event->key.key);
  180. case PUGL_KEY_RELEASE:
  181. return PRINT("%sKey release code %3u key U+%04X\n",
  182. prefix,
  183. event->key.keycode,
  184. event->key.key);
  185. case PUGL_TEXT:
  186. return PRINT("%sText entry code %3u char U+%04X (%s)\n",
  187. prefix,
  188. event->text.keycode,
  189. event->text.character,
  190. event->text.string);
  191. case PUGL_BUTTON_PRESS:
  192. case PUGL_BUTTON_RELEASE:
  193. return (PRINT("%sMouse %u %s at " PFMT " ",
  194. prefix,
  195. event->button.button,
  196. (event->type == PUGL_BUTTON_PRESS) ? "down" : "up ",
  197. event->button.x,
  198. event->button.y) +
  199. printModifiers(event->scroll.state));
  200. case PUGL_SCROLL:
  201. return (PRINT("%sScroll %5.1f %5.1f at " PFMT " ",
  202. prefix,
  203. event->scroll.dx,
  204. event->scroll.dy,
  205. event->scroll.x,
  206. event->scroll.y) +
  207. printModifiers(event->scroll.state));
  208. case PUGL_POINTER_IN:
  209. return PRINT("%sMouse enter at " PFMT "\n",
  210. prefix,
  211. event->crossing.x,
  212. event->crossing.y);
  213. case PUGL_POINTER_OUT:
  214. return PRINT("%sMouse leave at " PFMT "\n",
  215. prefix,
  216. event->crossing.x,
  217. event->crossing.y);
  218. case PUGL_FOCUS_IN:
  219. return PRINT("%sFocus in %i\n",
  220. prefix,
  221. event->focus.mode);
  222. case PUGL_FOCUS_OUT:
  223. return PRINT("%sFocus out %i\n",
  224. prefix,
  225. event->focus.mode);
  226. case PUGL_CLIENT:
  227. return PRINT("%sClient %" PRIXPTR " %" PRIXPTR "\n",
  228. prefix,
  229. event->client.data1,
  230. event->client.data2);
  231. case PUGL_TIMER:
  232. return PRINT("%sTimer %" PRIuPTR "\n", prefix, event->timer.id);
  233. default:
  234. break;
  235. }
  236. if (verbose) {
  237. switch (event->type) {
  238. case PUGL_CREATE:
  239. return fprintf(stderr, "%sCreate\n", prefix);
  240. case PUGL_DESTROY:
  241. return fprintf(stderr, "%sDestroy\n", prefix);
  242. case PUGL_MAP:
  243. return fprintf(stderr, "%sMap\n", prefix);
  244. case PUGL_UNMAP:
  245. return fprintf(stderr, "%sUnmap\n", prefix);
  246. case PUGL_UPDATE:
  247. return fprintf(stderr, "%sUpdate\n", prefix);
  248. case PUGL_CONFIGURE:
  249. return PRINT("%sConfigure " PFMT " " PFMT "\n",
  250. prefix,
  251. event->configure.x,
  252. event->configure.y,
  253. event->configure.width,
  254. event->configure.height);
  255. case PUGL_EXPOSE:
  256. return PRINT("%sExpose " PFMT " " PFMT "\n",
  257. prefix,
  258. event->expose.x,
  259. event->expose.y,
  260. event->expose.width,
  261. event->expose.height);
  262. case PUGL_CLOSE:
  263. return PRINT("%sClose\n", prefix);
  264. case PUGL_MOTION:
  265. return PRINT("%sMouse motion at " PFMT "\n",
  266. prefix,
  267. event->motion.x,
  268. event->motion.y);
  269. default:
  270. return PRINT("%sUnknown event type %d\n", prefix, (int)event->type);
  271. }
  272. }
  273. #undef PRINT
  274. #undef PFMT
  275. #undef FFMT
  276. return 0;
  277. }
  278. PuglStatus Window::PrivateData::puglEventCallback(PuglView* const view, const PuglEvent* const event)
  279. {
  280. printEvent(event, "", true);
  281. Window::PrivateData* const pData = (Window::PrivateData*)puglGetHandle(view);
  282. switch (event->type)
  283. {
  284. ///< No event
  285. case PUGL_NOTHING:
  286. break;
  287. ///< View created, a #PuglEventCreate
  288. case PUGL_CREATE:
  289. #ifdef DGL_PUGL_USING_X11
  290. if (! pData->fUsingEmbed)
  291. puglExtraSetWindowTypeAndPID(view);
  292. #endif
  293. break;
  294. ///< View destroyed, a #PuglEventDestroy
  295. case PUGL_DESTROY:
  296. break;
  297. ///< View moved/resized, a #PuglEventConfigure
  298. case PUGL_CONFIGURE:
  299. pData->onPuglReshape(event->configure.width, event->configure.height);
  300. break;
  301. case PUGL_MAP: ///< View made visible, a #PuglEventMap
  302. case PUGL_UNMAP: ///< View made invisible, a #PuglEventUnmap
  303. break;
  304. ///< View ready to draw, a #PuglEventUpdate
  305. case PUGL_UPDATE:
  306. break;
  307. ///< View must be drawn, a #PuglEventExpose
  308. case PUGL_EXPOSE:
  309. pData->onPuglDisplay();
  310. break;
  311. ///< View will be closed, a #PuglEventClose
  312. case PUGL_CLOSE:
  313. pData->onPuglClose();
  314. break;
  315. case PUGL_FOCUS_IN: ///< Keyboard focus entered view, a #PuglEventFocus
  316. case PUGL_FOCUS_OUT: ///< Keyboard focus left view, a #PuglEventFocus
  317. case PUGL_KEY_PRESS: ///< Key pressed, a #PuglEventKey
  318. case PUGL_KEY_RELEASE: ///< Key released, a #PuglEventKey
  319. case PUGL_TEXT: ///< Character entered, a #PuglEventText
  320. case PUGL_POINTER_IN: ///< Pointer entered view, a #PuglEventCrossing
  321. case PUGL_POINTER_OUT: ///< Pointer left view, a #PuglEventCrossing
  322. case PUGL_BUTTON_PRESS: ///< Mouse button pressed, a #PuglEventButton
  323. case PUGL_BUTTON_RELEASE: ///< Mouse button released, a #PuglEventButton
  324. case PUGL_MOTION: ///< Pointer moved, a #PuglEventMotion
  325. case PUGL_SCROLL: ///< Scrolled, a #PuglEventScroll
  326. case PUGL_CLIENT: ///< Custom client message, a #PuglEventClient
  327. case PUGL_TIMER: ///< Timer triggered, a #PuglEventTimer
  328. break;
  329. }
  330. return PUGL_SUCCESS;
  331. }
  332. // -----------------------------------------------------------------------
  333. void Window::PrivateData::Fallback::onDisplayBefore()
  334. {
  335. #ifdef DGL_OPENGL
  336. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  337. glLoadIdentity();
  338. #endif
  339. }
  340. void Window::PrivateData::Fallback::onDisplayAfter()
  341. {
  342. }
  343. void Window::PrivateData::Fallback::onReshape(const uint width, const uint height)
  344. {
  345. #ifdef DGL_OPENGL
  346. glEnable(GL_BLEND);
  347. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  348. glMatrixMode(GL_PROJECTION);
  349. glLoadIdentity();
  350. glOrtho(0.0, static_cast<GLdouble>(width), static_cast<GLdouble>(height), 0.0, 0.0, 1.0);
  351. glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height));
  352. glMatrixMode(GL_MODELVIEW);
  353. glLoadIdentity();
  354. #else
  355. // unused
  356. (void)width;
  357. (void)height;
  358. #endif
  359. }
  360. // -----------------------------------------------------------------------
  361. END_NAMESPACE_DGL