From e6cc4e7f4b8189be55dd3b0e13e54e59f73d7672 Mon Sep 17 00:00:00 2001
From: X512 <danger_mail@list.ru>
Date: Thu, 30 Jan 2020 04:01:58 +0900
Subject: libsdl2: Remove BDirectWindow, fix OpenGL handling.

* BDirectWindow changed to BWindow.
* Implemented fullscreen.
* Introduced view for non-OpenGL drawing.
* Drawing thread removed, window thread is used instead.
* Use BGLView as OpenGL context. Implement proper context switching and OpenGL
  locking. Only one context per window is supported. BGLView should be not
  deleted when window is closed, it deleted when deleting context.

diff --git a/src/main/haiku/SDL_BApp.h b/src/main/haiku/SDL_BApp.h
index 56b1fa0..b8b9939 100644
--- a/src/main/haiku/SDL_BApp.h
+++ b/src/main/haiku/SDL_BApp.h
@@ -198,6 +198,10 @@ public:
     }
 
 #if SDL_VIDEO_OPENGL
+    BGLView *GetCurrentContext() {
+        return _current_context;
+    }
+    
     void SetCurrentContext(BGLView *newContext) {
         if(_current_context)
             _current_context->UnlockGL();
@@ -234,25 +238,22 @@ private:
         }
         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();
-		}
-
-        /* Tell the application that the mouse passed over, redraw needed */
-        HAIKU_UpdateWindowFramebuffer(NULL,win,NULL,-1);
+        // 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) {
diff --git a/src/video/haiku/SDL_BWin.h b/src/video/haiku/SDL_BWin.h
index dc6e442..2e947a1 100644
--- a/src/video/haiku/SDL_BWin.h
+++ b/src/video/haiku/SDL_BWin.h
@@ -39,7 +39,6 @@ extern "C" {
 #include <AppKit.h>
 #include <Cursor.h>
 #include <InterfaceKit.h>
-#include <game/DirectWindow.h>
 #if SDL_VIDEO_OPENGL
 #include <opengl/GLView.h>
 #endif
@@ -58,19 +57,47 @@ enum WinCommands {
     BWIN_SET_TITLE,
     BWIN_SET_BORDERED,
     BWIN_SET_RESIZABLE,
-    BWIN_FULLSCREEN
+    BWIN_FULLSCREEN,
+    BWIN_UPDATE_FRAMEBUFFER
 };
 
+// non-OpenGL framebuffer view
+class SDL_BView: public BView
+{
+public:
+    SDL_BView(BRect frame, const char* name, uint32 resizingMode)
+        : BView(frame, name, resizingMode, B_WILL_DRAW),
+        fBitmap(NULL)
+    {
+    }
+
+    void Draw(BRect dirty)
+    {
+        if (fBitmap != NULL)
+            DrawBitmap(fBitmap, B_ORIGIN);
+    }
+
+    void SetBitmap(BBitmap *bitmap)
+    {
+        fBitmap = bitmap;
+    }
+
+private:
+    BBitmap *fBitmap;
+};
 
-class SDL_BWin:public BDirectWindow
+class SDL_BWin: public BWindow
 {
   public:
     /* Constructor/Destructor */
     SDL_BWin(BRect bounds, window_look look, uint32 flags)
-        : BDirectWindow(bounds, "Untitled", look, B_NORMAL_WINDOW_FEEL, flags)
+        : BWindow(bounds, "Untitled", look, B_NORMAL_WINDOW_FEEL, flags)
     {
         _last_buttons = 0;
 
+        _cur_view = NULL;
+        _SDL_View = NULL;
+
 #if SDL_VIDEO_OPENGL
         _SDL_GLView = NULL;
         _gl_type = 0;
@@ -79,59 +106,88 @@ class SDL_BWin:public BDirectWindow
         _inhibit_resize = false;
         _mouse_focused = false;
         _prev_frame = NULL;
+        _fullscreen = NULL;
 
         /* Handle framebuffer stuff */
-        _connected = _connection_disabled = false;
-        _buffer_created = _buffer_dirty = false;
-        _trash_window_buffer = false;
         _buffer_locker = new BLocker();
         _bitmap = NULL;
-        _clips = NULL;
-        _num_clips = 0;
-
-#ifdef DRAWTHREAD
-        _draw_thread_id = spawn_thread(HAIKU_DrawThread, "drawing_thread",
-                            B_NORMAL_PRIORITY, (void*) this);
-        resume_thread(_draw_thread_id);
-#endif
     }
 
     virtual ~ SDL_BWin()
     {
         Lock();
-        _connection_disabled = true;
-        int32 result;
+        
+        if (_SDL_View != NULL && _SDL_View != _cur_view) {
+            delete _SDL_View;
+            _SDL_View = NULL;
+        }
 
 #if SDL_VIDEO_OPENGL
         if (_SDL_GLView) {
-            _SDL_GLView->UnlockGL();
-            RemoveChild(_SDL_GLView);   /* Why was this outside the if
-                                            statement before? */
+            if (((SDL_BApp*)be_app)->GetCurrentContext() == _SDL_GLView)
+                ((SDL_BApp*)be_app)->SetCurrentContext(NULL);
+            if (_SDL_GLView == _cur_view)
+                RemoveChild(_SDL_GLView);
+            _SDL_GLView = NULL;
+            // _SDL_GLView deleted by HAIKU_GL_DeleteContext
         }
 
 #endif
         Unlock();
-#if SDL_VIDEO_OPENGL
-        if (_SDL_GLView) {
-            delete _SDL_GLView;
-        }
-#endif
 
         delete _prev_frame;
 
         /* Clean up framebuffer stuff */
         _buffer_locker->Lock();
-#ifdef DRAWTHREAD
-        wait_for_thread(_draw_thread_id, &result);
-#endif
-        SDL_free(_clips);
         delete _buffer_locker;
     }
+    
+    void SetCurrentView(BView *view)
+    {
+        if (_cur_view != view) {
+            if (_cur_view != NULL)
+                RemoveChild(_cur_view);
+            _cur_view = view;
+            if (_cur_view != NULL)
+                AddChild(_cur_view);
+        }
+    }
+
+    void UpdateCurrentView()
+    {
+        if (_SDL_GLView != NULL) {
+            SetCurrentView(_SDL_GLView);
+        } else if (_SDL_View != NULL) {
+            SetCurrentView(_SDL_View);
+        } else {
+            SetCurrentView(NULL);
+        }
+    }
+
+    SDL_BView *CreateView() {
+        Lock();
+        if (_SDL_View == NULL) {
+            _SDL_View = new SDL_BView(Bounds(), "SDL View", B_FOLLOW_ALL_SIDES);
+            UpdateCurrentView();
+        }
+        Unlock();
+        return _SDL_View;
+    }
 
+    void RemoveView() {
+        Lock();
+        if(_SDL_View != NULL) {
+            SDL_BView *oldView = _SDL_View;
+            _SDL_View = NULL;
+            UpdateCurrentView();
+            delete oldView;
+        }
+        Unlock();
+    }
 
     /* * * * * OpenGL functionality * * * * */
 #if SDL_VIDEO_OPENGL
-    virtual BGLView *CreateGLView(Uint32 gl_flags) {
+    BGLView *CreateGLView(Uint32 gl_flags) {
         Lock();
         if (_SDL_GLView == NULL) {
             _SDL_GLView = new BGLView(Bounds(), "SDL GLView",
@@ -139,92 +195,29 @@ class SDL_BWin:public BDirectWindow
                                      (B_WILL_DRAW | B_FRAME_EVENTS),
                                      gl_flags);
             _gl_type = gl_flags;
+            UpdateCurrentView();
         }
-        AddChild(_SDL_GLView);
-        _SDL_GLView->EnableDirectMode(false); /* Disable direct mode */
-        _SDL_GLView->LockGL();  /* "New" GLViews are created */
         Unlock();
-        return (_SDL_GLView);
+        return _SDL_GLView;
     }
 
-    virtual void RemoveGLView() {
+    void RemoveGLView() {
         Lock();
-        if(_SDL_GLView) {
-            _SDL_GLView->UnlockGL();
-            RemoveChild(_SDL_GLView);
+        if(_SDL_GLView != NULL) {
+            if (((SDL_BApp*)be_app)->GetCurrentContext() == _SDL_GLView)
+                ((SDL_BApp*)be_app)->SetCurrentContext(NULL);
+            _SDL_GLView = NULL;
+            UpdateCurrentView();
+            // _SDL_GLView deleted by HAIKU_GL_DeleteContext
         }
         Unlock();
     }
 
-    virtual void SwapBuffers(void) {
-        _SDL_GLView->UnlockGL();
-        _SDL_GLView->LockGL();
+    void SwapBuffers(void) {
         _SDL_GLView->SwapBuffers();
     }
 #endif
 
-    /* * * * * Framebuffering* * * * */
-    virtual void DirectConnected(direct_buffer_info *info) {
-        if(!_connected && _connection_disabled) {
-            return;
-        }
-
-        /* Determine if the pixel buffer is usable after this update */
-        _trash_window_buffer =      _trash_window_buffer
-                                || ((info->buffer_state & B_BUFFER_RESIZED)
-                                || (info->buffer_state & B_BUFFER_RESET)
-                                || (info->driver_state == B_MODE_CHANGED));
-        LockBuffer();
-
-        switch(info->buffer_state & B_DIRECT_MODE_MASK) {
-        case B_DIRECT_START:
-            _connected = true;
-
-        case B_DIRECT_MODIFY:
-            if (info->clip_list_count > _num_clips)
-            {
-                if(_clips) {
-                    SDL_free(_clips);
-                    _clips = NULL;
-                }
-            }
-
-            _num_clips = info->clip_list_count;
-            if (_clips == NULL)
-                _clips = (clipping_rect *)SDL_malloc(_num_clips*sizeof(clipping_rect));
-            if(_clips) {
-                SDL_memcpy(_clips, info->clip_list,
-                    _num_clips*sizeof(clipping_rect));
-
-                _bits = (uint8*) info->bits;
-                _row_bytes = info->bytes_per_row;
-                _bounds = info->window_bounds;
-                _bytes_per_px = info->bits_per_pixel / 8;
-                _buffer_dirty = true;
-            }
-            break;
-
-        case B_DIRECT_STOP:
-            _connected = false;
-            break;
-        }
-#if SDL_VIDEO_OPENGL
-        if(_SDL_GLView) {
-            _SDL_GLView->DirectConnected(info);
-        }
-#endif
-
-
-        /* Call the base object directconnected */
-        BDirectWindow::DirectConnected(info);
-
-        UnlockBuffer();
-
-    }
-
-
-
-
     /* * * * * Event sending * * * * */
     /* Hook functions */
     virtual void FrameMoved(BPoint origin) {
@@ -235,10 +228,10 @@ class SDL_BWin:public BDirectWindow
         _PostWindowEvent(msg);
 
         /* Perform normal hook operations */
-        BDirectWindow::FrameMoved(origin);
+        BWindow::FrameMoved(origin);
     }
 
-    virtual void FrameResized(float width, float height) {
+    void FrameResized(float width, float height) {
         /* Post a message to the BApp so that it can handle the window event */
         BMessage msg(BAPP_WINDOW_RESIZED);
 
@@ -247,10 +240,10 @@ class SDL_BWin:public BDirectWindow
         _PostWindowEvent(msg);
 
         /* Perform normal hook operations */
-        BDirectWindow::FrameResized(width, height);
+        BWindow::FrameResized(width, height);
     }
 
-    virtual bool QuitRequested() {
+    bool QuitRequested() {
         BMessage msg(BAPP_WINDOW_CLOSE_REQUESTED);
         _PostWindowEvent(msg);
 
@@ -258,13 +251,13 @@ class SDL_BWin:public BDirectWindow
         return false;
     }
 
-    virtual void WindowActivated(bool active) {
+    void WindowActivated(bool active) {
         BMessage msg(BAPP_KEYBOARD_FOCUS);  /* Mouse focus sold separately */
         msg.AddBool("focusGained", active);
         _PostWindowEvent(msg);
     }
 
-    virtual void Zoom(BPoint origin,
+    void Zoom(BPoint origin,
                 float width,
                 float height) {
         BMessage msg(BAPP_MAXIMIZE);    /* Closest thing to maximization Haiku has */
@@ -275,13 +268,13 @@ class SDL_BWin:public BDirectWindow
             _prev_frame = new BRect(Frame());
 
         /* Perform normal hook operations */
-        BDirectWindow::Zoom(origin, width, height);
+        BWindow::Zoom(origin, width, height);
     }
 
     /* Member functions */
-    virtual void Show() {
+    void Show() {
         while(IsHidden()) {
-            BDirectWindow::Show();
+            BWindow::Show();
         }
         _shown = true;
 
@@ -289,25 +282,33 @@ class SDL_BWin:public BDirectWindow
         _PostWindowEvent(msg);
     }
 
-    virtual void Hide() {
-        BDirectWindow::Hide();
+    void Hide() {
+        BWindow::Hide();
         _shown = false;
 
         BMessage msg(BAPP_HIDE);
         _PostWindowEvent(msg);
     }
 
-    virtual void Minimize(bool minimize) {
-        BDirectWindow::Minimize(minimize);
+    void Minimize(bool minimize) {
+        BWindow::Minimize(minimize);
         int32 minState = (minimize ? BAPP_MINIMIZE : BAPP_RESTORE);
 
         BMessage msg(minState);
         _PostWindowEvent(msg);
     }
 
+    void ScreenChanged(BRect screenFrame, color_space depth)
+    {
+        if (_fullscreen) {
+            MoveTo(screenFrame.left, screenFrame.top);
+            ResizeTo(screenFrame.Width(), screenFrame.Height());
+        }
+    }
+
 
     /* BView message interruption */
-    virtual void DispatchMessage(BMessage * msg, BHandler * target)
+    void DispatchMessage(BMessage * msg, BHandler * target)
     {
         BPoint where;   /* Used by mouse moved */
         int32 buttons;  /* Used for mouse button events */
@@ -356,7 +357,7 @@ class SDL_BWin:public BDirectWindow
                 }
             }
             break;
-            
+
         case B_UNMAPPED_KEY_DOWN:      /* modifier keys are unmapped */
             if (msg->FindInt32("key", &key) == B_OK) {
                 _KeyEvent((SDL_Scancode)key, NULL, 0, SDL_PRESSED);
@@ -376,15 +377,15 @@ class SDL_BWin:public BDirectWindow
                - CTRL+Q to close window (and other shortcuts)
                - PrintScreen to make screenshot into /boot/home
                - etc.. */
-            /* BDirectWindow::DispatchMessage(msg, target); */
+            /* BWindow::DispatchMessage(msg, target); */
             break;
         }
 
-        BDirectWindow::DispatchMessage(msg, target);
+        BWindow::DispatchMessage(msg, target);
     }
 
     /* Handle command messages */
-    virtual void MessageReceived(BMessage* message) {
+    void MessageReceived(BMessage* message) {
         switch (message->what) {
             /* Handle commands from SDL */
             case BWIN_SET_TITLE:
@@ -396,12 +397,18 @@ class SDL_BWin:public BDirectWindow
             case BWIN_RESIZE_WINDOW:
                 _ResizeTo(message);
                 break;
-            case BWIN_SET_BORDERED:
-                _SetBordered(message);
+            case BWIN_SET_BORDERED: {
+                bool bEnabled;
+                if (message->FindBool("window-border", &bEnabled) == B_OK)
+                    _SetBordered(bEnabled);
                 break;
-            case BWIN_SET_RESIZABLE:
-                _SetResizable(message);
+            }
+            case BWIN_SET_RESIZABLE: {
+                bool bEnabled;
+                if (message->FindBool("window-resizable", &bEnabled) == B_OK)
+                    _SetResizable(bEnabled);
                 break;
+            }
             case BWIN_SHOW_WINDOW:
                 Show();
                 break;
@@ -417,12 +424,31 @@ class SDL_BWin:public BDirectWindow
             case BWIN_RESTORE_WINDOW:
                 _Restore();
                 break;
-            case BWIN_FULLSCREEN:
-                _SetFullScreen(message);
+            case BWIN_FULLSCREEN: {
+                bool fullscreen;
+                if (message->FindBool("fullscreen", &fullscreen) == B_OK)
+                    _SetFullScreen(fullscreen);
                 break;
+            }
+            case BWIN_UPDATE_FRAMEBUFFER: {
+                BMessage* pendingMessage;
+                while ((pendingMessage
+                                = MessageQueue()->FindMessage(BWIN_UPDATE_FRAMEBUFFER, 0))) {
+                        MessageQueue()->RemoveMessage(pendingMessage);
+                        delete pendingMessage;
+                }
+                if (_bitmap != NULL) {
+                    if (_SDL_View != NULL && _cur_view == _SDL_View)
+                        _SDL_View->Draw(Bounds());
+                    else if (_SDL_GLView != NULL && _cur_view == _SDL_GLView) {
+                        _SDL_GLView->CopyPixelsIn(_bitmap, B_ORIGIN);
+                    }
+                }
+                break;
+            }
             default:
                 /* Perform normal message handling */
-                BDirectWindow::MessageReceived(message);
+                BWindow::MessageReceived(message);
                 break;
         }
 
@@ -433,19 +459,9 @@ class SDL_BWin:public BDirectWindow
     /* Accessor methods */
     bool IsShown() { return _shown; }
     int32 GetID() { return _id; }
-    uint32 GetRowBytes() { return _row_bytes; }
-    int32 GetFbX() { return _bounds.left; }
-    int32 GetFbY() { return _bounds.top; }
-    bool ConnectionEnabled() { return !_connection_disabled; }
-    bool Connected() { return _connected; }
-    clipping_rect *GetClips() { return _clips; }
-    int32 GetNumClips() { return _num_clips; }
-    uint8* GetBufferPx() { return _bits; }
-    int32 GetBytesPerPx() { return _bytes_per_px; }
-    bool CanTrashWindowBuffer() { return _trash_window_buffer; }
-    bool BufferExists() { return _buffer_created; }
-    bool BufferIsDirty() { return _buffer_dirty; }
     BBitmap *GetBitmap() { return _bitmap; }
+    BView *GetCurView() { return _cur_view; }
+    SDL_BView *GetView() { return _SDL_View; }
 #if SDL_VIDEO_OPENGL
     BGLView *GetGLView() { return _SDL_GLView; }
     Uint32 GetGLType() { return _gl_type; }
@@ -453,12 +469,9 @@ class SDL_BWin:public BDirectWindow
 
     /* Setter methods */
     void SetID(int32 id) { _id = id; }
-    void SetBufferExists(bool bufferExists) { _buffer_created = bufferExists; }
     void LockBuffer() { _buffer_locker->Lock(); }
     void UnlockBuffer() { _buffer_locker->Unlock(); }
-    void SetBufferDirty(bool bufferDirty) { _buffer_dirty = bufferDirty; }
-    void SetTrashBuffer(bool trash) { _trash_window_buffer = trash;     }
-    void SetBitmap(BBitmap *bitmap) { _bitmap = bitmap; }
+    void SetBitmap(BBitmap *bitmap) { _bitmap = bitmap; if (_SDL_View != NULL) _SDL_View->SetBitmap(bitmap); }
 
 
 private:
@@ -564,7 +577,10 @@ private:
         ) {
             return;
         }
-        MoveTo(x, y);
+        if (_fullscreen)
+            _non_fullscreen_frame.OffsetTo(x, y);
+        else
+            MoveTo(x, y);
     }
 
     void _ResizeTo(BMessage *msg) {
@@ -575,26 +591,29 @@ private:
         ) {
             return;
         }
-        ResizeTo(w, h);
+        if (_fullscreen) {
+            _non_fullscreen_frame.right = _non_fullscreen_frame.left + w;
+            _non_fullscreen_frame.bottom = _non_fullscreen_frame.top + h;
+        } else
+            ResizeTo(w, h);
     }
 
-    void _SetBordered(BMessage *msg) {
-        bool bEnabled;
-        if(msg->FindBool("window-border", &bEnabled) != B_OK) {
-            return;
-        }
-        SetLook(bEnabled ? B_TITLED_WINDOW_LOOK : B_NO_BORDER_WINDOW_LOOK);
+    void _SetBordered(bool bEnabled) {
+        if (_fullscreen)
+            _bordered = bEnabled;
+        else
+            SetLook(bEnabled ? B_TITLED_WINDOW_LOOK : B_NO_BORDER_WINDOW_LOOK);
     }
 
-    void _SetResizable(BMessage *msg) {
-        bool bEnabled;
-        if(msg->FindBool("window-resizable", &bEnabled) != B_OK) {
-            return;
-        }
-        if (bEnabled) {
-            SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
-        } else {
-            SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+    void _SetResizable(bool bEnabled) {
+        if (_fullscreen)
+            _resizable = bEnabled;
+        else {
+            if (bEnabled) {
+                SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+            } else {
+                SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+            }
         }
     }
 
@@ -603,23 +622,42 @@ private:
             Minimize(false);
         } else if(IsHidden()) {
             Show();
+        } else if (_fullscreen) {
+
         } else if(_prev_frame != NULL) {    /* Zoomed */
             MoveTo(_prev_frame->left, _prev_frame->top);
             ResizeTo(_prev_frame->Width(), _prev_frame->Height());
         }
     }
 
-    void _SetFullScreen(BMessage *msg) {
-        bool fullscreen;
-        if(
-            msg->FindBool("fullscreen", &fullscreen) != B_OK
-        ) {
-            return;
+    void _SetFullScreen(bool fullscreen) {
+        if (fullscreen != _fullscreen) {
+            if (fullscreen) {
+                BScreen screen(this);
+                BRect screenFrame = screen.Frame();
+                printf("screen frame: "); screenFrame.PrintToStream(); printf("\n");
+                _bordered = Look() != B_NO_BORDER_WINDOW_LOOK;
+                _resizable = !(Flags() & B_NOT_RESIZABLE);
+                _non_fullscreen_frame = Frame();
+                _SetBordered(false);
+                _SetResizable(false);
+                MoveTo(screenFrame.left, screenFrame.top);
+                ResizeTo(screenFrame.Width(), screenFrame.Height());
+                _fullscreen = fullscreen;
+            } else {
+                _fullscreen = fullscreen;
+                MoveTo(_non_fullscreen_frame.left, _non_fullscreen_frame.top);
+                ResizeTo(_non_fullscreen_frame.Width(), _non_fullscreen_frame.Height());
+                _SetBordered(_bordered);
+                _SetResizable(_resizable);
+            }
         }
-        SetFullScreen(fullscreen);
     }
 
     /* Members */
+
+    BView* _cur_view;
+    SDL_BView* _SDL_View;
 #if SDL_VIDEO_OPENGL
     BGLView * _SDL_GLView;
     Uint32 _gl_type;
@@ -632,23 +670,15 @@ private:
     bool  _inhibit_resize;
 
     BRect *_prev_frame; /* Previous position and size of the window */
+    bool _fullscreen;
+    // valid only if fullscreen
+    BRect _non_fullscreen_frame;
+    bool _bordered;
+    bool _resizable;
 
     /* Framebuffer members */
-    bool            _connected,
-                    _connection_disabled,
-                    _buffer_created,
-                    _buffer_dirty,
-                    _trash_window_buffer;
-    uint8          *_bits;
-    uint32          _row_bytes;
-    clipping_rect   _bounds;
-    BLocker        *_buffer_locker;
-    clipping_rect  *_clips;
-    uint32          _num_clips;
-    int32           _bytes_per_px;
-    thread_id       _draw_thread_id;
-
-    BBitmap        *_bitmap;
+    BLocker *_buffer_locker;
+    BBitmap *_bitmap;
 };
 
 
diff --git a/src/video/haiku/SDL_bframebuffer.cc b/src/video/haiku/SDL_bframebuffer.cc
index c1017eb..9712319 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 e221177..c88cb37 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,23 @@ SDL_GLContext HAIKU_GL_CreateContext(_THIS, SDL_Window * window) {
             _this->gl_config.accum_alpha_size) {
         gl_flags |= BGL_ACCUM;
     }
+    if (_this->gl_config.share_with_current_context) {
+        gl_flags |= BGL_SHARE_CONTEXT;
+    }
     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();
+    }
 }
 
 
-- 
2.30.2


From b23c88239d9a3ee907eebf0b225465d600b8dde7 Mon Sep 17 00:00:00 2001
From: Augustin Cavalier <waddlesplash@gmail.com>
Date: Tue, 11 Jan 2022 17:15:28 -0500
Subject: RelativeMouseMode: B_KEYBOARD_EVENTS is not needed.


diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc
index 77259f9..5551e92 100644
--- a/src/video/haiku/SDL_bvideo.cc
+++ b/src/video/haiku/SDL_bvideo.cc
@@ -222,7 +222,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();
-- 
2.30.2


From 7fa278e0623c0da9a50c587703bbcc79726306c7 Mon Sep 17 00:00:00 2001
From: Pascal Abresch <nep@packageloss.eu>
Date: Mon, 15 Nov 2021 16:32:58 +0100
Subject: Implement SDL_SendDropFile for opening files with RefsReceived


diff --git a/src/main/haiku/SDL_BApp.h b/src/main/haiku/SDL_BApp.h
index b8b9939..215f836 100644
--- a/src/main/haiku/SDL_BApp.h
+++ b/src/main/haiku/SDL_BApp.h
@@ -21,6 +21,7 @@
 #ifndef SDL_BAPP_H
 #define SDL_BAPP_H
 
+#include <Path.h>
 #include <InterfaceKit.h>
 #include <LocaleRoster.h>
 #if SDL_VIDEO_OPENGL
@@ -93,6 +94,15 @@ public:
     }
 
 
+	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) {
@@ -301,7 +311,7 @@ private:
         }
         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;
-- 
2.30.2


From 44a98d9a7ef399fa047c35d6ea27915b0288ae6d Mon Sep 17 00:00:00 2001
From: Pascal Abresch <nep@packageloss.eu>
Date: Sat, 4 Dec 2021 10:08:01 +0100
Subject: SDL2: implement minimum window size for Haiku


diff --git a/src/video/haiku/SDL_BWin.h b/src/video/haiku/SDL_BWin.h
index 2e947a1..1ac5171 100644
--- a/src/video/haiku/SDL_BWin.h
+++ b/src/video/haiku/SDL_BWin.h
@@ -58,7 +58,8 @@ enum WinCommands {
     BWIN_SET_BORDERED,
     BWIN_SET_RESIZABLE,
     BWIN_FULLSCREEN,
-    BWIN_UPDATE_FRAMEBUFFER
+    BWIN_UPDATE_FRAMEBUFFER,
+    BWIN_MINIMUM_SIZE_WINDOW
 };
 
 // non-OpenGL framebuffer view
@@ -430,6 +431,9 @@ class SDL_BWin: public BWindow
                     _SetFullScreen(fullscreen);
                 break;
             }
+            case BWIN_MINIMUM_SIZE_WINDOW:
+                _SetMinimumSize(message);
+                break;
             case BWIN_UPDATE_FRAMEBUFFER: {
                 BMessage* pendingMessage;
                 while ((pendingMessage
@@ -617,6 +621,24 @@ private:
         }
     }
 
+    void _SetMinimumSize(BMessage *msg) {
+        float maxHeight;
+        float maxWidth;
+        float _;
+        int32 minHeight;
+        int32 minWidth;
+
+        // This is a bit convoluted, we only want to set the minimum not the maximum
+        // But there is no direct call to do that, so store the maximum size beforehand
+        GetSizeLimits(&_, &maxWidth, &_, &maxHeight);
+        if (msg->FindInt32("window-w", &minWidth) != B_OK)
+            return;
+        if (msg->FindInt32("window-h", &minHeight) != B_OK)
+            return;
+        SetSizeLimits((float)minWidth, maxWidth, (float)minHeight, maxHeight);
+        UpdateSizeLimits();
+    }
+
     void _Restore() {
         if(IsMinimized()) {
             Minimize(false);
diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc
index 5551e92..ca9dcad 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;
diff --git a/src/video/haiku/SDL_bwindow.cc b/src/video/haiku/SDL_bwindow.cc
index 57aba17..587affa 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 1d6a3c5..58a85d8 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);
-- 
2.30.2


From ff9a8fe69d69213b2633d3bc0eb14dbd1836cc72 Mon Sep 17 00:00:00 2001
From: Augustin Cavalier <waddlesplash@gmail.com>
Date: Tue, 11 Jan 2022 17:45:29 -0500
Subject: Only expect BGL_SHARE_CONTEXT on __GNUC__ > 3.


diff --git a/src/video/haiku/SDL_bopengl.cc b/src/video/haiku/SDL_bopengl.cc
index c88cb37..0c7a704 100644
--- a/src/video/haiku/SDL_bopengl.cc
+++ b/src/video/haiku/SDL_bopengl.cc
@@ -133,9 +133,11 @@ 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);
     _GetBeApp()->SetCurrentContext(bwin->GetGLView());
     return (SDL_GLContext)(bwin->GetGLView());
-- 
2.30.2


From 6371539d891837b999d57efa995fa78beb581c77 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Wed, 12 Jan 2022 11:59:06 +1000
Subject: Workaround for gcc2


diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c
index 12cc2da..bc46aec 100644
--- a/src/stdlib/SDL_string.c
+++ b/src/stdlib/SDL_string.c
@@ -34,6 +34,10 @@
 #define va_copy(dst, src)   dst = src
 #endif
 
+#if __GNUC__ == 2
+#define va_copy(to, from)   __va_copy(to, from)
+#endif
+
 #if !defined(HAVE_VSSCANF) || !defined(HAVE_STRTOL) || !defined(HAVE_STRTOUL) || !defined(HAVE_STRTOD) || !defined(HAVE_STRTOLL) || !defined(HAVE_STRTOULL)
 #define SDL_isupperhex(X)   (((X) >= 'A') && ((X) <= 'F'))
 #define SDL_islowerhex(X)   (((X) >= 'a') && ((X) <= 'f'))
-- 
2.30.2


From 61510a4a211bc7b3fe8006d3c16447cef07e11a0 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 12 Dec 2021 10:07:47 +1000
Subject: Add bitmap cursor support


diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc
index c5026de..868512e 100644
--- a/src/video/haiku/SDL_bvideo.cc
+++ b/src/video/haiku/SDL_bvideo.cc
@@ -190,6 +190,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();
@@ -235,6 +260,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;
-- 
2.30.2
