DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

haiku.cpp (8180B)


      1 // Copyright 2012-2022 David Robillard <d@drobilla.net>
      2 // Copyright 2021-2022 Filipe Coelho <falktx@falktx.com>
      3 // SPDX-License-Identifier: ISC
      4 
      5 #include "haiku.h"
      6 
      7 #include "../pugl-upstream/src/internal.h"
      8 
      9 class PuglHaikuView : public BView
     10 {
     11     PuglView* const view;
     12 
     13 public:
     14     PuglHaikuView(PuglView* const v)
     15         : BView(NULL, B_FULL_UPDATE_ON_RESIZE|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE),
     16           view(v) {}
     17 
     18 protected:
     19     void GetPreferredSize(float* width, float* height) override
     20     {
     21         d_stdout("%s %i", __func__, __LINE__);
     22         if (width != nullptr)
     23             *width = view->frame.width;
     24         if (height != nullptr)
     25             *height = view->frame.height;
     26         d_stdout("%s %i", __func__, __LINE__);
     27     }
     28 };
     29 
     30 class PuglHaikuWindow : public BWindow
     31 {
     32     PuglView* const view;
     33 
     34 public:
     35     PuglHaikuWindow(PuglView* const v)
     36         : BWindow(BRect(1.0f), "DPF-Window", B_TITLED_WINDOW, 0x0),
     37           view(v) {}
     38 
     39 // protected:
     40 //     bool QuitRequested() override
     41 //     {
     42 //         d_stdout("%s %i", __func__, __LINE__);
     43 //         if (puglView->closeFunc) {
     44 //             puglView->closeFunc(puglView);
     45 //             puglView->redisplay = false;
     46 //         }
     47 //         needsQuit = false;
     48 //         d_stdout("%s %i", __func__, __LINE__);
     49 //         return true;
     50 //     }
     51 };
     52 
     53 BApplication* s_app = NULL;
     54 
     55 PuglWorldInternals*
     56 puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags)
     57 {
     58   if (!s_app) {
     59     status_t status;
     60     s_app = new BApplication("application/x-vnd.pugl-application", &status);
     61     
     62     if (status != B_OK) {
     63       delete s_app;
     64       return NULL;
     65     }
     66   }
     67 
     68   PuglWorldInternals* impl =
     69     (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals));
     70 
     71   impl->app = s_app;
     72   return impl;
     73 }
     74 
     75 void*
     76 puglGetNativeWorld(PuglWorld* const world)
     77 {
     78   return world->impl->app;
     79 }
     80 
     81 PuglInternals*
     82 puglInitViewInternals(PuglWorld* const world)
     83 {
     84   PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals));
     85 
     86   return impl;
     87 }
     88 
     89 PuglStatus
     90 puglRealize(PuglView* const view)
     91 {
     92   PuglInternals* const impl    = view->impl;
     93   PuglStatus           st      = PUGL_SUCCESS;
     94 
     95   // Ensure that we're unrealized and that a reasonable backend has been set
     96   if (impl->view) {
     97     return PUGL_FAILURE;
     98   }
     99   if (!view->backend || !view->backend->configure) {
    100     return PUGL_BAD_BACKEND;
    101   }
    102 
    103   // Set the size to the default if it has not already been set
    104   if (view->frame.width <= 0.0 || view->frame.height <= 0.0) {
    105     const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
    106     if (!defaultSize.width || !defaultSize.height) {
    107       return PUGL_BAD_CONFIGURATION;
    108     }
    109 
    110     view->frame.width  = defaultSize.width;
    111     view->frame.height = defaultSize.height;
    112   }
    113 
    114   // Center top-level windows if a position has not been set
    115   if (!view->parent && !view->frame.x && !view->frame.y) {
    116     // TODO
    117   }
    118 
    119   if (!view->parent) {
    120     impl->window = new PuglHaikuWindow(view);
    121     impl->window->Lock();
    122   }
    123 
    124   impl->view = new PuglHaikuView(view);
    125 
    126   if (view->parent) {
    127     BView* const pview = (BView*)view->parent;
    128     pview->AddChild(impl->view);
    129   } else {
    130     impl->window->AddChild(impl->view);
    131   }
    132 
    133   // Configure and create the backend
    134   if ((st = view->backend->configure(view)) || (st = view->backend->create(view))) {
    135     view->backend->destroy(view);
    136     return st;
    137   }
    138 
    139   if (view->title) {
    140     puglSetWindowTitle(view, view->title);
    141   }
    142 
    143   if (view->transientParent) {
    144     puglSetTransientParent(view, view->transientParent);
    145   }
    146 
    147   puglDispatchSimpleEvent(view, PUGL_CREATE);
    148 
    149   if (impl->window) {
    150     impl->window->Unlock();
    151   }
    152 
    153   return PUGL_SUCCESS;
    154 }
    155 
    156 PuglStatus
    157 puglShow(PuglView* const view)
    158 {
    159   PuglInternals* const impl = view->impl;
    160   if (impl->window) {
    161     impl->window->Show();
    162   } else {
    163     impl->view->Show();
    164   }
    165   return PUGL_SUCCESS;
    166 }
    167 
    168 PuglStatus
    169 puglHide(PuglView* const view)
    170 {
    171   PuglInternals* const impl = view->impl;
    172   if (impl->window) {
    173     impl->window->Hide();
    174   } else {
    175     impl->view->Hide();
    176   }
    177   return PUGL_SUCCESS;
    178 }
    179 
    180 void
    181 puglFreeViewInternals(PuglView* const view)
    182 {
    183   if (view && view->impl) {
    184     PuglInternals* const impl = view->impl;
    185     if (view->backend) {
    186       view->backend->destroy(view);
    187     }
    188     if (impl->view) {
    189       if (impl->window) {
    190         impl->window->RemoveChild(impl->view);
    191       }
    192       delete impl->view;
    193       delete impl->window;
    194     }
    195     free(impl);
    196   }
    197 }
    198 
    199 void
    200 puglFreeWorldInternals(PuglWorld* const world)
    201 {
    202 //   if (world->impl->app != nullptr && world->impl->app->CountWindows() == 0) {
    203 //     delete world->impl->app;
    204 //     s_app = NULL;
    205 //   }
    206   free(world->impl);
    207 }
    208 
    209 PuglStatus
    210 puglGrabFocus(PuglView*)
    211 {
    212   return PUGL_UNSUPPORTED;
    213 }
    214 
    215 double
    216 puglGetScaleFactor(const PuglView* const view)
    217 {
    218   return 1.0;
    219 }
    220 
    221 double
    222 puglGetTime(const PuglWorld* const world)
    223 {
    224   struct timespec ts;
    225   clock_gettime(CLOCK_MONOTONIC, &ts);
    226   return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) -
    227          world->startTime;
    228 }
    229 
    230 PuglStatus
    231 puglUpdate(PuglWorld* const world, const double timeout)
    232 {
    233   return PUGL_UNSUPPORTED;
    234 }
    235 
    236 PuglStatus
    237 puglPostRedisplay(PuglView* const view)
    238 {
    239   return PUGL_UNSUPPORTED;
    240 }
    241 
    242 PuglStatus
    243 puglPostRedisplayRect(PuglView* const view, const PuglRect rect)
    244 {
    245   return PUGL_UNSUPPORTED;
    246 }
    247 
    248 PuglNativeView
    249 puglGetNativeView(PuglView* const view)
    250 {
    251   return 0;
    252 }
    253 
    254 PuglStatus
    255 puglSetWindowTitle(PuglView* const view, const char* const title)
    256 {
    257   puglSetString(&view->title, title);
    258   return PUGL_UNSUPPORTED;
    259 }
    260 
    261 PuglStatus
    262 puglSetSizeHint(PuglView* const    view,
    263                 const PuglSizeHint hint,
    264                 const PuglSpan     width,
    265                 const PuglSpan     height)
    266 {
    267   view->sizeHints[hint].width  = width;
    268   view->sizeHints[hint].height = height;
    269   return PUGL_SUCCESS;
    270 }
    271 
    272 PuglStatus
    273 puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout)
    274 {
    275   return PUGL_UNSUPPORTED;
    276 }
    277 
    278 PuglStatus
    279 puglStopTimer(PuglView* const view, const uintptr_t id)
    280 {
    281   return PUGL_UNSUPPORTED;
    282 }
    283 
    284 PuglStatus
    285 puglPaste(PuglView* const view)
    286 {
    287   return PUGL_UNSUPPORTED;
    288 }
    289 
    290 PuglStatus
    291 puglAcceptOffer(PuglView* const                 view,
    292                 const PuglDataOfferEvent* const offer,
    293                 const uint32_t                  typeIndex)
    294 {
    295   return PUGL_UNSUPPORTED;
    296 }
    297 
    298 uint32_t
    299 puglGetNumClipboardTypes(const PuglView* const view)
    300 {
    301   return 0u;
    302 }
    303 
    304 const char*
    305 puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex)
    306 {
    307   return NULL;
    308 }
    309 
    310 const void*
    311 puglGetClipboard(PuglView* const view,
    312                  const uint32_t  typeIndex,
    313                  size_t* const   len)
    314 {
    315   return NULL;
    316 }
    317 
    318 PuglStatus
    319 puglSetClipboard(PuglView* const   view,
    320                  const char* const type,
    321                  const void* const data,
    322                  const size_t      len)
    323 {
    324   return PUGL_FAILURE;
    325 }
    326 
    327 PuglStatus
    328 puglSetCursor(PuglView* const view, const PuglCursor cursor)
    329 {
    330   return PUGL_FAILURE;
    331 }
    332 
    333 PuglStatus
    334 puglSetTransientParent(PuglView* const view, const PuglNativeView parent)
    335 {
    336   return PUGL_FAILURE;
    337 }
    338 
    339 PuglStatus
    340 puglSetPosition(PuglView* const view, const int x, const int y)
    341 {
    342   return PUGL_FAILURE;
    343 }
    344 
    345 #if 0
    346 PuglStatus
    347 puglGrabFocus(PuglView* view)
    348 {
    349     view->impl->bView->MakeFocus(true);
    350     return PUGL_SUCCESS;
    351 }
    352 
    353 // extras follow
    354 
    355 void
    356 puglRaiseWindow(PuglView* view)
    357 {
    358 }
    359 
    360 void
    361 puglSetWindowSize(PuglView* view, unsigned int width, unsigned int height)
    362 {
    363     bView->ResizeTo(width, height);
    364 
    365     if (bWindow != nullptr && bWindow->LockLooper())
    366     {
    367         bWindow->MoveTo(50, 50);
    368         bWindow->ResizeTo(width, height);
    369 
    370         if (! forced)
    371             bWindow->Flush();
    372 
    373         bWindow->UnlockLooper();
    374     }
    375     // TODO resizable
    376 }
    377 
    378 void setVisible(const bool yesNo)
    379 {
    380     if (bWindow != nullptr)
    381     {
    382         if (bWindow->LockLooper())
    383         {
    384             if (yesNo)
    385                 bWindow->Show();
    386             else
    387                 bWindow->Hide();
    388 
    389             // TODO use flush?
    390             bWindow->Sync();
    391             bWindow->UnlockLooper();
    392         }
    393     }
    394     else
    395     {
    396         if (yesNo)
    397             bView->Show();
    398         else
    399             bView->Hide();
    400     }
    401 }
    402 #endif