diff options
author | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
---|---|---|
committer | WlodekM <[email protected]> | 2024-06-16 10:35:45 +0300 |
commit | abef6da56913f1c55528103e60a50451a39628b1 (patch) | |
tree | b3c8092471ecbb73e568cd0d336efa0e7871ee8d /src/Window_BeOS.cpp |
initial commit
Diffstat (limited to 'src/Window_BeOS.cpp')
-rw-r--r-- | src/Window_BeOS.cpp | 743 |
1 files changed, 743 insertions, 0 deletions
diff --git a/src/Window_BeOS.cpp b/src/Window_BeOS.cpp new file mode 100644 index 0000000..38ef2d4 --- /dev/null +++ b/src/Window_BeOS.cpp @@ -0,0 +1,743 @@ +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_BEOS + +extern "C" { +#include "_WindowBase.h" +#include "Graphics.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Errors.h" +#include "Utils.h" +} +// Other +#include <errno.h> +// AppKit +#include <Application.h> +#include <Clipboard.h> +#include <Message.h> +// GLKit +#include <GL/gl.h> +#include <GLView.h> +// InterfaceKit +#include <Alert.h> +#include <Bitmap.h> +#include <Screen.h> +// StorageKit +#include <FilePanel.h> +#include <Path.h> + +static BApplication* app_handle; +static BWindow* win_handle; +static BView* view_handle; +static BGLView* view_3D; + +// Event management +enum CCEventType { + CC_NONE, + CC_MOUSE_SCROLL, CC_MOUSE_DOWN, CC_MOUSE_UP, CC_MOUSE_MOVE, + CC_KEY_DOWN, CC_KEY_UP, CC_KEY_INPUT, + CC_WIN_RESIZED, CC_WIN_FOCUS, CC_WIN_REDRAW, CC_WIN_QUIT, + CC_RAW_MOUSE +}; +union CCEventValue { float f32; int i32; void* ptr; }; +struct CCEvent { + int type; + CCEventValue v1, v2; +}; + +#define EVENTS_DEFAULT_MAX 30 +static void* events_mutex; +static int events_count, events_capacity; +static CCEvent* events_list, events_default[EVENTS_DEFAULT_MAX]; + +static void Events_Init(void) { + events_mutex = Mutex_Create("BeOS events"); + events_capacity = EVENTS_DEFAULT_MAX; + events_list = events_default; +} + +static void Events_Push(const CCEvent* event) { + Mutex_Lock(events_mutex); + { + if (events_count >= events_capacity) { + Utils_Resize((void**)&events_list, &events_capacity, + sizeof(CCEvent), EVENTS_DEFAULT_MAX, 20); + } + events_list[events_count++] = *event; + } + Mutex_Unlock(events_mutex); +} + +static cc_bool Events_Pull(CCEvent* event) { + cc_bool found = false; + + Mutex_Lock(events_mutex); + { + if (events_count) { + *event = events_list[0]; + for (int i = 1; i < events_count; i++) { + events_list[i - 1] = events_list[i]; + } + events_count--; + found = true; + } + } + Mutex_Unlock(events_mutex); + return found; +} + +// BApplication implementation +class CC_BApp : public BApplication +{ +public: + CC_BApp() : BApplication("application/x-ClassiCube") { } + void DispatchMessage(BMessage* msg, BHandler* handler); +}; + +static void CallOpenFileCallback(const char* path); +void CC_BApp::DispatchMessage(BMessage* msg, BHandler* handler) { + CCEvent event = { 0 }; + const char* filename; + entry_ref fileRef; + + switch (msg->what) + { + case B_QUIT_REQUESTED: + Platform_LogConst("APP QUIT"); + event.type = CC_WIN_QUIT; + break; + case B_REFS_RECEIVED: + // TODO do we need to support more than 1 ref? + if (msg->FindRef("refs", 0, &fileRef) == B_OK) { + BPath path(&fileRef); + CallOpenFileCallback(path.Path()); + } + break; + case B_SAVE_REQUESTED: + // TODO do we need to support more than 1 ref? + if (msg->FindRef("directory", 0, &fileRef) == B_OK && + msg->FindString("name", &filename) == B_OK) { + BDirectory folder(&fileRef); + BPath path(&folder, filename); + // TODO add default file extension + CallOpenFileCallback(path.Path()); + } + break; + default: + //Platform_LogConst("UNHANDLED APP MESSAGE:"); + //msg->PrintToStream(); + break; + } + if (event.type) Events_Push(&event); + BApplication::DispatchMessage(msg, handler); +} + +// BWindow implementation +class CC_BWindow : public BWindow +{ + public: + CC_BWindow(BRect frame) : BWindow(frame, "", B_TITLED_WINDOW, 0) { } + void DispatchMessage(BMessage* msg, BHandler* handler); + + virtual ~CC_BWindow() { + if (!view_3D) return; + + // Fixes OpenGL related crashes on exit since Mesa 21 + // Calling RemoveChild seems to fix the crash as per https://dev.haiku-os.org/ticket/16840 + // "Some OpenGL applications like GLInfo crash on exit under Mesa 21" + this->Lock(); + this->RemoveChild(view_3D); + this->Unlock(); + } +}; + +static void ProcessKeyInput(BMessage* msg) { + CCEvent event; + const char* value; + cc_codepoint cp; + + if (msg->FindString("bytes", &value) != B_OK) return; + if (!Convert_Utf8ToCodepoint(&cp, (const cc_uint8*)value, String_Length(value))) return; + + event.type = CC_KEY_INPUT; + event.v1.i32 = cp; + Events_Push(&event); +} + +static int last_buttons; +static int mouse_raw_delta, mouse_is_tablet; + +static void UpdateMouseButton(int btn, int pressed) { + CCEvent event; + event.type = pressed ? CC_MOUSE_DOWN : CC_MOUSE_UP; + event.v1.i32 = btn; + Events_Push(&event); +} + +static void UpdateMouseButtons(int buttons) { + // BeOS API is really odd in that it only provides you with a bitmask + // of 'current mouse buttons pressed' + int changed = buttons ^ last_buttons; + + // TODO move logic to UpdateMouseButton instead? + if (changed & B_PRIMARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_L, buttons & B_PRIMARY_MOUSE_BUTTON); + if (changed & B_SECONDARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_R, buttons & B_SECONDARY_MOUSE_BUTTON); + if (changed & B_TERTIARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_M, buttons & B_TERTIARY_MOUSE_BUTTON); + if (changed & B_MOUSE_BUTTON(4)) + UpdateMouseButton(CCMOUSE_X1, buttons & B_MOUSE_BUTTON(4)); + if (changed & B_MOUSE_BUTTON(5)) + UpdateMouseButton(CCMOUSE_X2, buttons & B_MOUSE_BUTTON(5)); + + last_buttons = buttons; +} + +static void HandleMouseMovement(BMessage* msg) { + int dx, dy; + float prs; + + if (msg->FindInt32("be:delta_x", &dx) == B_OK && + msg->FindInt32("be:delta_y", &dy) == B_OK) { + + CCEvent event = { 0 }; + event.type = CC_RAW_MOUSE; + event.v1.i32 = dx; + event.v2.i32 = -dy; + Events_Push(&event); + + mouse_raw_delta = true; + } else if (msg->FindFloat("be:tablet_pressure", &prs) == B_OK) { + mouse_is_tablet = true; + } +} + +void CC_BWindow::DispatchMessage(BMessage* msg, BHandler* handler) { + CCEvent event = { 0 }; + BPoint where; + float delta; + int32 value, width, height; + bool active; + + switch (msg->what) + { + case B_KEY_DOWN: + case B_UNMAPPED_KEY_DOWN: + if (msg->FindInt32("key", &value) == B_OK) { + event.type = CC_KEY_DOWN; + event.v1.i32 = value; + } + break; + case B_KEY_UP: + case B_UNMAPPED_KEY_UP: + if (msg->FindInt32("key", &value) == B_OK) { + event.type = CC_KEY_UP; + event.v1.i32 = value; + } + break; + case B_MOUSE_DOWN: + case B_MOUSE_UP: + if (msg->FindInt32("buttons", &value) == B_OK) { + UpdateMouseButtons(value); + HandleMouseMovement(msg); + } + break; + case B_MOUSE_MOVED: + if (msg->FindPoint("where", &where) == B_OK) { + event.type = CC_MOUSE_MOVE; + event.v1.i32 = where.x; + event.v2.i32 = where.y; + HandleMouseMovement(msg); + } + break; + case B_MOUSE_WHEEL_CHANGED: + if (msg->FindFloat("be:wheel_delta_y", &delta) == B_OK) { + event.type = CC_MOUSE_SCROLL; + event.v1.f32 = -delta; // negate to match other platforms + } + if (msg->FindFloat("be:wheel_delta_x", &delta) == B_OK) { + event.type = CC_MOUSE_SCROLL; + event.v2.f32 = -delta; // negate to match other platforms + } + break; + + case B_WINDOW_ACTIVATED: + if (msg->FindBool("active", &active) == B_OK) { + event.type = CC_WIN_FOCUS; + event.v1.i32 = active; + } + break; + case B_WINDOW_MOVED: + break; // avoid unhandled message spam + case B_WINDOW_RESIZED: + if (msg->FindInt32("width", &width) == B_OK && + msg->FindInt32("height", &height) == B_OK) { + event.type = CC_WIN_RESIZED; + // width/height is 1 less than actual width/height + event.v1.i32 = width + 1; + event.v2.i32 = height + 1; + } + break; + case B_QUIT_REQUESTED: + event.type = CC_WIN_QUIT; + Platform_LogConst("WINQUIT"); + break; + case _UPDATE_: + event.type = CC_WIN_REDRAW; + break; + default: + //Platform_LogConst("UNHANDLED WIN MESSAGE:"); + //msg->PrintToStream(); + break; + } + + if (event.type) Events_Push(&event); + if (msg->what == B_KEY_DOWN) ProcessKeyInput(msg); + BWindow::DispatchMessage(msg, handler); +} + + +static void AppThread(void) { + app_handle = new CC_BApp(); + // runs forever + app_handle->Run(); + // because there are multiple other threads relying + // on BApp connection, trying to delete the reference + // tends to break them and crash the game at exit + //delete app_handle; +} + +static void RunApp(void) { + void* thread; + Thread_Run(&thread, AppThread, 128 * 1024, "App thread"); + Thread_Detach(thread); + + // wait for BApplication to be started in other thread + do { + Thread_Sleep(10); + } while (!app_handle || app_handle->IsLaunching()); + + Platform_LogConst("App initialised"); +} + +void Window_PreInit(void) { } +void Window_Init(void) { + Events_Init(); + RunApp(); + Input.Sources = INPUT_SOURCE_NORMAL; + + BScreen screen(B_MAIN_SCREEN_ID); + BRect frame = screen.Frame(); + + // e.g. frame = (l:0.0, t:0.0, r:1023.0, b:767.0) + // so have to add 1 here for actual width/height + DisplayInfo.Width = frame.IntegerWidth() + 1; + DisplayInfo.Height = frame.IntegerHeight() + 1; + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; +} + +void Window_Free(void) { } + +static void DoCreateWindow(int width, int height) { + // https://www.haiku-os.org/docs/api/classBRect.html#details + // right/bottom coordinates are inclusive of the coordinates, + // so need to subtract 1 to end up with correct width/height + int x = Display_CentreX(width), y = Display_CentreY(height); + BRect frame(x, y, x + width - 1, y + height - 1); + win_handle = new CC_BWindow(frame); + + Window_Main.Exists = true; + Window_Main.Handle = win_handle; + + frame = win_handle->Bounds(); + Window_Main.Width = frame.IntegerWidth() + 1; + Window_Main.Height = frame.IntegerHeight() + 1; +} + +void Window_Create2D(int width, int height) { + DoCreateWindow(width, height); + view_handle = new BView(win_handle->Bounds(), "CC_LAUNCHER", + B_FOLLOW_ALL, 0); + win_handle->AddChild(view_handle); +} + +void Window_Create3D(int width, int height) { + DoCreateWindow(width, height); + view_3D = new BGLView(win_handle->Bounds(), "CC_GAME", + B_FOLLOW_ALL, B_FRAME_EVENTS, + BGL_RGB | BGL_ALPHA | BGL_DOUBLE | BGL_DEPTH); + view_handle = view_3D; + win_handle->AddChild(view_handle); +} + +void Window_SetTitle(const cc_string* title) { + char raw[NATIVE_STR_LEN]; + String_EncodeUtf8(raw, title); + + win_handle->Lock(); // TODO even need to lock/unlock? + win_handle->SetTitle(raw); + win_handle->Unlock(); +} + +void Clipboard_GetText(cc_string* value) { + if (!be_clipboard->Lock()) return; + + BMessage* clip = be_clipboard->Data(); + char* str = NULL; + ssize_t str_len = 0; + + clip->FindData("text/plain", B_MIME_TYPE, (const void**)&str, &str_len); + if (str) String_AppendUtf8(value, str, str_len); + + be_clipboard->Unlock(); +} + +void Clipboard_SetText(const cc_string* value) { + char str[NATIVE_STR_LEN]; + int str_len = String_EncodeUtf8(str, value); + + if (!be_clipboard->Lock()) return; + be_clipboard->Clear(); + + BMessage* clip = be_clipboard->Data(); + clip->AddData("text/plain", B_MIME_TYPE, str, str_len); + be_clipboard->Commit(); + + be_clipboard->Unlock(); +} + +static BRect win_rect; +static cc_bool win_fullscreen; + +int Window_GetWindowState(void) { + return win_fullscreen ? WINDOW_STATE_FULLSCREEN : WINDOW_STATE_NORMAL; +} + +cc_result Window_EnterFullscreen(void) { + // TODO is there a better fullscreen API to use + win_fullscreen = true; + win_rect = win_handle->Frame(); + + BScreen screen(B_MAIN_SCREEN_ID); + BRect screen_frame = screen.Frame(); + + win_handle->Lock(); + win_handle->MoveTo(screen_frame.left, screen_frame.top); + win_handle->ResizeTo(screen_frame.Width(), screen_frame.Height()); + win_handle->SetFlags(win_handle->Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); + //win_handle->SetLook(B_NO_BORDER_WINDOW_LOOK); // TODO unnecessary? + win_handle->Unlock(); + return 0; +} +cc_result Window_ExitFullscreen(void) { + win_fullscreen = false; + + win_handle->Lock(); + win_handle->MoveTo(win_rect.left, win_rect.top); + win_handle->ResizeTo(win_rect.Width(), win_rect.Height()); + win_handle->SetFlags(win_handle->Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); + //win_handle->SetLook(B_TITLED_WINDOW_LOOK); + win_handle->Unlock(); + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { + win_handle->Lock(); // TODO even need to lock/unlock ? + win_handle->Show(); + win_handle->Unlock(); +} + +void Window_SetSize(int width, int height) { + // See reason for -1 in DoCreateWindow + win_handle->Lock(); // TODO even need to lock/unlock ? + win_handle->ResizeTo(width - 1, height - 1); + win_handle->Unlock(); +} + +void Window_RequestClose(void) { + BMessage* msg = new BMessage(B_QUIT_REQUESTED); + app_handle->PostMessage(msg); +} + +static const cc_uint8 key_map[] = { + /* 0x00 */ 0,CCKEY_ESCAPE,CCKEY_F1,CCKEY_F2, CCKEY_F3,CCKEY_F4,CCKEY_F5,CCKEY_F6, + /* 0x08 */ CCKEY_F7,CCKEY_F8,CCKEY_F9,CCKEY_F10, CCKEY_F11,CCKEY_F12,CCKEY_PRINTSCREEN,CCKEY_SCROLLLOCK, + /* 0x10 */ CCKEY_PAUSE,CCKEY_TILDE,'1','2', '3','4','5','6', + /* 0x18 */ '7','8','9','0', CCKEY_MINUS,CCKEY_EQUALS,CCKEY_BACKSPACE,CCKEY_INSERT, + /* 0x20 */ CCKEY_HOME,CCKEY_PAGEUP,CCKEY_NUMLOCK,CCKEY_KP_DIVIDE, CCKEY_KP_MULTIPLY,CCKEY_KP_MINUS,CCKEY_TAB,'Q', + /* 0x28 */ 'W','E','R','T', 'Y','U','I','O', + /* 0x30 */ 'P',CCKEY_LBRACKET,CCKEY_RBRACKET,CCKEY_BACKSLASH, CCKEY_DELETE,CCKEY_END,CCKEY_PAGEDOWN,CCKEY_KP7, + /* 0x38 */ CCKEY_KP8,CCKEY_KP9,CCKEY_KP_PLUS,CCKEY_CAPSLOCK, 'A','S','D','F', + /* 0x40 */ 'G','H','J','K', 'L',CCKEY_SEMICOLON,CCKEY_QUOTE,CCKEY_ENTER, + /* 0x48 */ CCKEY_KP4,CCKEY_KP5,CCKEY_KP6,CCKEY_LSHIFT, 'Z','X','C','V', + /* 0x50 */ 'B','N','M',CCKEY_COMMA, CCKEY_PERIOD,CCKEY_SLASH,CCKEY_RSHIFT,CCKEY_UP, + /* 0x58 */ CCKEY_KP1,CCKEY_KP2,CCKEY_KP3,CCKEY_KP_ENTER, CCKEY_LCTRL,CCKEY_LALT,CCKEY_SPACE,CCKEY_RALT, + /* 0x60 */ CCKEY_RCTRL,CCKEY_LEFT,CCKEY_DOWN,CCKEY_RIGHT, CCKEY_KP0,CCKEY_KP_DECIMAL,CCKEY_LWIN,0, + /* 0x68 */ CCKEY_RWIN,0,0,0, 0,0,0,0, +}; + +static int MapNativeKey(int raw) { + int key = raw >= 0 && raw < Array_Elems(key_map) ? key_map[raw] : 0; + if (!key) Platform_Log2("Unknown key: %i (%h)", &raw, &raw); + return key; +} + +void Window_ProcessEvents(float delta) { + CCEvent event; + int key; + + while (Events_Pull(&event)) + { + switch (event.type) + { + case CC_MOUSE_SCROLL: + Mouse_ScrollVWheel(event.v1.f32); + Mouse_ScrollHWheel(event.v2.f32); + break; + case CC_MOUSE_DOWN: + Input_SetPressed(event.v1.i32); + break; + case CC_MOUSE_UP: + Input_SetReleased(event.v1.i32); + break; + case CC_MOUSE_MOVE: + Pointer_SetPosition(0, event.v1.i32, event.v2.i32); + break; + case CC_KEY_DOWN: + key = MapNativeKey(event.v1.i32); + if (key) Input_SetPressed(key); + break; + case CC_KEY_UP: + key = MapNativeKey(event.v1.i32); + if (key) Input_SetReleased(key); + break; + case CC_KEY_INPUT: + Event_RaiseInt(&InputEvents.Press, event.v1.i32); + break; + case CC_WIN_RESIZED: + Window_Main.Width = event.v1.i32; + Window_Main.Height = event.v2.i32; + Event_RaiseVoid(&WindowEvents.Resized); + break; + case CC_WIN_FOCUS: + Window_Main.Focused = event.v1.i32; + Event_RaiseVoid(&WindowEvents.FocusChanged); + break; + case CC_WIN_REDRAW: + Event_RaiseVoid(&WindowEvents.RedrawNeeded); + break; + case CC_WIN_QUIT: + Window_Main.Exists = false; + Event_RaiseVoid(&WindowEvents.Closing); + break; + case CC_RAW_MOUSE: + if (Input.RawMode) Event_RaiseRawMove(&PointerEvents.RawMoved, event.v1.i32, event.v2.i32); + break; + } + } +} + +void Window_ProcessGamepads(float delta) { } + +static void Cursor_GetRawPos(int* x, int* y) { + BPoint where; + uint32 buttons; + + win_handle->Lock(); + view_handle->GetMouse(&where, &buttons, false); + win_handle->Unlock(); + + // TODO: Should checkQueue be true + *x = (int)where.x; + *y = (int)where.y; +} + +void Cursor_SetPosition(int x, int y) { + // https://discourse.libsdl.org/t/sdl-mouse-bug/597/11 + BRect frame = win_handle->Frame(); + set_mouse_position(frame.left + x, frame.top + y); +} + +static void Cursor_DoSetVisible(cc_bool visible) { + if (visible) { + app_handle->ShowCursor(); + } else { + app_handle->HideCursor(); + } +} + +static void ShowDialogCore(const char* title, const char* msg) { + BAlert* alert = new BAlert(title, msg, "OK"); + // doesn't show title by default + alert->SetLook(B_TITLED_WINDOW_LOOK); + alert->Go(); +} + +static BFilePanel* open_panel; +static BFilePanel* save_panel; +static FileDialogCallback file_callback; +static const char* const* file_filters; + +class CC_BRefFilter : public BRefFilter +{ +public: + CC_BRefFilter() : BRefFilter() { } + +#if defined CC_BUILD_BEOS + bool Filter(const entry_ref* ref, BNode* node, struct stat* st, const char* filetype) { +#else + bool Filter(const entry_ref* ref, BNode* node, stat_beos* st, const char* filetype) override { +#endif + BPath path(ref); + cc_string str; + int i; + + if (node->IsDirectory()) return true; + str = String_FromReadonly(path.Path()); + + for (i = 0; file_filters[i]; i++) + { + cc_string ext = String_FromReadonly(file_filters[i]); + if (String_CaselessEnds(&str, &ext)) return true; + } + return false; + } +}; + +static void CallOpenFileCallback(const char* rawPath) { + cc_string path; char pathBuffer[1024]; + String_InitArray(path, pathBuffer); + if (!file_callback) return; + + String_AppendUtf8(&path, rawPath, String_Length(rawPath)); + file_callback(&path); + file_callback = NULL; +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + if (!open_panel) { + open_panel = new BFilePanel(B_OPEN_PANEL); + open_panel->SetRefFilter(new CC_BRefFilter()); + // NOTE: the CC_BRefFilter is NOT owned by the BFilePanel, + // so this is technically a memory leak.. but meh + } + + file_callback = args->Callback; + file_filters = args->filters; + open_panel->Show(); + return 0; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + if (!save_panel) { + save_panel = new BFilePanel(B_SAVE_PANEL); + save_panel->SetRefFilter(new CC_BRefFilter()); + // NOTE: the CC_BRefFilter is NOT owned by the BFilePanel, + // so this is technically a memory leak.. but meh + } + + file_callback = args->Callback; + file_filters = args->filters; + save_panel->Show(); + return 0; +} + +static BBitmap* win_framebuffer; +void Window_AllocFramebuffer(struct Bitmap* bmp, int width, int height) { + // right/bottom coordinates are inclusive of the coordinates, + // so need to subtract 1 to end up with correct width/height + BRect bounds(0, 0, width - 1, height - 1); + + win_framebuffer = new BBitmap(bounds, B_RGB32); + bmp->scan0 = (BitmapCol*)win_framebuffer->Bits(); + bmp->width = width; + bmp->height = height; +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO rect should maybe subtract -1 too ???? + BRect rect(r.x, r.y, r.x + r.width, r.y + r.height); + win_handle->Lock(); + view_handle->DrawBitmap(win_framebuffer, rect, rect); + win_handle->Unlock(); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + delete win_framebuffer; +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { } + +void Window_EnableRawMouse(void) { + DefaultEnableRawMouse(); +} + +void Window_UpdateRawMouse(void) { + if (mouse_raw_delta) { // handled by events instead + CentreMousePosition(); + } else if (mouse_is_tablet) { + MoveRawUsingCursorDelta(); + Cursor_GetRawPos(&cursorPrevX, &cursorPrevY); + } else { + DefaultUpdateRawMouse(); + } +} + +void Window_DisableRawMouse(void) { + DefaultDisableRawMouse(); +} + + +/*########################################################################################################################* +*-----------------------------------------------------OpenGL context------------------------------------------------------* +*#########################################################################################################################*/ +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL +static cc_bool win_vsync; + +void GLContext_Create(void) { + view_3D->LockGL(); +} + +void GLContext_Update(void) { + // it's necessary to call UnlockGL then LockGL, otherwise resizing doesn't work + // (backbuffer rendering is performed to doesn't get resized) + // https://github.com/anholt/mesa/blob/01e511233b24872b08bff862ff692dfb5b22c1f4/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp#L120..L127 + // might be fixed in newer MESA though? + view_3D->UnlockGL(); + view_3D->LockGL(); +} + +cc_bool GLContext_TryRestore(void) { return true; } +void GLContext_Free(void) { + view_3D->UnlockGL(); +} + +void* GLContext_GetAddress(const char* function) { +#if defined CC_BUILD_BEOS + return NULL; +#else + return view_3D->GetGLProcAddress(function); +#endif +} + +cc_bool GLContext_SwapBuffers(void) { + view_3D->SwapBuffers(win_vsync); + return true; +} + +void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { + win_vsync = vsync; +} +void GLContext_GetApiInfo(cc_string* info) { } +#endif // (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !CC_BUILD_EGL + +#endif |