diff --git a/Makefile.base.mk b/Makefile.base.mk index e1faf654..1d10a239 100644 --- a/Makefile.base.mk +++ b/Makefile.base.mk @@ -272,7 +272,10 @@ BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections endif ifeq ($(DEBUG),true) -BASE_FLAGS += -DDEBUG -O0 -g -fsanitize=address +BASE_FLAGS += -DDEBUG -O0 -g +ifneq ($(HAIKU),true) +BASE_FLAGS += -fsanitize=address +endif LINK_OPTS = ifeq ($(WASM),true) LINK_OPTS += -sASSERTIONS=1 @@ -347,9 +350,11 @@ endif # --------------------------------------------------------------------------------------------------------------------- # Check for required libraries -HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true) +ifneq ($(HAIKU),true) +HAVE_CAIRO = $(shell $(PKG_CONFIG) --exists cairo && echo true) +endif -ifeq ($(MACOS_OR_WASM_OR_WINDOWS),true) +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) HAVE_OPENGL = true else HAVE_OPENGL = $(shell $(PKG_CONFIG) --exists gl && echo true) @@ -454,8 +459,8 @@ ifeq ($(HAVE_OPENGL),true) DGL_FLAGS += -DHAVE_OPENGL ifeq ($(HAIKU),true) -OPENGL_FLAGS = $(shell $(PKG_CONFIG) --cflags gl) -OPENGL_LIBS = $(shell $(PKG_CONFIG) --libs gl) +OPENGL_FLAGS = +OPENGL_LIBS = -lGL else ifeq ($(MACOS),true) OPENGL_FLAGS = -DGL_SILENCE_DEPRECATION=1 -Wno-deprecated-declarations OPENGL_LIBS = -framework OpenGL @@ -481,7 +486,7 @@ endif # --------------------------------------------------------------------------------------------------------------------- # Set Stub specific stuff -ifeq ($(MACOS_OR_WASM_OR_WINDOWS),true) +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) HAVE_STUB = true else HAVE_STUB = $(HAVE_X11) @@ -540,7 +545,7 @@ endif # --------------------------------------------------------------------------------------------------------------------- # Backwards-compatible HAVE_DGL -ifeq ($(MACOS_OR_WASM_OR_WINDOWS),true) +ifeq ($(HAIKU_OR_MACOS_OR_WASM_OR_WINDOWS),true) HAVE_DGL = true else ifeq ($(HAVE_OPENGL),true) HAVE_DGL = $(HAVE_X11) diff --git a/dgl/src/pugl-extra/haiku.cpp b/dgl/src/pugl-extra/haiku.cpp index b01b6629..13db156a 100644 --- a/dgl/src/pugl-extra/haiku.cpp +++ b/dgl/src/pugl-extra/haiku.cpp @@ -1,28 +1,348 @@ -/* - Copyright 2012-2019 David Robillard - Copyright 2019-2020 Filipe Coelho - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file mac.cpp HaikuOS implementation. -*/ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC #include "haiku.h" -#include "pugl/detail/implementation.h" +#include "../pugl-upstream/src/internal.h" +class PuglHaikuView : public BView +{ + PuglView* const view; + +public: + PuglHaikuView(PuglView* const v) + : BView(NULL, B_FULL_UPDATE_ON_RESIZE|B_FRAME_EVENTS|B_NAVIGABLE|B_INPUT_METHOD_AWARE), + view(v) {} + +protected: + void GetPreferredSize(float* width, float* height) override + { + d_stdout("%s %i", __func__, __LINE__); + if (width != nullptr) + *width = view->frame.width; + if (height != nullptr) + *height = view->frame.height; + d_stdout("%s %i", __func__, __LINE__); + } +}; + +class PuglHaikuWindow : public BWindow +{ + PuglView* const view; + +public: + PuglHaikuWindow(PuglView* const v) + : BWindow(BRect(1.0f), "DPF-Window", B_TITLED_WINDOW, 0x0), + view(v) {} + +// 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; +// } +}; + +BApplication* s_app = NULL; + +PuglWorldInternals* +puglInitWorldInternals(const PuglWorldType type, const PuglWorldFlags flags) +{ + if (!s_app) { + status_t status; + s_app = new BApplication("application/x-vnd.pugl-application", &status); + + if (status != B_OK) { + delete s_app; + return NULL; + } + } + + PuglWorldInternals* impl = + (PuglWorldInternals*)calloc(1, sizeof(PuglWorldInternals)); + + impl->app = s_app; + return impl; +} + +void* +puglGetNativeWorld(PuglWorld* const world) +{ + return world->impl->app; +} + +PuglInternals* +puglInitViewInternals(PuglWorld* const world) +{ + PuglInternals* impl = (PuglInternals*)calloc(1, sizeof(PuglInternals)); + + return impl; +} + +PuglStatus +puglRealize(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + PuglStatus st = PUGL_SUCCESS; + + // Ensure that we're unrealized and that a reasonable backend has been set + if (impl->view) { + return PUGL_FAILURE; + } + if (!view->backend || !view->backend->configure) { + return PUGL_BAD_BACKEND; + } + + // Set the size to the default if it has not already been set + if (view->frame.width <= 0.0 || view->frame.height <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { + return PUGL_BAD_CONFIGURATION; + } + + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + } + + // Center top-level windows if a position has not been set + if (!view->parent && !view->frame.x && !view->frame.y) { + // TODO + } + + if (!view->parent) { + impl->window = new PuglHaikuWindow(view); + impl->window->Lock(); + } + + impl->view = new PuglHaikuView(view); + + if (view->parent) { + BView* const pview = (BView*)view->parent; + pview->AddChild(impl->view); + } else { + impl->window->AddChild(impl->view); + } + + // Configure and create the backend + if ((st = view->backend->configure(view)) || (st = view->backend->create(view))) { + view->backend->destroy(view); + return st; + } + + if (view->title) { + puglSetWindowTitle(view, view->title); + } + + if (view->transientParent) { + puglSetTransientParent(view, view->transientParent); + } + + puglDispatchSimpleEvent(view, PUGL_CREATE); + + if (impl->window) { + impl->window->Unlock(); + } + + return PUGL_SUCCESS; +} + +PuglStatus +puglShow(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + if (impl->window) { + impl->window->Show(); + } else { + impl->view->Show(); + } + return PUGL_SUCCESS; +} + +PuglStatus +puglHide(PuglView* const view) +{ + PuglInternals* const impl = view->impl; + if (impl->window) { + impl->window->Hide(); + } else { + impl->view->Hide(); + } + return PUGL_SUCCESS; +} + +void +puglFreeViewInternals(PuglView* const view) +{ + if (view && view->impl) { + PuglInternals* const impl = view->impl; + if (view->backend) { + view->backend->destroy(view); + } + if (impl->view) { + if (impl->window) { + impl->window->RemoveChild(impl->view); + } + delete impl->view; + delete impl->window; + } + free(impl); + } +} + +void +puglFreeWorldInternals(PuglWorld* const world) +{ +// if (world->impl->app != nullptr && world->impl->app->CountWindows() == 0) { +// delete world->impl->app; +// s_app = NULL; +// } + free(world->impl); +} + +PuglStatus +puglGrabFocus(PuglView*) +{ + return PUGL_UNSUPPORTED; +} + +double +puglGetScaleFactor(const PuglView* const view) +{ + return 1.0; +} + +double +puglGetTime(const PuglWorld* const world) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ((double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0) - + world->startTime; +} + +PuglStatus +puglUpdate(PuglWorld* const world, const double timeout) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPostRedisplay(PuglView* const view) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPostRedisplayRect(PuglView* const view, const PuglRect rect) +{ + return PUGL_UNSUPPORTED; +} + +PuglNativeView +puglGetNativeView(PuglView* const view) +{ + return 0; +} + +PuglStatus +puglSetWindowTitle(PuglView* const view, const char* const title) +{ + puglSetString(&view->title, title); + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) +{ + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; + return PUGL_SUCCESS; +} + +PuglStatus +puglStartTimer(PuglView* const view, const uintptr_t id, const double timeout) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglStopTimer(PuglView* const view, const uintptr_t id) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglPaste(PuglView* const view) +{ + return PUGL_UNSUPPORTED; +} + +PuglStatus +puglAcceptOffer(PuglView* const view, + const PuglDataOfferEvent* const offer, + const uint32_t typeIndex) +{ + return PUGL_UNSUPPORTED; +} + +uint32_t +puglGetNumClipboardTypes(const PuglView* const view) +{ + return 0u; +} + +const char* +puglGetClipboardType(const PuglView* const view, const uint32_t typeIndex) +{ + return NULL; +} + +const void* +puglGetClipboard(PuglView* const view, + const uint32_t typeIndex, + size_t* const len) +{ + return NULL; +} + +PuglStatus +puglSetClipboard(PuglView* const view, + const char* const type, + const void* const data, + const size_t len) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetCursor(PuglView* const view, const PuglCursor cursor) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetTransientParent(PuglView* const view, const PuglNativeView parent) +{ + return PUGL_FAILURE; +} + +PuglStatus +puglSetPosition(PuglView* const view, const int x, const int y) +{ + return PUGL_FAILURE; +} + +#if 0 PuglStatus puglGrabFocus(PuglView* view) { @@ -79,3 +399,4 @@ void setVisible(const bool yesNo) bView->Hide(); } } +#endif diff --git a/dgl/src/pugl-extra/haiku.h b/dgl/src/pugl-extra/haiku.h index 9930a8df..f98c5d79 100644 --- a/dgl/src/pugl-extra/haiku.h +++ b/dgl/src/pugl-extra/haiku.h @@ -1,35 +1,25 @@ -/* - Copyright 2012-2019 David Robillard - Copyright 2019-2020 Filipe Coelho +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. +#ifndef PUGL_SRC_HAIKU_H +#define PUGL_SRC_HAIKU_H - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/** - @file haiku.h Shared definitions for HaikuOS implementation. -*/ +#include "../pugl-upstream/src/types.h" #include "pugl/pugl.h" #include #include -// using? interface/ struct PuglWorldInternalsImpl { - BApplication* app; + BApplication* app; }; struct PuglInternalsImpl { - BViewType* view; - BWindow* window; + PuglSurface* surface; + BView* view; + BWindow* window; }; + +#endif // PUGL_SRC_HAIKU_H diff --git a/dgl/src/pugl-extra/haiku_gl.cpp b/dgl/src/pugl-extra/haiku_gl.cpp new file mode 100644 index 00000000..1b8fc1f0 --- /dev/null +++ b/dgl/src/pugl-extra/haiku_gl.cpp @@ -0,0 +1,87 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "../pugl-upstream/src/stub.h" +#include "haiku.h" + +#include "pugl/pugl.h" + +#include +#include + +#include +#include + +typedef struct { + BGLView* view; +} PuglHaikuGlSurface; + +static PuglStatus +puglHaikuGlConfigure(PuglView* view) +{ + PuglInternals* const impl = view->impl; + + PuglHaikuGlSurface* const surface = + (PuglHaikuGlSurface*)calloc(1, sizeof(PuglHaikuGlSurface)); + impl->surface = surface; + + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglHaikuGlEnter(PuglView* const view, const PuglExposeEvent* PUGL_UNUSED(expose)) +{ + PuglHaikuGlSurface* const surface = (PuglHaikuGlSurface*)view->impl->surface; + if (!surface || !surface->view) { + return PUGL_FAILURE; + } + + surface->view->LockGL(); + return PUGL_SUCCESS; +} + +PUGL_WARN_UNUSED_RESULT +static PuglStatus +puglHaikuGlLeave(PuglView* const view, const PuglExposeEvent* const expose) +{ + PuglHaikuGlSurface* const surface = (PuglHaikuGlSurface*)view->impl->surface; + if (!surface || !surface->view) { + return PUGL_FAILURE; + } + + if (expose) + surface->view->SwapBuffers(); + + surface->view->UnlockGL(); + return PUGL_SUCCESS; +} + +static PuglStatus +puglHaikuGlCreate(PuglView* view) +{ + return PUGL_SUCCESS; +} + +static void +puglHaikuGlDestroy(PuglView* view) +{ + PuglHaikuGlSurface* surface = (PuglHaikuGlSurface*)view->impl->surface; + if (surface) { + free(surface); + view->impl->surface = NULL; + } +} + +const PuglBackend* +puglGlBackend(void) +{ + static const PuglBackend backend = {puglHaikuGlConfigure, + puglHaikuGlCreate, + puglHaikuGlDestroy, + puglHaikuGlEnter, + puglHaikuGlLeave, + puglStubGetContext}; + return &backend; +} diff --git a/dgl/src/pugl-extra/haiku_stub.cpp b/dgl/src/pugl-extra/haiku_stub.cpp new file mode 100644 index 00000000..20e018fe --- /dev/null +++ b/dgl/src/pugl-extra/haiku_stub.cpp @@ -0,0 +1,24 @@ +// Copyright 2012-2022 David Robillard +// Copyright 2021-2022 Filipe Coelho +// SPDX-License-Identifier: ISC + +#include "pugl/stub.h" + +#include "../pugl-upstream/src/stub.h" + +#include "pugl/pugl.h" + +const PuglBackend* +puglStubBackend(void) +{ + static const PuglBackend backend = { + puglStubConfigure, + puglStubCreate, + puglStubDestroy, + puglStubEnter, + puglStubLeave, + puglStubGetContext, + }; + + return &backend; +} diff --git a/dgl/src/pugl-extra/wasm_gl.c b/dgl/src/pugl-extra/wasm_gl.c index 3d875421..98f5b5cd 100644 --- a/dgl/src/pugl-extra/wasm_gl.c +++ b/dgl/src/pugl-extra/wasm_gl.c @@ -41,7 +41,7 @@ puglWasmGlGetAttrib(const EGLDisplay display, static PuglStatus puglWasmGlConfigure(PuglView* view) { - PuglInternals* const impl = view->impl; + PuglInternals* const impl = view->impl; const EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); diff --git a/dgl/src/pugl.cpp b/dgl/src/pugl.cpp index 98260b78..4c84b97f 100644 --- a/dgl/src/pugl.cpp +++ b/dgl/src/pugl.cpp @@ -37,7 +37,14 @@ #include #include -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +# include +# include +# ifdef DGL_OPENGL +# include +# include +# endif +#elif defined(DISTRHO_OS_MAC) # import # include # include @@ -119,7 +126,13 @@ START_NAMESPACE_DGL // -------------------------------------------------------------------------------------------------------------------- -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +# include "pugl-extra/haiku.cpp" +# include "pugl-extra/haiku_stub.cpp" +# ifdef DGL_OPENGL +# include "pugl-extra/haiku_gl.cpp" +# endif +#elif defined(DISTRHO_OS_MAC) # ifndef DISTRHO_MACOS_NAMESPACE_MACRO # define DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, SEP, INTERFACE) NS ## SEP ## INTERFACE # define DISTRHO_MACOS_NAMESPACE_MACRO(NS, INTERFACE) DISTRHO_MACOS_NAMESPACE_MACRO_HELPER(NS, _, INTERFACE) @@ -237,7 +250,8 @@ void puglSetMatchingBackendForCurrentBuild(PuglView* const view) void puglRaiseWindow(PuglView* const view) { -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) if (NSWindow* const window = view->impl->window ? view->impl->window : [view->impl->wrapperView window]) [window orderFrontRegardless]; @@ -257,7 +271,10 @@ void puglRaiseWindow(PuglView* const view) double puglGetScaleFactorFromParent(const PuglView* const view) { const PuglNativeView parent = view->parent ? view->parent : view->transientParent ? view->transientParent : 0; -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) + // TODO + return 1.0; +#elif defined(DISTRHO_OS_MAC) // some of these can return 0 as backingScaleFactor, pick the most relevant valid one const NSWindow* possibleWindows[] = { parent != 0 ? [(NSView*)parent window] : nullptr, @@ -296,7 +313,8 @@ PuglStatus puglSetGeometryConstraints(PuglView* const view, const uint width, co view->sizeHints[PUGL_FIXED_ASPECT].height = height; } -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) if (view->impl->window) { PuglStatus status; @@ -328,7 +346,8 @@ void puglSetResizable(PuglView* const view, const bool resizable) { puglSetViewHint(view, PUGL_RESIZABLE, resizable ? PUGL_TRUE : PUGL_FALSE); -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) if (PuglWindow* const window = view->impl->window) { const uint style = (NSClosableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask) @@ -361,7 +380,8 @@ PuglStatus puglSetSizeAndDefault(PuglView* view, uint width, uint height) view->sizeHints[PUGL_DEFAULT_SIZE].width = view->frame.width = static_cast(width); view->sizeHints[PUGL_DEFAULT_SIZE].height = view->frame.height = static_cast(height); -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) +#elif defined(DISTRHO_OS_MAC) // mostly matches upstream pugl, simplified PuglInternals* const impl = view->impl; @@ -456,7 +476,11 @@ void puglFallbackOnResize(PuglView* const view) // -------------------------------------------------------------------------------------------------------------------- -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) + +// -------------------------------------------------------------------------------------------------------------------- + +#elif defined(DISTRHO_OS_MAC) // -------------------------------------------------------------------------------------------------------------------- // macOS specific, add another view's window as child diff --git a/dgl/src/pugl.hpp b/dgl/src/pugl.hpp index d5d540b1..244adc5d 100644 --- a/dgl/src/pugl.hpp +++ b/dgl/src/pugl.hpp @@ -73,7 +73,11 @@ void puglOnDisplayPrepare(PuglView* view); // DGL specific, build-specific fallback resize void puglFallbackOnResize(PuglView* view); -#if defined(DISTRHO_OS_MAC) +#if defined(DISTRHO_OS_HAIKU) + +// nothing here yet + +#elif defined(DISTRHO_OS_MAC) // macOS specific, add another view's window as child PuglStatus puglMacOSAddChildWindow(PuglView* view, PuglView* child);