diff --git a/dgl/src/Window.cpp b/dgl/src/Window.cpp index b1d57f93..0e2e5b46 100644 --- a/dgl/src/Window.cpp +++ b/dgl/src/Window.cpp @@ -38,6 +38,7 @@ #endif #if defined(DISTRHO_OS_HAIKU) +# define DGL_DEBUG_EVENTS # include "pugl/pugl_haiku.cpp" #elif defined(DISTRHO_OS_MAC) # define PuglWindow DISTRHO_JOIN_MACRO(PuglWindow, DGL_NAMESPACE) @@ -102,6 +103,8 @@ struct Window::PrivateData { fWidgets(), fModal(), #if defined(DISTRHO_OS_HAIKU) + bApplication(nullptr), + bView(nullptr), bWindow(nullptr) #elif defined(DISTRHO_OS_MAC) fNeedsIdle(true), @@ -140,6 +143,8 @@ struct Window::PrivateData { fWidgets(), fModal(parent.pData), #if defined(DISTRHO_OS_HAIKU) + bApplication(nullptr), + bView(nullptr), bWindow(nullptr) #elif defined(DISTRHO_OS_MAC) fNeedsIdle(false), @@ -192,6 +197,8 @@ struct Window::PrivateData { fWidgets(), fModal(), #if defined(DISTRHO_OS_HAIKU) + bApplication(nullptr), + bView(nullptr), bWindow(nullptr) #elif defined(DISTRHO_OS_MAC) fNeedsIdle(parentId == 0), @@ -260,7 +267,9 @@ struct Window::PrivateData { PuglInternals* impl = fView->impl; #if defined(DISTRHO_OS_HAIKU) - bWindow = impl->window; + bApplication = impl->app; + bView = impl->view; + bWindow = impl->window; #elif defined(DISTRHO_OS_MAC) mView = impl->view; mWindow = impl->window; @@ -293,7 +302,6 @@ struct Window::PrivateData { XInternAtom(xDisplay, "_NET_WM_WINDOW_TYPE_NORMAL", False) }; XChangeProperty(xDisplay, xWindow, _wt, XA_ATOM, 32, PropModeReplace, (const uchar*)&_wts, 2); - } #endif puglEnterContext(fView); @@ -340,6 +348,9 @@ struct Window::PrivateData { } #if defined(DISTRHO_OS_HAIKU) + bApplication = nullptr; + bView = nullptr; + bWindow = nullptr; #elif defined(DISTRHO_OS_MAC) mView = nullptr; mWindow = nullptr; @@ -456,6 +467,10 @@ struct Window::PrivateData { { DBG("Window focus\n"); #if defined(DISTRHO_OS_HAIKU) + if (bWindow != nullptr) + bWindow->Activate(true); + else + bView->MakeFocus(true); #elif defined(DISTRHO_OS_MAC) if (mWindow != nullptr) [mWindow makeKeyWindow]; @@ -493,7 +508,27 @@ struct Window::PrivateData { setSize(fWidth, fHeight, true); #if defined(DISTRHO_OS_HAIKU) - // TODO + if (bWindow != nullptr) + { + if (yesNo) + { + + bView->Show(); + bWindow->Show(); + } + else + bWindow->Hide(); + + // TODO use flush? + bWindow->Sync(); + } + else + { + if (yesNo) + bView->Show(); + else + bView->Hide(); + } #elif defined(DISTRHO_OS_MAC) if (yesNo) { @@ -599,8 +634,11 @@ struct Window::PrivateData { #if defined(DISTRHO_OS_HAIKU) // TODO + // B_NO_BORDER + // B_TITLED_WINDOW_LOOK + // bWindow->SetFlags(); #elif defined(DISTRHO_OS_MAC) - const uint flags(yesNo ? (NSViewWidthSizable|NSViewHeightSizable) : 0x0); + const uint flags = yesNo ? (NSViewWidthSizable|NSViewHeightSizable) : 0x0; [mView setAutoresizingMask:flags]; #elif defined(DISTRHO_OS_WINDOWS) const int winFlags = fResizable ? GetWindowLong(hwnd, GWL_STYLE) | WS_SIZEBOX @@ -645,7 +683,16 @@ struct Window::PrivateData { DBGp("Window setSize called %s, size %i %i, resizable %s\n", forced ? "(forced)" : "(not forced)", width, height, fResizable?"true":"false"); #if defined(DISTRHO_OS_HAIKU) - // TODO + bView->ResizeTo(width, height); + + if (bWindow != nullptr) + { + bWindow->ResizeTo(width, height); + + if (! forced) + bWindow->Flush(); + } + // TODO resizable #elif defined(DISTRHO_OS_MAC) [mView setFrame:NSMakeRect(0, 0, width, height)]; @@ -807,6 +854,15 @@ struct Window::PrivateData { { puglProcessEvents(fView); +#ifdef DISTRHO_OS_HAIKU + if (bApplication != nullptr) + { + bApplication->Lock(); + // bApplication->Loop(); + bApplication->Unlock(); + } +#endif + #ifdef DISTRHO_OS_MAC if (fNeedsIdle) { @@ -1192,7 +1248,9 @@ struct Window::PrivateData { } fModal; #if defined(DISTRHO_OS_HAIKU) - BWindow* bWindow; + BApplication* bApplication; + BView* bView; + BWindow* bWindow; #elif defined(DISTRHO_OS_MAC) bool fNeedsIdle; NSView* mView; diff --git a/dgl/src/pugl/pugl_haiku.cpp b/dgl/src/pugl/pugl_haiku.cpp index c69a99cc..7a241efa 100644 --- a/dgl/src/pugl/pugl_haiku.cpp +++ b/dgl/src/pugl/pugl_haiku.cpp @@ -18,21 +18,59 @@ @file pugl_haiku.cpp BeOS/HaikuOS Pugl Implementation. */ +#include #include #ifdef PUGL_CAIRO #include +typedef BView BViewType; #endif #ifdef PUGL_OPENGL #include +#include +typedef BGLView BViewType; #endif #include "pugl_internal.h" +class DWindow; + struct PuglInternalsImpl { - BWindow* window; + BApplication* app; + BViewType* view; + DWindow* window; }; +static void +puglReshape(PuglView* view, int width, int height) +{ + puglEnterContext(view); + + if (view->reshapeFunc) { + view->reshapeFunc(view, width, height); + } else { + puglDefaultReshape(width, height); + } + + puglLeaveContext(view, false); + + view->width = width; + view->height = height; +} + +static void +puglDisplay(PuglView* view) +{ + puglEnterContext(view); + + view->redisplay = false; + if (view->displayFunc) { + view->displayFunc(view); + } + + puglLeaveContext(view, true); +} + PuglInternals* puglInitInternals() { @@ -42,48 +80,253 @@ puglInitInternals() void puglEnterContext(PuglView* view) { +#ifdef PUGL_OPENGL + PuglInternals* impl = view->impl; + + // FIXME without the first unlock we freeze + impl->view->UnlockGL(); + impl->view->LockGL(); +#endif } void puglLeaveContext(PuglView* view, bool flush) { +#ifdef PUGL_OPENGL + PuglInternals* impl = view->impl; + + if (flush) + impl->view->SwapBuffers(true); + + impl->view->UnlockGL(); +#endif } +class DView : public BViewType +{ +public: +#ifdef PUGL_CAIRO + DView(PuglView* const v) + : BView(nullptr, + B_FULL_UPDATE_ON_RESIZE|B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE), + puglView(v) {} +#endif + +#ifdef PUGL_OPENGL + DView(PuglView* const v) + : BGLView(BRect(512.0f), + "DPF-GLView", + 0x0, // resize mode + B_FULL_UPDATE_ON_RESIZE|B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE, + BGL_RGB /*|BGL_DOUBLE|BGL_ALPHA|BGL_DEPTH|BGL_STENCIL*/), + puglView(v) {} +#endif + +protected: + void Draw(BRect updateRect) override + { + d_stdout("%s %i", __func__, __LINE__); + puglDisplay(puglView); + d_stdout("%s %i", __func__, __LINE__); + +#ifdef PUGL_OPENGL + BGLView::Draw(updateRect); +#endif + d_stdout("%s %i", __func__, __LINE__); + } + + void MouseDown(BPoint where) override + { + if (puglView->mouseFunc) { + // puglView->event_timestamp_ms = GetMessageTime(); + puglView->mouseFunc(puglView, 1, true, where.x, where.y); + } + } + + void MouseUp(BPoint where) override + { + if (puglView->mouseFunc) { + // puglView->event_timestamp_ms = GetMessageTime(); + puglView->mouseFunc(puglView, 1, false, where.x, where.y); + } + } + + void MouseMoved(BPoint where, uint32, const BMessage*) override + { + if (puglView->motionFunc) { + // puglView->event_timestamp_ms = GetMessageTime(); + puglView->motionFunc(puglView, where.x, where.y); + } + } + + void KeyDown(const char* bytes, int32 numBytes) override + { + d_stdout("KeyDown %s %i", bytes, numBytes); + if (numBytes != 1) + return; // TODO + + if (puglView->keyboardFunc) { + puglView->keyboardFunc(puglView, true, bytes[0]); + } + } + + void KeyUp(const char* bytes, int32 numBytes) override + { + if (numBytes != 1) + return; // TODO + + if (puglView->keyboardFunc) { + puglView->keyboardFunc(puglView, false, bytes[0]); + } + } + + void FrameResized(float newWidth, float newHeight) override + { + d_stdout("%s %i", __func__, __LINE__); + const int width = static_cast(newWidth); + const int height = static_cast(newHeight); + + puglReshape(puglView, width, height); + d_stdout("%s %i", __func__, __LINE__); + puglView->width = width; + puglView->height = height; + d_stdout("%s %i", __func__, __LINE__); +#ifdef PUGL_OPENGL + BGLView::FrameResized(newWidth, newHeight); +#endif + d_stdout("%s %i", __func__, __LINE__); + } + +private: + PuglView* const puglView; +}; + class DWindow : public BWindow { public: - DWindow(PuglInternals* const i) - : BWindow(BRect(), "", B_TITLED_WINDOW, 0x0), - impl(i) + DWindow(PuglView* const v) + : BWindow(BRect(1.0f), "DPF-Window", B_TITLED_WINDOW, 0x0), + puglView(v), + needsQuit(true) + { + } + + bool NeedsQuit() const + { + return needsQuit; + } + +protected: + bool QuitRequested() override { + d_stdout("%s %i", __func__, __LINE__); + if (puglView->closeFunc) { + puglView->closeFunc(puglView); + puglView->redisplay = false; + } + needsQuit = false; + d_stdout("%s %i", __func__, __LINE__); + return true; } private: - PuglInternals* const impl; + PuglView* const puglView; + bool needsQuit; }; int puglCreateWindow(PuglView* view, const char* title) { PuglInternals* impl = view->impl; + + if (be_app == nullptr) + { + status_t status; + BApplication* const app = new BApplication("application/x-vnd.dpf-application", &status); + + if (status != B_OK) + { + d_stdout("app status error %u", status); + delete app; + return 1; + } + + impl->app = app; + } + + if (view->parent == 0) { + impl->window = new DWindow(view); + impl->window->Lock(); + } + + impl->view = new DView(view); + + if (view->parent != 0) { + BView* const pview = (BView*)view->parent; + pview->AddChild(impl->view); + impl->view->LockGL(); + return 0; + } + + if (title != nullptr) { + impl->window->SetTitle(title); + } - impl->window = new DWindow(impl); + impl->window->AddChild(impl->view); + puglEnterContext(view); + impl->window->Unlock(); return 0; } void puglShowWindow(PuglView* view) { + PuglInternals* impl = view->impl; + + if (impl->window != nullptr) + impl->window->Show(); + else + impl->view->Show(); } void puglHideWindow(PuglView* view) { + PuglInternals* impl = view->impl; + + if (impl->window != nullptr) + impl->window->Hide(); + else + impl->view->Show(); } void puglDestroy(PuglView* view) { + PuglInternals* impl = view->impl; + + if (impl->window != nullptr) + { + // impl->window->Lock(); + puglLeaveContext(view, false); + impl->window->RemoveChild(impl->view); + // impl->window->Unlock(); + + if (impl->window->NeedsQuit()) + impl->window->Quit(); + } + + delete impl->view; + impl->view = nullptr; + impl->window = nullptr; + + if (impl->app != nullptr && impl->app->CountWindows() == 0) + { + d_stdout("deleting app"); + delete impl->app; + impl->app = nullptr; + } else + d_stdout("NOT deleting app"); } PuglStatus @@ -96,12 +339,19 @@ void puglPostRedisplay(PuglView* view) { view->redisplay = true; + view->impl->view->Invalidate(); } PuglNativeWindow puglGetNativeWindow(PuglView* view) { - return NULL; + PuglInternals* impl = view->impl; + +#ifdef PUGL_OPENGL + // return (PuglNativeWindow)impl->view->EmbeddedView(); +#endif + + return (PuglNativeWindow)impl->view; } void* @@ -113,11 +363,15 @@ puglGetContext(PuglView* view) int puglUpdateGeometryConstraints(PuglView* view, int min_width, int min_height, bool aspect) { - // TODO - return 1; + PuglInternals* impl = view->impl; + + d_stdout("puglUpdateGeometryConstraints %i %i %i %i", min_width, min_height, view->width, view->height); + impl->window->SetSizeLimits(min_width, + view->user_resizable ? 4096 : min_width, + min_height, + view->user_resizable ? 4096 : min_height); + return 0; - (void)view; - (void)min_width; - (void)min_height; + // TODO (void)aspect; } diff --git a/dgl/src/pugl/pugl_win.cpp b/dgl/src/pugl/pugl_win.cpp index d8b3866d..90aa5975 100644 --- a/dgl/src/pugl/pugl_win.cpp +++ b/dgl/src/pugl/pugl_win.cpp @@ -392,8 +392,6 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) case WM_SIZE: GetClientRect(view->impl->hwnd, &rect); puglReshape(view, rect.right, rect.bottom); - view->width = rect.right; - view->height = rect.bottom; break; case WM_GETMINMAXINFO: mmi = (MINMAXINFO*)lParam;