SDL: haiku: updated for Haiku

From bff867013e33454a2995c53449c6e7c5592caa93 Mon Sep 17 00:00:00 2001
From: kenmays <[EMAIL REDACTED]>
Date: Wed, 12 Jan 2022 06:47:02 -0800
Subject: [PATCH] haiku: updated for Haiku

---
 src/video/haiku/SDL_BApp.h          | 431 ++++++++++++++++++++++++++++
 src/video/haiku/SDL_bframebuffer.cc | 148 +---------
 src/video/haiku/SDL_bopengl.cc      |  36 ++-
 src/video/haiku/SDL_bvideo.cc       |  29 +-
 src/video/haiku/SDL_bwindow.cc      |   7 +
 src/video/haiku/SDL_bwindow.h       |   1 +
 6 files changed, 505 insertions(+), 147 deletions(-)
 create mode 100644 src/video/haiku/SDL_BApp.h

diff --git a/src/video/haiku/SDL_BApp.h b/src/video/haiku/SDL_BApp.h
new file mode 100644
index 00000000000..215f83662a0
--- /dev/null
+++ b/src/video/haiku/SDL_BApp.h
@@ -0,0 +1,431 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef SDL_BAPP_H
+#define SDL_BAPP_H
+
+#include <Path.h>
+#include <InterfaceKit.h>
+#include <LocaleRoster.h>
+#if SDL_VIDEO_OPENGL
+#include <OpenGLKit.h>
+#endif
+
+#include "../../video/haiku/SDL_bkeyboard.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../SDL_internal.h"
+
+#include "SDL_video.h"
+
+/* Local includes */
+#include "../../events/SDL_events_c.h"
+#include "../../video/haiku/SDL_bframebuffer.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <vector>
+
+
+
+
+/* Forward declarations */
+class SDL_BWin;
+
+/* Message constants */
+enum ToSDL {
+    /* Intercepted by BWindow on its way to BView */
+    BAPP_MOUSE_MOVED,
+    BAPP_MOUSE_BUTTON,
+    BAPP_MOUSE_WHEEL,
+    BAPP_KEY,
+    BAPP_REPAINT,           /* from _UPDATE_ */
+    /* From BWindow */
+    BAPP_MAXIMIZE,          /* from B_ZOOM */
+    BAPP_MINIMIZE,
+    BAPP_RESTORE,           /* TODO: IMPLEMENT! */
+    BAPP_SHOW,
+    BAPP_HIDE,
+    BAPP_MOUSE_FOCUS,       /* caused by MOUSE_MOVE */
+    BAPP_KEYBOARD_FOCUS,    /* from WINDOW_ACTIVATED */
+    BAPP_WINDOW_CLOSE_REQUESTED,
+    BAPP_WINDOW_MOVED,
+    BAPP_WINDOW_RESIZED,
+    BAPP_SCREEN_CHANGED
+};
+
+
+
+/* Create a descendant of BApplication */
+class SDL_BApp : public BApplication {
+public:
+    SDL_BApp(const char* signature) :
+        BApplication(signature) {
+#if SDL_VIDEO_OPENGL
+        _current_context = NULL;
+#endif
+    }
+
+
+    virtual ~SDL_BApp() {
+    }
+
+
+	virtual void RefsReceived(BMessage* message) {
+		char filePath[512];
+		entry_ref entryRef;
+		for (int32 i = 0; message->FindRef("refs", i, &entryRef) == B_OK; i++) {
+			BPath referencePath = BPath(&entryRef);
+			SDL_SendDropFile(NULL, referencePath.Path());
+		}
+		return;
+	}
+
+        /* Event-handling functions */
+    virtual void MessageReceived(BMessage* message) {
+        /* Sort out SDL-related messages */
+        switch ( message->what ) {
+        case BAPP_MOUSE_MOVED:
+            _HandleMouseMove(message);
+            break;
+
+        case BAPP_MOUSE_BUTTON:
+            _HandleMouseButton(message);
+            break;
+
+        case BAPP_MOUSE_WHEEL:
+            _HandleMouseWheel(message);
+            break;
+
+        case BAPP_KEY:
+            _HandleKey(message);
+            break;
+
+        case BAPP_REPAINT:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_EXPOSED);
+            break;
+
+        case BAPP_MAXIMIZE:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MAXIMIZED);
+            break;
+
+        case BAPP_MINIMIZE:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_MINIMIZED);
+            break;
+
+        case BAPP_SHOW:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_SHOWN);
+            break;
+
+        case BAPP_HIDE:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_HIDDEN);
+            break;
+
+        case BAPP_MOUSE_FOCUS:
+            _HandleMouseFocus(message);
+            break;
+
+        case BAPP_KEYBOARD_FOCUS:
+            _HandleKeyboardFocus(message);
+            break;
+
+        case BAPP_WINDOW_CLOSE_REQUESTED:
+            _HandleBasicWindowEvent(message, SDL_WINDOWEVENT_CLOSE);
+            break;
+
+        case BAPP_WINDOW_MOVED:
+            _HandleWindowMoved(message);
+            break;
+
+        case BAPP_WINDOW_RESIZED:
+            _HandleWindowResized(message);
+            break;
+
+        case B_LOCALE_CHANGED:
+            SDL_SendLocaleChangedEvent();
+            break;
+
+        case BAPP_SCREEN_CHANGED:
+            /* TODO: Handle screen resize or workspace change */
+            break;
+
+        default:
+           BApplication::MessageReceived(message);
+           break;
+        }
+    }
+
+    /* Window creation/destruction methods */
+    int32 GetID(SDL_Window *win) {
+        int32 i;
+        for(i = 0; i < _GetNumWindowSlots(); ++i) {
+            if( GetSDLWindow(i) == NULL ) {
+                _SetSDLWindow(win, i);
+                return i;
+            }
+        }
+
+        /* Expand the vector if all slots are full */
+        if( i == _GetNumWindowSlots() ) {
+            _PushBackWindow(win);
+            return i;
+        }
+
+        /* TODO: error handling */
+        return 0;
+    }
+
+    /* FIXME: Bad coding practice, but I can't include SDL_BWin.h here.  Is
+       there another way to do this? */
+    void ClearID(SDL_BWin *bwin); /* Defined in SDL_BeApp.cc */
+
+
+    SDL_Window *GetSDLWindow(int32 winID) {
+        return _window_map[winID];
+    }
+
+#if SDL_VIDEO_OPENGL
+    BGLView *GetCurrentContext() {
+        return _current_context;
+    }
+    
+    void SetCurrentContext(BGLView *newContext) {
+        if(_current_context)
+            _current_context->UnlockGL();
+        _current_context = newContext;
+        if (_current_context)
+            _current_context->LockGL();
+    }
+#endif
+
+private:
+    /* Event management */
+    void _HandleBasicWindowEvent(BMessage *msg, int32 sdlEventType) {
+        SDL_Window *win;
+        int32 winID;
+        if(
+            !_GetWinID(msg, &winID)
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        SDL_SendWindowEvent(win, sdlEventType, 0, 0);
+    }
+
+    void _HandleMouseMove(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        int32 x = 0, y = 0;
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindInt32("x", &x) != B_OK || /* x movement */
+            msg->FindInt32("y", &y) != B_OK    /* y movement */
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+
+        // Simple relative mode support for mouse.
+        if (SDL_GetMouse()->relative_mode) {
+            int winWidth, winHeight, winPosX, winPosY;
+            SDL_GetWindowSize(win, &winWidth, &winHeight);
+            SDL_GetWindowPosition(win, &winPosX, &winPosY);
+            int dx = x - (winWidth / 2);
+            int dy = y - (winHeight / 2);
+            SDL_SendMouseMotion(win, 0, SDL_GetMouse()->relative_mode, dx, dy);
+            set_mouse_position((winPosX + winWidth / 2), (winPosY + winHeight / 2));
+            if (!be_app->IsCursorHidden())
+                be_app->HideCursor();
+        } else {
+            SDL_SendMouseMotion(win, 0, 0, x, y);
+            if (SDL_ShowCursor(-1) && be_app->IsCursorHidden())
+                be_app->ShowCursor();
+        }
+    }
+
+    void _HandleMouseButton(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        int32 button, state;    /* left/middle/right, pressed/released */
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindInt32("button-id", &button) != B_OK ||
+            msg->FindInt32("button-state", &state) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        SDL_SendMouseButton(win, 0, state, button);
+    }
+
+    void _HandleMouseWheel(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        int32 xTicks, yTicks;
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindInt32("xticks", &xTicks) != B_OK ||
+            msg->FindInt32("yticks", &yTicks) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        SDL_SendMouseWheel(win, 0, xTicks, -yTicks, SDL_MOUSEWHEEL_NORMAL);
+    }
+
+    void _HandleKey(BMessage *msg) {
+        int32 scancode, state;  /* scancode, pressed/released */
+        if(
+            msg->FindInt32("key-state", &state) != B_OK ||
+            msg->FindInt32("key-scancode", &scancode) != B_OK
+        ) {
+            return;
+        }
+
+        /* Make sure this isn't a repeated event (key pressed and held) */
+        if(state == SDL_PRESSED && HAIKU_GetKeyState(scancode) == SDL_PRESSED) {
+            return;
+        }
+        HAIKU_SetKeyState(scancode, state);
+        SDL_SendKeyboardKey(state, HAIKU_GetScancodeFromBeKey(scancode));
+
+        if (state == SDL_PRESSED && SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
+            const int8 *keyUtf8;
+            ssize_t count;
+            if (msg->FindData("key-utf8", B_INT8_TYPE, (const void**)&keyUtf8, &count) == B_OK) {
+                char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
+                SDL_zeroa(text);
+                SDL_memcpy(text, keyUtf8, count);
+                SDL_SendKeyboardText(text);
+            }
+        }
+    }
+
+    void _HandleMouseFocus(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        bool bSetFocus; /* If false, lose focus */
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindBool("focusGained", &bSetFocus) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        if(bSetFocus) {
+            SDL_SetMouseFocus(win);
+        } else if(SDL_GetMouseFocus() == win) {
+            /* Only lose all focus if this window was the current focus */
+            SDL_SetMouseFocus(NULL);
+        }
+    }
+
+    void _HandleKeyboardFocus(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        bool bSetFocus; /* If false, lose focus */
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindBool("focusGained", &bSetFocus) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        if(bSetFocus) {
+            SDL_SetKeyboardFocus(win);
+        } else if(SDL_GetKeyboardFocus() == win) {
+            /* Only lose all focus if this window was the current focus */
+            SDL_SetKeyboardFocus(NULL);
+        }
+    }
+
+    void _HandleWindowMoved(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        int32 xPos, yPos;
+        /* Get the window id and new x/y position of the window */
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindInt32("window-x", &xPos) != B_OK ||
+            msg->FindInt32("window-y", &yPos) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        SDL_SendWindowEvent(win, SDL_WINDOWEVENT_MOVED, xPos, yPos);
+    }
+
+    void _HandleWindowResized(BMessage *msg) {
+        SDL_Window *win;
+        int32 winID;
+        int32 w, h;
+        /* Get the window id ]and new x/y position of the window */
+        if(
+            !_GetWinID(msg, &winID) ||
+            msg->FindInt32("window-w", &w) != B_OK ||
+            msg->FindInt32("window-h", &h) != B_OK
+        ) {
+            return;
+        }
+        win = GetSDLWindow(winID);
+        SDL_SendWindowEvent(win, SDL_WINDOWEVENT_RESIZED, w, h);
+    }
+
+    bool _GetWinID(BMessage *msg, int32 *winID) {
+        return msg->FindInt32("window-id", winID) == B_OK;
+    }
+
+
+
+    /* Vector functions: Wraps vector stuff in case we need to change
+       implementation */
+    void _SetSDLWindow(SDL_Window *win, int32 winID) {
+        _window_map[winID] = win;
+    }
+
+    int32 _GetNumWindowSlots() {
+        return _window_map.size();
+    }
+
+
+    void _PopBackWindow() {
+        _window_map.pop_back();
+    }
+
+    void _PushBackWindow(SDL_Window *win) {
+        _window_map.push_back(win);
+    }
+
+
+    /* Members */
+    std::vector<SDL_Window*> _window_map; /* Keeps track of SDL_Windows by index-id */
+
+#if SDL_VIDEO_OPENGL
+    BGLView      *_current_context;
+#endif
+};
+
+#endif
diff --git a/src/video/haiku/SDL_bframebuffer.cc b/src/video/haiku/SDL_bframebuffer.cc
index c1017eb4669..971231924b7 100644
--- a/src/video/haiku/SDL_bframebuffer.cc
+++ b/src/video/haiku/SDL_bframebuffer.cc
@@ -35,10 +35,6 @@
 extern "C" {
 #endif
 
-#ifndef DRAWTHREAD
-static int32 HAIKU_UpdateOnce(SDL_Window *window);
-#endif
-
 static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) {
     return ((SDL_BWin*)(window->driverdata));
 }
@@ -56,11 +52,11 @@ int HAIKU_CreateWindowFramebuffer(_THIS, SDL_Window * window,
         return -1;
     }
 
-    while(!bwin->Connected()) { snooze(100); }
-    
     /* Make sure we have exclusive access to frame buffer data */
     bwin->LockBuffer();
 
+    bwin->CreateView();
+
     /* format */
     display_mode bmode;
     bscreen.GetMode(&bmode);
@@ -76,7 +72,7 @@ int HAIKU_CreateWindowFramebuffer(_THIS, SDL_Window * window,
     bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
             false,    /* Views not accepted */
             true);    /* Contiguous memory required */
-            
+
     if(bitmap->InitCheck() != B_OK) {
         delete bitmap;
         return SDL_SetError("Could not initialize back buffer!");
@@ -84,15 +80,13 @@ int HAIKU_CreateWindowFramebuffer(_THIS, SDL_Window * window,
 
 
     bwin->SetBitmap(bitmap);
-    
+
     /* Set the pixel pointer */
     *pixels = bitmap->Bits();
 
     /* pitch = width of window, in bytes */
     *pitch = bitmap->BytesPerRow();
 
-    bwin->SetBufferExists(true);
-    bwin->SetTrashBuffer(false);
     bwin->UnlockBuffer();
     return 0;
 }
@@ -106,149 +100,25 @@ int HAIKU_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
 
     SDL_BWin *bwin = _ToBeWin(window);
 
-#ifdef DRAWTHREAD    
-    bwin->LockBuffer();
-    bwin->SetBufferDirty(true);
-    bwin->UnlockBuffer();
-#else
-    bwin->SetBufferDirty(true);
-    HAIKU_UpdateOnce(window);
-#endif
+    bwin->PostMessage(BWIN_UPDATE_FRAMEBUFFER);
 
     return 0;
 }
 
-int32 HAIKU_DrawThread(void *data) {
-    SDL_BWin *bwin = (SDL_BWin*)data;
-    
-    BScreen bscreen;
-    if(!bscreen.IsValid()) {
-        return -1;
-    }
-
-    while(bwin->ConnectionEnabled()) {
-        if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
-            bwin->LockBuffer();
-            BBitmap *bitmap = NULL;
-            bitmap = bwin->GetBitmap();
-            int32 windowPitch = bitmap->BytesPerRow();
-            int32 bufferPitch = bwin->GetRowBytes();
-            uint8 *windowpx;
-            uint8 *bufferpx;
-
-            int32 BPP = bwin->GetBytesPerPx();
-            int32 windowSub = bwin->GetFbX() * BPP +
-                          bwin->GetFbY() * windowPitch;
-            clipping_rect *clips = bwin->GetClips();
-            int32 numClips = bwin->GetNumClips();
-            int i, y;
-
-            /* Blit each clipping rectangle */
-            bscreen.WaitForRetrace();
-            for(i = 0; i < numClips; ++i) {
-                /* Get addresses of the start of each clipping rectangle */
-                int32 width = clips[i].right - clips[i].left + 1;
-                int32 height = clips[i].bottom - clips[i].top + 1;
-                bufferpx = bwin->GetBufferPx() + 
-                    clips[i].top * bufferPitch + clips[i].left * BPP;
-                windowpx = (uint8*)bitmap->Bits() + 
-                    clips[i].top * windowPitch + clips[i].left * BPP -
-                    windowSub;
-
-                /* Copy each row of pixels from the window buffer into the frame
-                   buffer */
-                for(y = 0; y < height; ++y)
-                {
-
-                    if(bwin->CanTrashWindowBuffer()) {
-                        goto escape;    /* Break out before the buffer is killed */
-                    }
-
-                    memcpy(bufferpx, windowpx, width * BPP);
-                    bufferpx += bufferPitch;
-                    windowpx += windowPitch;
-                }
-            }
-
-            bwin->SetBufferDirty(false);
-escape:
-            bwin->UnlockBuffer();
-        } else {
-            snooze(16000);
-        }
-    }
-    
-    return B_OK;
-}
-
 void HAIKU_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
     SDL_BWin *bwin = _ToBeWin(window);
-    
+
     bwin->LockBuffer();
-    
+
     /* Free and clear the window buffer */
     BBitmap *bitmap = bwin->GetBitmap();
     delete bitmap;
     bwin->SetBitmap(NULL);
-    bwin->SetBufferExists(false);
-    bwin->UnlockBuffer();
-}
 
+    bwin->RemoveView();
 
-/*
- * TODO:
- * This was written to test if certain errors were caused by threading issues.
- * The specific issues have since become rare enough that they may have been
- * solved, but I doubt it- they were pretty sporadic before now.
- */
-#ifndef DRAWTHREAD
-static int32 HAIKU_UpdateOnce(SDL_Window *window) {
-    SDL_BWin *bwin = _ToBeWin(window);
-    BScreen bscreen;
-    if(!bscreen.IsValid()) {
-        return -1;
-    }
-
-    if(bwin->ConnectionEnabled() && bwin->Connected()) {
-        bwin->LockBuffer();
-        int32 windowPitch = window->surface->pitch;
-        int32 bufferPitch = bwin->GetRowBytes();
-        uint8 *windowpx;
-        uint8 *bufferpx;
-
-        int32 BPP = bwin->GetBytesPerPx();
-        uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
-        int32 windowSub = bwin->GetFbX() * BPP +
-                          bwin->GetFbY() * windowPitch;
-        clipping_rect *clips = bwin->GetClips();
-        int32 numClips = bwin->GetNumClips();
-        int i, y;
-
-        /* Blit each clipping rectangle */
-        bscreen.WaitForRetrace();
-        for(i = 0; i < numClips; ++i) {
-            /* Get addresses of the start of each clipping rectangle */
-            int32 width = clips[i].right - clips[i].left + 1;
-            int32 height = clips[i].bottom - clips[i].top + 1;
-            bufferpx = bwin->GetBufferPx() + 
-                clips[i].top * bufferPitch + clips[i].left * BPP;
-            windowpx = windowBaseAddress + 
-                clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
-
-            /* Copy each row of pixels from the window buffer into the frame
-               buffer */
-            for(y = 0; y < height; ++y)
-            {
-                memcpy(bufferpx, windowpx, width * BPP);
-                bufferpx += bufferPitch;
-                windowpx += windowPitch;
-            }
-        }
-        bwin->UnlockBuffer();
-    }
-    return 0;
+    bwin->UnlockBuffer();
 }
-#endif
 
 #ifdef __cplusplus
 }
diff --git a/src/video/haiku/SDL_bopengl.cc b/src/video/haiku/SDL_bopengl.cc
index e221177f451..0c7a704d88c 100644
--- a/src/video/haiku/SDL_bopengl.cc
+++ b/src/video/haiku/SDL_bopengl.cc
@@ -84,16 +84,21 @@ void *HAIKU_GL_GetProcAddress(_THIS, const char *proc)
 }
 
 
-
-
 int HAIKU_GL_SwapWindow(_THIS, SDL_Window * window) {
     _ToBeWin(window)->SwapBuffers();
     return 0;
 }
 
 int HAIKU_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) {
-    SDL_BWin* win = (SDL_BWin*)context;
-    _GetBeApp()->SetCurrentContext(win ? win->GetGLView() : NULL);
+    BGLView* glView = (BGLView*)context;
+    // printf("HAIKU_GL_MakeCurrent(%llx), win = %llx, thread = %d\n", (uint64)context, (uint64)window, find_thread(NULL));
+    if (glView != NULL) {
+        if ((glView->Window() == NULL) || (window == NULL) || (_ToBeWin(window)->GetGLView() != glView)) {
+            SDL_SetError("MakeCurrent failed");
+            return -1;
+        }
+    }
+    _GetBeApp()->SetCurrentContext(glView);
     return 0;
 }
 
@@ -102,6 +107,11 @@ SDL_GLContext HAIKU_GL_CreateContext(_THIS, SDL_Window * window) {
     /* FIXME: Not sure what flags should be included here; may want to have
        most of them */
     SDL_BWin *bwin = _ToBeWin(window);
+    // printf("HAIKU_GL_CreateContext, win = %llx, thread = %d\n", (uint64)window, find_thread(NULL));
+    if (bwin->GetGLView() != NULL) {
+        SDL_SetError("Context already creaded");
+        return NULL;
+    }
     Uint32 gl_flags = BGL_RGB;
     if (_this->gl_config.alpha_size) {
         gl_flags |= BGL_ALPHA;
@@ -123,13 +133,25 @@ SDL_GLContext HAIKU_GL_CreateContext(_THIS, SDL_Window * window) {
             _this->gl_config.accum_alpha_size) {
         gl_flags |= BGL_ACCUM;
     }
+#if __GNUC__ > 3
+    if (_this->gl_config.share_with_current_context) {
+        gl_flags |= BGL_SHARE_CONTEXT;
+    }
+#endif
     bwin->CreateGLView(gl_flags);
-    return (SDL_GLContext)(bwin);
+    _GetBeApp()->SetCurrentContext(bwin->GetGLView());
+    return (SDL_GLContext)(bwin->GetGLView());
 }
 
 void HAIKU_GL_DeleteContext(_THIS, SDL_GLContext context) {
-    /* Currently, automatically unlocks the view */
-    ((SDL_BWin*)context)->RemoveGLView();
+    // printf("HAIKU_GL_DeleteContext(%llx), thread = %d\n", (uint64)context, find_thread(NULL));
+    BGLView* glView = (BGLView*)context;
+    SDL_BWin *bwin = (SDL_BWin*)glView->Window();
+    if (bwin == NULL) {
+        delete glView;
+    } else {
+        bwin->RemoveGLView();
+    }
 }
 
 
diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc
index 77259f9084f..1ac3201f2f0 100644
--- a/src/video/haiku/SDL_bvideo.cc
+++ b/src/video/haiku/SDL_bvideo.cc
@@ -94,6 +94,7 @@ HAIKU_CreateDevice(int devindex)
     device->SetWindowGammaRamp = HAIKU_SetWindowGammaRamp;
     device->GetWindowGammaRamp = HAIKU_GetWindowGammaRamp;
     device->SetWindowMouseGrab = HAIKU_SetWindowMouseGrab;
+    device->SetWindowMinimumSize = HAIKU_SetWindowMinimumSize;
     device->DestroyWindow = HAIKU_DestroyWindow;
     device->GetWindowWMInfo = HAIKU_GetWindowWMInfo;
     device->CreateWindowFramebuffer = HAIKU_CreateWindowFramebuffer;
@@ -190,6 +191,31 @@ HAIKU_FreeCursor(SDL_Cursor * cursor)
     SDL_free(cursor);
 }
 
+static SDL_Cursor *
+HAIKU_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{
+    SDL_Cursor *cursor;
+    SDL_Surface *converted;
+
+    converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
+    if (!converted) {
+        return NULL;
+    }
+
+	BBitmap *cursorBitmap = new BBitmap(BRect(0, 0, surface->w - 1, surface->h - 1), B_RGBA32);
+	cursorBitmap->SetBits(converted->pixels, converted->h * converted->pitch, 0, B_RGBA32);
+    SDL_FreeSurface(converted);
+
+    cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
+    if (cursor) {
+        cursor->driverdata = (void *)new BCursor(cursorBitmap, BPoint(hot_x, hot_y));
+    } else {
+        return NULL;
+    }
+
+    return cursor;
+}
+
 static int HAIKU_ShowCursor(SDL_Cursor *cursor)
 {
 	SDL_Mouse *mouse = SDL_GetMouse();
@@ -222,7 +248,7 @@ HAIKU_SetRelativeMouseMode(SDL_bool enabled)
 
 	bewin->Lock();
 	if (enabled)
-		_SDL_GLView->SetEventMask(B_POINTER_EVENTS | B_KEYBOARD_EVENTS, B_NO_POINTER_HISTORY);
+		_SDL_GLView->SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
 	else
 		_SDL_GLView->SetEventMask(0, 0);
 	bewin->Unlock();
@@ -235,6 +261,7 @@ static void HAIKU_MouseInit(_THIS)
 	SDL_Mouse *mouse = SDL_GetMouse();
 	if (!mouse)
 		return;
+	mouse->CreateCursor = HAIKU_CreateCursor;
 	mouse->CreateSystemCursor = HAIKU_CreateSystemCursor;
 	mouse->ShowCursor = HAIKU_ShowCursor;
 	mouse->FreeCursor = HAIKU_FreeCursor;
diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc
index 57aba174168..587affad29c 100644
--- a/src/video/haiku/SDL_bwindow.cc
+++ b/src/video/haiku/SDL_bwindow.cc
@@ -205,6 +205,13 @@ int HAIKU_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp) {
 }
 
 
+void HAIKU_SetWindowMinimumSize(_THIS, SDL_Window * window){
+    BMessage msg(BWIN_MINIMUM_SIZE_WINDOW);
+    msg.AddInt32("window-w", window->w -1);
+    msg.AddInt32("window-h", window->h -1);
+    _ToBeWin(window)->PostMessage(&msg);
+}
+
 void HAIKU_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed) {
     /* TODO: Implement this! */
 }
diff --git a/src/video/haiku/SDL_bwindow.h b/src/video/haiku/SDL_bwindow.h
index 1d6a3c591d7..58a85d8725d 100644
--- a/src/video/haiku/SDL_bwindow.h
+++ b/src/video/haiku/SDL_bwindow.h
@@ -32,6 +32,7 @@ extern void HAIKU_SetWindowTitle(_THIS, SDL_Window * window);
 extern void HAIKU_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
 extern void HAIKU_SetWindowPosition(_THIS, SDL_Window * window);
 extern void HAIKU_SetWindowSize(_THIS, SDL_Window * window);
+extern void HAIKU_SetWindowMinimumSize(_THIS, SDL_Window * window);
 extern void HAIKU_ShowWindow(_THIS, SDL_Window * window);
 extern void HAIKU_HideWindow(_THIS, SDL_Window * window);
 extern void HAIKU_RaiseWindow(_THIS, SDL_Window * window);