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.

378 lines
8.2KB

  1. /*
  2. Copyright 2019 Filipe Coelho <falktx@falktx.com>
  3. Permission to use, copy, modify, and/or distribute this software for any
  4. purpose with or without fee is hereby granted, provided that the above
  5. copyright notice and this permission notice appear in all copies.
  6. THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  7. WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  8. MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  9. ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  10. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  11. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  12. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  13. */
  14. /**
  15. @file pugl_haiku.cpp BeOS/HaikuOS Pugl Implementation.
  16. */
  17. #include <Application.h>
  18. #include <interface/Window.h>
  19. #ifdef PUGL_CAIRO
  20. #include <cairo/cairo.h>
  21. typedef BView BViewType;
  22. #endif
  23. #ifdef PUGL_OPENGL
  24. #include <GL/gl.h>
  25. #include <opengl/GLView.h>
  26. typedef BGLView BViewType;
  27. #endif
  28. #include "pugl_internal.h"
  29. class DWindow;
  30. struct PuglInternalsImpl {
  31. BApplication* app;
  32. BViewType* view;
  33. DWindow* window;
  34. };
  35. static void
  36. puglReshape(PuglView* view, int width, int height)
  37. {
  38. puglEnterContext(view);
  39. if (view->reshapeFunc) {
  40. view->reshapeFunc(view, width, height);
  41. } else {
  42. puglDefaultReshape(width, height);
  43. }
  44. puglLeaveContext(view, false);
  45. view->width = width;
  46. view->height = height;
  47. }
  48. static void
  49. puglDisplay(PuglView* view)
  50. {
  51. puglEnterContext(view);
  52. view->redisplay = false;
  53. if (view->displayFunc) {
  54. view->displayFunc(view);
  55. }
  56. puglLeaveContext(view, true);
  57. }
  58. PuglInternals*
  59. puglInitInternals()
  60. {
  61. return (PuglInternals*)calloc(1, sizeof(PuglInternals));
  62. }
  63. void
  64. puglEnterContext(PuglView* view)
  65. {
  66. #ifdef PUGL_OPENGL
  67. PuglInternals* impl = view->impl;
  68. // FIXME without the first unlock we freeze
  69. impl->view->UnlockGL();
  70. impl->view->LockGL();
  71. #endif
  72. }
  73. void
  74. puglLeaveContext(PuglView* view, bool flush)
  75. {
  76. #ifdef PUGL_OPENGL
  77. PuglInternals* impl = view->impl;
  78. if (flush)
  79. impl->view->SwapBuffers(true);
  80. impl->view->UnlockGL();
  81. #endif
  82. }
  83. class DView : public BViewType
  84. {
  85. public:
  86. #ifdef PUGL_CAIRO
  87. DView(PuglView* const v)
  88. : BView(nullptr,
  89. B_FULL_UPDATE_ON_RESIZE|B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE),
  90. puglView(v) {}
  91. #endif
  92. #ifdef PUGL_OPENGL
  93. DView(PuglView* const v)
  94. : BGLView(BRect(512.0f),
  95. "DPF-GLView",
  96. 0x0, // resize mode
  97. B_FULL_UPDATE_ON_RESIZE|B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE,
  98. BGL_RGB /*|BGL_DOUBLE|BGL_ALPHA|BGL_DEPTH|BGL_STENCIL*/),
  99. puglView(v) {}
  100. #endif
  101. protected:
  102. void Draw(BRect updateRect) override
  103. {
  104. d_stdout("%s %i", __func__, __LINE__);
  105. puglDisplay(puglView);
  106. d_stdout("%s %i", __func__, __LINE__);
  107. #ifdef PUGL_OPENGL
  108. BGLView::Draw(updateRect);
  109. #endif
  110. d_stdout("%s %i", __func__, __LINE__);
  111. }
  112. void MouseDown(BPoint where) override
  113. {
  114. if (puglView->mouseFunc) {
  115. // puglView->event_timestamp_ms = GetMessageTime();
  116. puglView->mouseFunc(puglView, 1, true, where.x, where.y);
  117. }
  118. }
  119. void MouseUp(BPoint where) override
  120. {
  121. if (puglView->mouseFunc) {
  122. // puglView->event_timestamp_ms = GetMessageTime();
  123. puglView->mouseFunc(puglView, 1, false, where.x, where.y);
  124. }
  125. }
  126. void MouseMoved(BPoint where, uint32, const BMessage*) override
  127. {
  128. if (puglView->motionFunc) {
  129. // puglView->event_timestamp_ms = GetMessageTime();
  130. puglView->motionFunc(puglView, where.x, where.y);
  131. }
  132. }
  133. void KeyDown(const char* bytes, int32 numBytes) override
  134. {
  135. d_stdout("KeyDown %s %i", bytes, numBytes);
  136. if (numBytes != 1)
  137. return; // TODO
  138. if (puglView->keyboardFunc) {
  139. puglView->keyboardFunc(puglView, true, bytes[0]);
  140. }
  141. }
  142. void KeyUp(const char* bytes, int32 numBytes) override
  143. {
  144. if (numBytes != 1)
  145. return; // TODO
  146. if (puglView->keyboardFunc) {
  147. puglView->keyboardFunc(puglView, false, bytes[0]);
  148. }
  149. }
  150. void FrameResized(float newWidth, float newHeight) override
  151. {
  152. d_stdout("%s %i", __func__, __LINE__);
  153. const int width = static_cast<int>(newWidth);
  154. const int height = static_cast<int>(newHeight);
  155. puglReshape(puglView, width, height);
  156. d_stdout("%s %i", __func__, __LINE__);
  157. puglView->width = width;
  158. puglView->height = height;
  159. d_stdout("%s %i", __func__, __LINE__);
  160. #ifdef PUGL_OPENGL
  161. BGLView::FrameResized(newWidth, newHeight);
  162. #endif
  163. d_stdout("%s %i", __func__, __LINE__);
  164. }
  165. private:
  166. PuglView* const puglView;
  167. };
  168. class DWindow : public BWindow
  169. {
  170. public:
  171. DWindow(PuglView* const v)
  172. : BWindow(BRect(1.0f), "DPF-Window", B_TITLED_WINDOW, 0x0),
  173. puglView(v),
  174. needsQuit(true)
  175. {
  176. }
  177. bool NeedsQuit() const
  178. {
  179. return needsQuit;
  180. }
  181. protected:
  182. bool QuitRequested() override
  183. {
  184. d_stdout("%s %i", __func__, __LINE__);
  185. if (puglView->closeFunc) {
  186. puglView->closeFunc(puglView);
  187. puglView->redisplay = false;
  188. }
  189. needsQuit = false;
  190. d_stdout("%s %i", __func__, __LINE__);
  191. return true;
  192. }
  193. private:
  194. PuglView* const puglView;
  195. bool needsQuit;
  196. };
  197. int
  198. puglCreateWindow(PuglView* view, const char* title)
  199. {
  200. PuglInternals* impl = view->impl;
  201. if (be_app == nullptr)
  202. {
  203. status_t status;
  204. BApplication* const app = new BApplication("application/x-vnd.dpf-application", &status);
  205. if (status != B_OK)
  206. {
  207. d_stdout("app status error %u", status);
  208. delete app;
  209. return 1;
  210. }
  211. impl->app = app;
  212. }
  213. if (view->parent == 0) {
  214. impl->window = new DWindow(view);
  215. impl->window->Lock();
  216. }
  217. impl->view = new DView(view);
  218. if (view->parent != 0) {
  219. BView* const pview = (BView*)view->parent;
  220. pview->AddChild(impl->view);
  221. impl->view->LockGL();
  222. return 0;
  223. }
  224. if (title != nullptr) {
  225. impl->window->SetTitle(title);
  226. }
  227. impl->window->AddChild(impl->view);
  228. puglEnterContext(view);
  229. impl->window->Unlock();
  230. return 0;
  231. }
  232. void
  233. puglShowWindow(PuglView* view)
  234. {
  235. PuglInternals* impl = view->impl;
  236. if (impl->window != nullptr)
  237. impl->window->Show();
  238. else
  239. impl->view->Show();
  240. }
  241. void
  242. puglHideWindow(PuglView* view)
  243. {
  244. PuglInternals* impl = view->impl;
  245. if (impl->window != nullptr)
  246. impl->window->Hide();
  247. else
  248. impl->view->Show();
  249. }
  250. void
  251. puglDestroy(PuglView* view)
  252. {
  253. PuglInternals* impl = view->impl;
  254. if (impl->window != nullptr)
  255. {
  256. // impl->window->Lock();
  257. puglLeaveContext(view, false);
  258. impl->window->RemoveChild(impl->view);
  259. // impl->window->Unlock();
  260. if (impl->window->NeedsQuit())
  261. impl->window->Quit();
  262. }
  263. delete impl->view;
  264. impl->view = nullptr;
  265. impl->window = nullptr;
  266. if (impl->app != nullptr && impl->app->CountWindows() == 0)
  267. {
  268. d_stdout("deleting app");
  269. delete impl->app;
  270. impl->app = nullptr;
  271. } else
  272. d_stdout("NOT deleting app");
  273. }
  274. PuglStatus
  275. puglProcessEvents(PuglView* view)
  276. {
  277. return PUGL_SUCCESS;
  278. }
  279. void
  280. puglPostRedisplay(PuglView* view)
  281. {
  282. view->redisplay = true;
  283. view->impl->view->Invalidate();
  284. }
  285. PuglNativeWindow
  286. puglGetNativeWindow(PuglView* view)
  287. {
  288. PuglInternals* impl = view->impl;
  289. #ifdef PUGL_OPENGL
  290. // return (PuglNativeWindow)impl->view->EmbeddedView();
  291. #endif
  292. return (PuglNativeWindow)impl->view;
  293. }
  294. void*
  295. puglGetContext(PuglView* view)
  296. {
  297. return NULL;
  298. }
  299. int
  300. puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect)
  301. {
  302. PuglInternals* impl = view->impl;
  303. d_stdout("puglUpdateGeometryConstraints %i %i %i %i", min_width, min_height, view->width, view->height);
  304. impl->window->SetSizeLimits(min_width,
  305. view->user_resizable ? 4096 : min_width,
  306. min_height,
  307. view->user_resizable ? 4096 : min_height);
  308. return 0;
  309. // TODO
  310. (void)aspect;
  311. }