commit 20a464142a2cc27aa0b3b930b6416c950cf79c24
parent 700762a5b57079051237dc77a2aa6a355965b879
Author: falkTX <falktx@gmail.com>
Date: Sun, 18 Aug 2019 05:14:49 +0100
Incomplete but sorta working initial Haiku support, WIP
See https://nextcloud.falktx.com/s/SGsiLLHJ7Qn4PDj/preview
and https://nextcloud.falktx.com/s/w7qsZigFNTHFrmw/preview
Great times ahead!
Diffstat:
3 files changed, 330 insertions(+), 20 deletions(-)
diff --git 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<PuglGenericView>* mView;
diff --git 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 <Application.h>
#include <interface/Window.h>
#ifdef PUGL_CAIRO
#include <cairo/cairo.h>
+typedef BView BViewType;
#endif
#ifdef PUGL_OPENGL
#include <GL/gl.h>
+#include <opengl/GLView.h>
+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<int>(newWidth);
+ const int height = static_cast<int>(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
@@ -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;