diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..82b56bcb --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,22 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "${workspaceFolder}/**", + "\\\\wsl.localhost\\Ubuntu\\usr\\ppc-amigaos\\SDK" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "windowsSdkVersion": "10.0.19041.0", + "compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30133\\bin\\Hostx64\\x64\\cl.exe", + "cStandard": "c17", + "cppStandard": "c++17", + "intelliSenseMode": "windows-msvc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..eb437ae1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "internal.h": "c", + "platform.h": "c", + "xutility": "c", + "gl.h": "c" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f5e538bf..c0c300e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,9 +37,10 @@ endif() cmake_dependent_option(GLFW_BUILD_WIN32 "Build support for Win32" ON "WIN32" OFF) cmake_dependent_option(GLFW_BUILD_COCOA "Build support for Cocoa" ON "APPLE" OFF) -cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE" OFF) +cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE;NOT AMIGAOS4" OFF) cmake_dependent_option(GLFW_BUILD_WAYLAND "Build support for Wayland" "${GLFW_USE_WAYLAND}" "UNIX;NOT APPLE" OFF) +cmake_dependent_option(GLFW_BUILD_OS4 "Build support for AmigaOS4" ON "AMIGAOS4" OFF) cmake_dependent_option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF "WIN32" OFF) @@ -83,6 +84,9 @@ endif() if (GLFW_BUILD_X11) message(STATUS "Including X11 support") endif() +if (GLFW_BUILD_OS4) + message(STATUS "Including AmigaOS4 support") +endif() #-------------------------------------------------------------------- # Apply Microsoft C runtime library option diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f0b8d5ec..6c1107e8 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1301,6 +1301,7 @@ extern "C" { #define GLFW_PLATFORM_WAYLAND 0x00060003 #define GLFW_PLATFORM_X11 0x00060004 #define GLFW_PLATFORM_NULL 0x00060005 +#define GLFW_PLATFORM_OS4 0x00060006 /*! @} */ #define GLFW_DONT_CARE -1 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16cb1749..806b5ab6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,11 @@ if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) endif() endif() +if (GLFW_BUILD_OS4) + target_compile_definitions(glfw PRIVATE _GLFW_OS4) + target_sources(glfw PRIVATE os4_init.c os4_window.c os4_monitor.c os4_context.c os4_joystick.c) +endif() + if (GLFW_BUILD_WAYLAND) include(CheckIncludeFiles) include(CheckFunctionExists) @@ -159,6 +164,11 @@ if (GLFW_BUILD_WIN32) list(APPEND glfw_PKG_LIBS "-lgdi32") endif() +if (GLFW_BUILD_OS4) + target_compile_options(glfw PRIVATE "-DGL4ES" "-gstabs") + target_link_libraries(glfw PRIVATE "-lGL4ES") +endif() + if (GLFW_BUILD_COCOA) target_link_libraries(glfw PRIVATE "-framework Cocoa" "-framework IOKit" diff --git a/src/os4_context.c b/src/os4_context.c new file mode 100644 index 00000000..c531204d --- /dev/null +++ b/src/os4_context.c @@ -0,0 +1,158 @@ +//======================================================================== +// GLFW 3.4 WGL - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2019 Camilla Löwy +// +// 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. +// +//======================================================================== +// Please use C89 style variable declarations in this file because VS 2010 +//======================================================================== + +#include "internal.h" + +#include + +#ifndef GL4ES +#include +#include +#define GETPROCADDRESS getProcAddressGL +#else +enum CreateContextTags { + OGLES2_CCT_MIN=(1UL<<31), + OGLES2_CCT_WINDOW, + OGLES2_CCT_MODEID, + OGLES2_CCT_DEPTH, + OGLES2_CCT_STENCIL, + OGLES2_CCT_VSYNC, + OGLES2_CCT_SINGLE_GET_ERROR_MODE, + OGLES2_CCT_GET_WIDTH, + OGLES2_CCT_GET_HEIGHT, + OGLES2_CCT_BITMAP, + OGLES2_CCT_SHADER_COMPAT_PATCH, + OGLES2_CCT_CONTEXT_FOR_MODEID, + OGLES2_CCT_RESIZE_VIEWPORT, + OGLES2_CCT_DEBUG_SHADER_LOG, +}; +typedef int GLint; +typedef int GLsizei; + +extern void aglMakeCurrent(void* context); +extern void aglSetParams2(struct TagItem * tags); +extern void aglDestroyContext(void* context); +extern void aglMakeCurrent(void* context); +extern void aglSwapBuffers(); +extern void glFinish(); +extern void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); +extern void *aglCreateContext2(ULONG * errcode, struct TagItem * tags); +extern void *gl4es_aglGetProcAddress(const char *name); +extern void gl4es_glXSwapInterval(int interval); +#define GETPROCADDRESS gl4es_aglGetProcAddress + +extern struct OGLES2IFace *IOGLES2; +#endif + +static void makeContextCurrentGL(_GLFWwindow* window) +{ + if (window) + { + aglMakeCurrent(window->context.gl.glContext); + + _glfwPlatformSetTls(&_glfw.contextSlot, window); + } +} + +static void destroyContextGL(_GLFWwindow* window) { + if (window->context.gl.glContext) { + printf("Destroying context %p for window handle %p\n", window->context.gl.glContext, window->os4.handle); + aglDestroyContext(window->context.gl.glContext); + } + window->context.gl.glContext = NULL; +} + +static void swapBuffersGL(_GLFWwindow* window) +{ + // First flush the render pipeline, so that everything gets drawn + glFinish(); + + // Swap the buffers (if any) + aglSwapBuffers(); +} + +static GLFWglproc getProcAddressGL(const char* procname) +{ + const GLFWglproc proc = (GLFWglproc) aglGetProcAddress(procname); + return proc; +} + +static int extensionSupportedGL(const char* extension) +{ + // TODO - Implement this + return GLFW_FALSE; +} + +static void swapIntervalGL(int interval) +{ + // TODO - Should we implement this? +} + +// Create the OpenGL or OpenGL ES context +// +GLFWbool _glfwCreateContextGL(_GLFWwindow* window, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) +{ + ULONG errCode; + + struct TagItem contextparams[] = + { + {OGLES2_CCT_WINDOW,(ULONG)window->os4.handle}, +/* + {OGLES2_CCT_DEPTH,_this->gl_config.depth_size}, + {OGLES2_CCT_STENCIL,_this->gl_config.stencil_size}, +*/ + {OGLES2_CCT_VSYNC,0}, + {TAG_DONE,0} + }; + + window->context.gl.glContext = (void *)aglCreateContext2(&errCode, contextparams); + + /* Set the context as current */ + if (window->context.gl.glContext) { + aglMakeCurrent(window->context.gl.glContext); + } + else { + IIntuition->CloseWindow(window->os4.handle); + window->os4.handle = NULL; + return GLFW_FALSE; + } + printf("Creating context %p for window handle %p\n", window->context.gl.glContext, window->os4.handle); + + window->context.makeCurrent = makeContextCurrentGL; + window->context.swapBuffers = swapBuffersGL; + window->context.swapInterval = swapIntervalGL; + window->context.extensionSupported = extensionSupportedGL; + window->context.getProcAddress = GETPROCADDRESS; + window->context.destroy = destroyContextGL; + + return GLFW_TRUE; +} + diff --git a/src/os4_init.c b/src/os4_init.c new file mode 100644 index 00000000..7023df43 --- /dev/null +++ b/src/os4_init.c @@ -0,0 +1,505 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2016 Google Inc. +// Copyright (c) 2016-2017 Camilla Löwy +// +// 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. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include "internal.h" + +#include +#include +#include + +extern struct Library *DOSBase; +extern struct DOSIFace *IDOS; + +struct GraphicsIFace *IGraphics = NULL; +struct Library *GfxBase = NULL; + +struct IntuitionIFace *IIntuition = NULL; +struct Library *IntuitionBase = NULL; + +struct KeymapIFace *IKeymap = NULL; +struct Library *KeymapBase = NULL; + +struct UtilityIFace *IUtility = NULL; +struct Library *UtilityBase = NULL; + +struct Library *AIN_Base = NULL; +struct AIN_IFace *IAIN = NULL; + +struct Device *TimerBase = NULL; +struct TimerIFace *ITimer = NULL; + +#ifndef GL4ES +struct Library *OGLES2Base = NULL; +struct OGLES2IFace *IOGLES2 = NULL; +#else +extern struct OGLES2IFace *IOGLES2; +#endif +//************************************************************************ +//**** OS4 internal functions **** +//************************************************************************ + +BOOL VARARGS68K showErrorRequester(const char *errMsgRaw, ...) +{ + va_list ap; + va_startlinear(ap, errMsgRaw); + ULONG *errMsgArgs = va_getlinearva(ap, ULONG *); + + Object *object = NULL; + if (IIntuition) + { + object = IIntuition->NewObject( + NULL, "requester.class", + REQ_Type, REQTYPE_INFO, + REQ_TitleText, "GLFW: FATAL ERROR", + REQ_BodyText, errMsgRaw, + REQ_VarArgs, errMsgArgs, + REQ_Image, REQIMAGE_ERROR, + REQ_GadgetText, "_Ok", + TAG_DONE); + } + if (object) + { + IIntuition->IDoMethod(object, RM_OPENREQ, NULL, NULL, NULL, TAG_DONE); + IIntuition->DisposeObject(object); + + return TRUE; + } + else + { + return FALSE; + } +} + +static struct Library *openLib(const char *libName, unsigned int minVers, struct Interface **iFacePtr) +{ + struct Library *libBase = IExec->OpenLibrary(libName, minVers); + if (libBase) + { + struct Interface *iFace = IExec->GetInterface(libBase, "main", 1, NULL); + if (!iFace) + { + // Failed + //CloseLibrary(libBase); + libBase = NULL; // Lets the code below know we've failed + } + + if (iFacePtr) + { + // Write the interface pointer + *iFacePtr = iFace; + } + } + else + { + // Opening the library failed. Show the error requester + const char errMsgRaw[] = "Couldn't open %s version %u+.\n"; + if (!showErrorRequester(errMsgRaw, libName, minVers)) + { + // Use printf() as a backup + printf(errMsgRaw, libName, minVers); + } + } + + return libBase; +} + +static int loadLibraries(void) +{ + // graphics.library + DOSBase = openLib("dos.library", 52, (struct Interface **)&IDOS); + if (!DOSBase) + { + return 0; + } + + // graphics.library + GfxBase = openLib("graphics.library", 52, (struct Interface **)&IGraphics); + if (!GfxBase) + { + return 0; + } + + // intuition.library + IntuitionBase = openLib("intuition.library", 52, (struct Interface **)&IIntuition); + if (!IntuitionBase) + { + return 0; + } + + // keymap.library + KeymapBase = openLib("keymap.library", 52, (struct Interface **)&IKeymap); + if (!KeymapBase) + { + return 0; + } + + // Utility.library + UtilityBase = openLib("utility.library", 52, (struct Interface **)&IUtility); + if (!UtilityBase) + { + return 0; + } + +#ifndef GL4ES + OGLES2Base = openLib("ogles2.library", MIN_OGLES2_VERSION, (struct Interface **)&IOGLES2); + if (!OGLES2Base) + { + return 0; + } +#endif + + AIN_Base = openLib("AmigaInput.library", 51, (struct Interface **)&IAIN); + if (!AIN_Base) + { + return 0; + } + + return 1; +} + +static void closeLibraries(void) +{ + printf("close libraries\n"); + if (IAIN) + { + IExec->DropInterface((struct Interface *)IAIN); + } + if (AIN_Base) + { + IExec->CloseLibrary(AIN_Base); + } + +#ifndef GL4ES + if (IOGLES2) + { + IExec->DropInterface((struct Interface *)IOGLES2); + } + if (OGLES2Base) + { + IExec->CloseLibrary(OGLES2Base); + } +#endif + + // Close graphics.library + if (IGraphics) + { + IExec->DropInterface((struct Interface *)IGraphics); + IGraphics = NULL; + } + if (GfxBase) + { + IExec->CloseLibrary((struct Library *)GfxBase); + GfxBase = NULL; + } + + // Close intuition.library + if (IIntuition) + { + IExec->DropInterface((struct Interface *)IIntuition); + IIntuition = NULL; + } + if (IntuitionBase) + { + IExec->CloseLibrary((struct Library *)IntuitionBase); + IntuitionBase = NULL; + } + + // Close keymap.library + if (IKeymap) + { + IExec->DropInterface((struct Interface *)IKeymap); + IKeymap = NULL; + } + if (KeymapBase) + { + IExec->CloseLibrary(KeymapBase); + KeymapBase = NULL; + } + + // Close utility.library + if (IUtility) + { + IExec->DropInterface((struct Interface *)IUtility); + IUtility = NULL; + } + if (UtilityBase) + { + IExec->CloseLibrary((struct Library *)UtilityBase); + UtilityBase = NULL; + } +} + +static void createKeyTables(void) +{ + memset(_glfw.os4.keycodes, -1, sizeof(_glfw.os4.keycodes)); + memset(_glfw.os4.scancodes, -1, sizeof(_glfw.os4.scancodes)); + + _glfw.os4.keycodes[0xb] = GLFW_KEY_GRAVE_ACCENT; + _glfw.os4.keycodes[0x1] = GLFW_KEY_1; + _glfw.os4.keycodes[0x2] = GLFW_KEY_2; + _glfw.os4.keycodes[0x3] = GLFW_KEY_3; + _glfw.os4.keycodes[0x4] = GLFW_KEY_4; + _glfw.os4.keycodes[0x5] = GLFW_KEY_5; + _glfw.os4.keycodes[0x6] = GLFW_KEY_6; + _glfw.os4.keycodes[0x7] = GLFW_KEY_7; + _glfw.os4.keycodes[0x8] = GLFW_KEY_8; + _glfw.os4.keycodes[0x9] = GLFW_KEY_9; + _glfw.os4.keycodes[0xa] = GLFW_KEY_0; + _glfw.os4.keycodes[0x40] = GLFW_KEY_SPACE; // + _glfw.os4.keycodes[0x3a] = GLFW_KEY_MINUS; + _glfw.os4.keycodes[0xc] = GLFW_KEY_EQUAL; + _glfw.os4.keycodes[0x10] = GLFW_KEY_Q; + _glfw.os4.keycodes[0x11] = GLFW_KEY_W; + _glfw.os4.keycodes[0x12] = GLFW_KEY_E; + _glfw.os4.keycodes[0x13] = GLFW_KEY_R; + _glfw.os4.keycodes[0x14] = GLFW_KEY_T; + _glfw.os4.keycodes[0x15] = GLFW_KEY_Y; + _glfw.os4.keycodes[0x16] = GLFW_KEY_U; + _glfw.os4.keycodes[0x17] = GLFW_KEY_I; + _glfw.os4.keycodes[0x18] = GLFW_KEY_O; + _glfw.os4.keycodes[0x19] = GLFW_KEY_P; + _glfw.os4.keycodes[0x1a] = GLFW_KEY_LEFT_BRACKET; + _glfw.os4.keycodes[0x1b] = GLFW_KEY_RIGHT_BRACKET; + _glfw.os4.keycodes[0x20] = GLFW_KEY_A; + _glfw.os4.keycodes[0x21] = GLFW_KEY_S; + _glfw.os4.keycodes[0x22] = GLFW_KEY_D; + _glfw.os4.keycodes[0x23] = GLFW_KEY_F; + _glfw.os4.keycodes[0x24] = GLFW_KEY_G; + _glfw.os4.keycodes[0x25] = GLFW_KEY_H; + _glfw.os4.keycodes[0x26] = GLFW_KEY_J; + _glfw.os4.keycodes[0x27] = GLFW_KEY_K; + _glfw.os4.keycodes[0x28] = GLFW_KEY_L; + //_glfw.os4.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON; + //_glfw.os4.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE; + _glfw.os4.keycodes[0x31] = GLFW_KEY_Z; + _glfw.os4.keycodes[0x32] = GLFW_KEY_X; + _glfw.os4.keycodes[0x33] = GLFW_KEY_C; + _glfw.os4.keycodes[0x34] = GLFW_KEY_V; + _glfw.os4.keycodes[0x35] = GLFW_KEY_B; + _glfw.os4.keycodes[0x36] = GLFW_KEY_N; + _glfw.os4.keycodes[0x37] = GLFW_KEY_M; + _glfw.os4.keycodes[0x38] = GLFW_KEY_COMMA; + _glfw.os4.keycodes[0x39] = GLFW_KEY_PERIOD; + _glfw.os4.keycodes[0x3a] = GLFW_KEY_SLASH; + _glfw.os4.keycodes[0x0] = GLFW_KEY_BACKSLASH; + _glfw.os4.keycodes[RAWKEY_ESC] = GLFW_KEY_ESCAPE; // + _glfw.os4.keycodes[RAWKEY_TAB] = GLFW_KEY_TAB; // + _glfw.os4.keycodes[RAWKEY_LSHIFT] = GLFW_KEY_LEFT_SHIFT; // + _glfw.os4.keycodes[RAWKEY_RSHIFT] = GLFW_KEY_RIGHT_SHIFT; // + _glfw.os4.keycodes[RAWKEY_LCTRL] = GLFW_KEY_LEFT_CONTROL; // + _glfw.os4.keycodes[RAWKEY_LCTRL] = GLFW_KEY_RIGHT_CONTROL; + _glfw.os4.keycodes[RAWKEY_LALT] = GLFW_KEY_LEFT_ALT; // + _glfw.os4.keycodes[RAWKEY_RALT] = GLFW_KEY_RIGHT_ALT; // + _glfw.os4.keycodes[RAWKEY_LCOMMAND] = GLFW_KEY_LEFT_SUPER; // + _glfw.os4.keycodes[RAWKEY_RCOMMAND] = GLFW_KEY_RIGHT_SUPER; + _glfw.os4.keycodes[RAWKEY_MENU] = GLFW_KEY_MENU; // + //_glfw.os4.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; + _glfw.os4.keycodes[RAWKEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; // + _glfw.os4.keycodes[RAWKEY_BREAK] = GLFW_KEY_PRINT_SCREEN; + _glfw.os4.keycodes[0x5f] = GLFW_KEY_SCROLL_LOCK; + _glfw.os4.keycodes[RAWKEY_BREAK] = GLFW_KEY_PAUSE; + _glfw.os4.keycodes[RAWKEY_DEL] = GLFW_KEY_DELETE; // + _glfw.os4.keycodes[RAWKEY_BACKSPACE] = GLFW_KEY_BACKSPACE; // + _glfw.os4.keycodes[RAWKEY_RETURN] = GLFW_KEY_ENTER; // + _glfw.os4.keycodes[RAWKEY_HOME] = GLFW_KEY_HOME; // + _glfw.os4.keycodes[RAWKEY_END] = GLFW_KEY_END; // + _glfw.os4.keycodes[RAWKEY_PAGEUP] = GLFW_KEY_PAGE_UP; // + _glfw.os4.keycodes[RAWKEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN; // + _glfw.os4.keycodes[RAWKEY_INSERT] = GLFW_KEY_INSERT; // + _glfw.os4.keycodes[RAWKEY_CRSRLEFT] = GLFW_KEY_LEFT; + _glfw.os4.keycodes[RAWKEY_CRSRRIGHT] = GLFW_KEY_RIGHT; // + _glfw.os4.keycodes[RAWKEY_CRSRDOWN] = GLFW_KEY_DOWN; // + _glfw.os4.keycodes[RAWKEY_CRSRUP] = GLFW_KEY_UP; // + _glfw.os4.keycodes[RAWKEY_F1] = GLFW_KEY_F1; // + _glfw.os4.keycodes[RAWKEY_F2] = GLFW_KEY_F2; // + _glfw.os4.keycodes[RAWKEY_F3] = GLFW_KEY_F3; // + _glfw.os4.keycodes[RAWKEY_F4] = GLFW_KEY_F4; // + _glfw.os4.keycodes[RAWKEY_F5] = GLFW_KEY_F5; // + _glfw.os4.keycodes[RAWKEY_F6] = GLFW_KEY_F6; // + _glfw.os4.keycodes[RAWKEY_F7] = GLFW_KEY_F7; // + _glfw.os4.keycodes[RAWKEY_F8] = GLFW_KEY_F8; // + _glfw.os4.keycodes[RAWKEY_F9] = GLFW_KEY_F9; // + _glfw.os4.keycodes[RAWKEY_F10] = GLFW_KEY_F10; // + _glfw.os4.keycodes[RAWKEY_F11] = GLFW_KEY_F11; // + _glfw.os4.keycodes[RAWKEY_F12] = GLFW_KEY_F12; // + _glfw.os4.keycodes[RAWKEY_F13] = GLFW_KEY_F13; // + _glfw.os4.keycodes[RAWKEY_F14] = GLFW_KEY_F14; // + _glfw.os4.keycodes[RAWKEY_F15] = GLFW_KEY_F15; // + _glfw.os4.keycodes[RAWKEY_HELP] = GLFW_KEY_F16; // Mapped amiga HELP key with F16 + _glfw.os4.keycodes[0x5c] = GLFW_KEY_KP_DIVIDE; + _glfw.os4.keycodes[0x5d] = GLFW_KEY_KP_MULTIPLY; + _glfw.os4.keycodes[0x4a] = GLFW_KEY_KP_SUBTRACT; + _glfw.os4.keycodes[0x5e] = GLFW_KEY_KP_ADD; + _glfw.os4.keycodes[0xf] = GLFW_KEY_KP_0; + _glfw.os4.keycodes[0x1d] = GLFW_KEY_KP_1; + _glfw.os4.keycodes[0x1e] = GLFW_KEY_KP_2; + _glfw.os4.keycodes[0x1f] = GLFW_KEY_KP_3; + _glfw.os4.keycodes[0x2d] = GLFW_KEY_KP_4; + _glfw.os4.keycodes[0x2e] = GLFW_KEY_KP_5; + _glfw.os4.keycodes[0x2f] = GLFW_KEY_KP_6; + _glfw.os4.keycodes[0x3d] = GLFW_KEY_KP_7; + _glfw.os4.keycodes[0x3e] = GLFW_KEY_KP_8; + _glfw.os4.keycodes[0x3f] = GLFW_KEY_KP_9; + _glfw.os4.keycodes[0x3c] = GLFW_KEY_KP_DECIMAL; + /* + _glfw.os4.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; + */ + _glfw.os4.keycodes[RAWKEY_ENTER] = GLFW_KEY_KP_ENTER; // + + for (int scancode = 0; scancode < 256; scancode++) + { + if (_glfw.os4.keycodes[scancode] > 0) + _glfw.os4.scancodes[_glfw.os4.keycodes[scancode]] = scancode; + } +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwConnectOS4(int platformID, _GLFWplatform *platform) +{ + const _GLFWplatform os4 = + { + GLFW_PLATFORM_OS4, + _glfwInitOS4, + _glfwTerminateOS4, + _glfwGetCursorPosOS4, + _glfwSetCursorPosOS4, + _glfwSetCursorModeOS4, + _glfwSetRawMouseMotionOS4, + _glfwRawMouseMotionSupportedOS4, + _glfwCreateCursorOS4, + _glfwCreateStandardCursorOS4, + _glfwDestroyCursorOS4, + _glfwSetCursorOS4, + _glfwGetScancodeNameOS4, + _glfwGetKeyScancodeOS4, + _glfwSetClipboardStringOS4, + _glfwGetClipboardStringOS4, + _glfwInitJoysticksOS4, + _glfwTerminateJoysticksOS4, + _glfwPollJoystickOS4, + _glfwGetMappingNameOS4, + _glfwUpdateGamepadGUIDOS4, + _glfwFreeMonitorOS4, + _glfwGetMonitorPosOS4, + _glfwGetMonitorContentScaleOS4, + _glfwGetMonitorWorkareaOS4, + _glfwGetVideoModesOS4, + _glfwGetVideoModeOS4, + _glfwGetGammaRampOS4, + _glfwSetGammaRampOS4, + _glfwCreateWindowOS4, + _glfwDestroyWindowOS4, + _glfwSetWindowTitleOS4, + _glfwSetWindowIconOS4, + _glfwGetWindowPosOS4, + _glfwSetWindowPosOS4, + _glfwGetWindowSizeOS4, + _glfwSetWindowSizeOS4, + _glfwSetWindowSizeLimitsOS4, + _glfwSetWindowAspectRatioOS4, + _glfwGetFramebufferSizeOS4, + _glfwGetWindowFrameSizeOS4, + _glfwGetWindowContentScaleOS4, + _glfwIconifyWindowOS4, + _glfwRestoreWindowOS4, + _glfwMaximizeWindowOS4, + _glfwShowWindowOS4, + _glfwHideWindowOS4, + _glfwRequestWindowAttentionOS4, + _glfwFocusWindowOS4, + _glfwSetWindowMonitorOS4, + _glfwWindowFocusedOS4, + _glfwWindowIconifiedOS4, + _glfwWindowVisibleOS4, + _glfwWindowMaximizedOS4, + _glfwWindowHoveredOS4, + _glfwFramebufferTransparentOS4, + _glfwGetWindowOpacityOS4, + _glfwSetWindowResizableOS4, + _glfwSetWindowDecoratedOS4, + _glfwSetWindowFloatingOS4, + _glfwSetWindowOpacityOS4, + _glfwSetWindowMousePassthroughOS4, + _glfwPollEventsOS4, + _glfwWaitEventsOS4, + _glfwWaitEventsTimeoutOS4, + _glfwPostEmptyEventOS4, + _glfwGetRequiredInstanceExtensionsOS4, + _glfwGetPhysicalDevicePresentationSupportOS4, + _glfwCreateWindowSurfaceOS4, + }; + + *platform = os4; + return GLFW_TRUE; +} + +int _glfwInitOS4(void) +{ + loadLibraries(); + createKeyTables(); + _glfwPollMonitorsOS4(); + + if (!(_glfw.os4.userPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE))) { + return GLFW_FALSE; + } + + if (!(_glfw.os4.appMsgPort = IExec->AllocSysObjectTags(ASOT_PORT, TAG_DONE))) { + return GLFW_FALSE; + } + + return GLFW_TRUE; +} + +void _glfwTerminateOS4(void) +{ + if (_glfw.os4.appMsgPort) { + struct Message *msg; + + while ((msg = IExec->GetMsg(_glfw.os4.appMsgPort))) { + IExec->ReplyMsg((struct Message *) msg); + } + IExec->FreeSysObject(ASOT_PORT, _glfw.os4.appMsgPort); + } + + if (_glfw.os4.userPort) { + struct Message *msg; + + while ((msg = IExec->GetMsg(_glfw.os4.userPort))) { + IExec->ReplyMsg((struct Message *) msg); + } + IExec->FreeSysObject(ASOT_PORT, _glfw.os4.userPort); + } + + free(_glfw.os4.clipboardString); + //_glfwTerminateOSMesa(); + closeLibraries(); +} diff --git a/src/os4_joystick.c b/src/os4_joystick.c new file mode 100644 index 00000000..188b9b2f --- /dev/null +++ b/src/os4_joystick.c @@ -0,0 +1,58 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2016-2017 Camilla Löwy +// +// 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. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include "internal.h" + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwInitJoysticksOS4(void) +{ + return GLFW_TRUE; +} + +void _glfwTerminateJoysticksOS4(void) +{ +} + +int _glfwPollJoystickOS4(_GLFWjoystick* js, int mode) +{ + return GLFW_FALSE; +} + +const char* _glfwGetMappingNameOS4(void) +{ + return ""; +} + +void _glfwUpdateGamepadGUIDOS4(char* guid) +{ +} + diff --git a/src/os4_monitor.c b/src/os4_monitor.c new file mode 100644 index 00000000..eb9a1a21 --- /dev/null +++ b/src/os4_monitor.c @@ -0,0 +1,166 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2016 Google Inc. +// Copyright (c) 2016-2019 Camilla Löwy +// +// 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. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include "internal.h" + +#include +#include +#include + +// The the sole (fake) video mode of our (sole) fake monitor +// +static GLFWvidmode getVideoMode(void) +{ + struct Screen* currentScreen = IIntuition->LockPubScreen(NULL); + + GLFWvidmode mode; + mode.width = currentScreen->Width; + mode.height = currentScreen->Height; + // TODO - Change this + mode.redBits = 8; + mode.greenBits = 8; + mode.blueBits = 8; + mode.refreshRate = 60; + + IIntuition->UnlockPubScreen(NULL, currentScreen); + return mode; +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +void _glfwPollMonitorsOS4(void) +{ + const float dpi = 141.f; + const GLFWvidmode mode = getVideoMode(); + _GLFWmonitor* monitor = _glfwAllocMonitor("OS4 Monitor 0", + (int) (mode.width * 25.4f / dpi), + (int) (mode.height * 25.4f / dpi)); + _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST); +} + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +void _glfwFreeMonitorOS4(_GLFWmonitor* monitor) +{ + _glfwFreeGammaArrays(&monitor->os4.ramp); +} + +void _glfwGetMonitorPosOS4(_GLFWmonitor* monitor, int* xpos, int* ypos) +{ + if (xpos) + *xpos = 0; + if (ypos) + *ypos = 0; +} + +void _glfwGetMonitorContentScaleOS4(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + +void _glfwGetMonitorWorkareaOS4(_GLFWmonitor* monitor, + int* xpos, int* ypos, + int* width, int* height) +{ + const GLFWvidmode mode = getVideoMode(); + + if (xpos) + *xpos = 0; + if (ypos) + *ypos = 10; + if (width) + *width = mode.width; + if (height) + *height = mode.height - 10; +} + +GLFWvidmode* _glfwGetVideoModesOS4(_GLFWmonitor* monitor, int* found) +{ + GLFWvidmode* mode = _glfw_calloc(1, sizeof(GLFWvidmode)); + *mode = getVideoMode(); + *found = 1; + return mode; +} + +void _glfwGetVideoModeOS4(_GLFWmonitor* monitor, GLFWvidmode* mode) +{ + *mode = getVideoMode(); +} + +GLFWbool _glfwGetGammaRampOS4(_GLFWmonitor* monitor, GLFWgammaramp* ramp) +{ + if (!monitor->os4.ramp.size) + { + unsigned int i; + + _glfwAllocGammaArrays(&monitor->os4.ramp, 256); + + for (i = 0; i < monitor->os4.ramp.size; i++) + { + const float gamma = 2.2f; + float value; + value = i / (float) (monitor->os4.ramp.size - 1); + value = powf(value, 1.f / gamma) * 65535.f + 0.5f; + value = _glfw_fminf(value, 65535.f); + + monitor->os4.ramp.red[i] = (unsigned short) value; + monitor->os4.ramp.green[i] = (unsigned short) value; + monitor->os4.ramp.blue[i] = (unsigned short) value; + } + } + + _glfwAllocGammaArrays(ramp, monitor->os4.ramp.size); + memcpy(ramp->red, monitor->os4.ramp.red, sizeof(short) * ramp->size); + memcpy(ramp->green, monitor->os4.ramp.green, sizeof(short) * ramp->size); + memcpy(ramp->blue, monitor->os4.ramp.blue, sizeof(short) * ramp->size); + return GLFW_TRUE; +} + +void _glfwSetGammaRampOS4(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +{ + if (monitor->os4.ramp.size != ramp->size) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "OS4: Gamma ramp size must match current ramp size"); + return; + } + + memcpy(monitor->os4.ramp.red, ramp->red, sizeof(short) * ramp->size); + memcpy(monitor->os4.ramp.green, ramp->green, sizeof(short) * ramp->size); + memcpy(monitor->os4.ramp.blue, ramp->blue, sizeof(short) * ramp->size); +} + diff --git a/src/os4_platform.h b/src/os4_platform.h new file mode 100644 index 00000000..be0a1ffc --- /dev/null +++ b/src/os4_platform.h @@ -0,0 +1,236 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2016 Google Inc. +// Copyright (c) 2016-2017 Camilla Löwy +// +// 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. +// +//======================================================================== + +#pragma once + +// Include files +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* GL Stuff */ +#ifndef GL4ES +#include +#include +#endif + +#define MIN_MINIGLVERSION 2 +#define MIN_OGLES2_VERSION 0 + +#define GLFW_OS4_WINDOW_STATE _GLFWwindowOS4 os4; +#define GLFW_OS4_LIBRARY_WINDOW_STATE _GLFWlibraryOS4 os4; +#define GLFW_OS4_MONITOR_STATE _GLFWmonitorOS4 os4; +#define GLFW_OS4_CONTEXT_STATE _GLFWcontextGL gl; + +#define GLFW_OS4_CURSOR_STATE _GLFWcursorOS4 os4; +#define GLFW_OS4_LIBRARY_CONTEXT_STATE + +struct MyIntuiMessage +{ + uint32 Class; + uint16 Code; + uint16 Qualifier; + + struct Gadget *Gadget; + struct Window *IDCMPWindow; + + int16 RelativeMouseX; + int16 RelativeMouseY; + + int16 WindowMouseX; // Absolute pointer position, relative to + int16 WindowMouseY; // top-left corner of inner window + + int16 ScreenMouseX; + int16 ScreenMouseY; + + int16 Width; // Inner window dimensions + int16 Height; +}; + +// OS4-specific per-window data +// +typedef struct _GLFWwindowOS4 +{ + struct Window *handle; + int xpos; + int ypos; + int lastCursorPosX; + int lastCursorPosY; + int width; + int height; + char *title; + GLFWbool visible; + GLFWbool iconified; + GLFWbool maximized; + GLFWbool resizable; + GLFWbool decorated; + GLFWbool floating; + GLFWbool transparent; + float opacity; + int windowType; // NORMAL - GL - GLES + +} _GLFWwindowOS4; + +typedef struct _GLFWcontextGL { + struct BitMap *bm; + void* glContext; +} _GLFWcontextGL; + +// OS4-specific per-monitor data +// +typedef struct _GLFWmonitorOS4 +{ + GLFWgammaramp ramp; +} _GLFWmonitorOS4; + +// X11-specific per-cursor data +// +typedef struct _GLFWcursorX11 +{ + Object *handle; + uint32_t *imageData; +} _GLFWcursorOS4; + +// OS4-specific global data +// +typedef struct _GLFWlibraryOS4 +{ + int xcursor; + int ycursor; + + char keynames[GLFW_KEY_LAST + 1][17]; + short int keycodes[256]; + short int scancodes[GLFW_KEY_LAST + 1]; + + char *clipboardString; + struct MsgPort *appMsgPort; + struct MsgPort *userPort; + + _GLFWwindow *focusedWindow; +} _GLFWlibraryOS4; + +void _glfwPollMonitorsOS4(void); + +GLFWbool _glfwConnectOS4(int platformID, _GLFWplatform* platform); +int _glfwInitOS4(void); +void _glfwTerminateOS4(void); + +void _glfwFreeMonitorOS4(_GLFWmonitor* monitor); +void _glfwGetMonitorPosOS4(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwGetMonitorContentScaleOS4(_GLFWmonitor* monitor, float* xscale, float* yscale); +void _glfwGetMonitorWorkareaOS4(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); +GLFWvidmode* _glfwGetVideoModesOS4(_GLFWmonitor* monitor, int* found); +void _glfwGetVideoModeOS4(_GLFWmonitor* monitor, GLFWvidmode* mode); +GLFWbool _glfwGetGammaRampOS4(_GLFWmonitor* monitor, GLFWgammaramp* ramp); +void _glfwSetGammaRampOS4(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +int _glfwCreateWindowOS4(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); +void _glfwDestroyWindowOS4(_GLFWwindow* window); +void _glfwSetWindowTitleOS4(_GLFWwindow* window, const char* title); +void _glfwSetWindowIconOS4(_GLFWwindow* window, int count, const GLFWimage* images); +void _glfwSetWindowMonitorOS4(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); +void _glfwGetWindowPosOS4(_GLFWwindow* window, int* xpos, int* ypos); +void _glfwSetWindowPosOS4(_GLFWwindow* window, int xpos, int ypos); +void _glfwGetWindowSizeOS4(_GLFWwindow* window, int* width, int* height); +void _glfwSetWindowSizeOS4(_GLFWwindow* window, int width, int height); +void _glfwSetWindowSizeLimitsOS4(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); +void _glfwSetWindowAspectRatioOS4(_GLFWwindow* window, int n, int d); +void _glfwGetFramebufferSizeOS4(_GLFWwindow* window, int* width, int* height); +void _glfwGetWindowFrameSizeOS4(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwGetWindowContentScaleOS4(_GLFWwindow* window, float* xscale, float* yscale); +void _glfwIconifyWindowOS4(_GLFWwindow* window); +void _glfwRestoreWindowOS4(_GLFWwindow* window); +void _glfwMaximizeWindowOS4(_GLFWwindow* window); +int _glfwWindowMaximizedOS4(_GLFWwindow* window); +int _glfwWindowHoveredOS4(_GLFWwindow* window); +int _glfwFramebufferTransparentOS4(_GLFWwindow* window); +void _glfwSetWindowResizableOS4(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowDecoratedOS4(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowFloatingOS4(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowMousePassthroughOS4(_GLFWwindow* window, GLFWbool enabled); +float _glfwGetWindowOpacityOS4(_GLFWwindow* window); +void _glfwSetWindowOpacityOS4(_GLFWwindow* window, float opacity); +void _glfwSetRawMouseMotionOS4(_GLFWwindow *window, GLFWbool enabled); +GLFWbool _glfwRawMouseMotionSupportedOS4(void); +void _glfwShowWindowOS4(_GLFWwindow* window); +void _glfwRequestWindowAttentionOS4(_GLFWwindow* window); +void _glfwRequestWindowAttentionOS4(_GLFWwindow* window); +void _glfwHideWindowOS4(_GLFWwindow* window); +void _glfwFocusWindowOS4(_GLFWwindow* window); +int _glfwWindowFocusedOS4(_GLFWwindow* window); +int _glfwWindowIconifiedOS4(_GLFWwindow* window); +int _glfwWindowVisibleOS4(_GLFWwindow* window); +void _glfwPollEventsOS4(void); +void _glfwWaitEventsOS4(void); +void _glfwWaitEventsTimeoutOS4(double timeout); +void _glfwPostEmptyEventOS4(void); +void _glfwGetCursorPosOS4(_GLFWwindow* window, double* xpos, double* ypos); +void _glfwSetCursorPosOS4(_GLFWwindow* window, double x, double y); +void _glfwSetCursorModeOS4(_GLFWwindow* window, int mode); +int _glfwCreateCursorOS4(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot); +int _glfwCreateStandardCursorOS4(_GLFWcursor* cursor, int shape); +void _glfwDestroyCursorOS4(_GLFWcursor* cursor); +void _glfwSetCursorOS4(_GLFWwindow* window, _GLFWcursor* cursor); +void _glfwSetClipboardStringOS4(const char* string); +const char* _glfwGetClipboardStringOS4(void); +const char* _glfwGetScancodeNameOS4(int scancode); +int _glfwGetKeyScancodeOS4(int key); + +GLFWbool _glfwInitJoysticksOS4(void); +void _glfwTerminateJoysticksOS4(void); +int _glfwPollJoystickOS4(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameOS4(void); +void _glfwUpdateGamepadGUIDOS4(char* guid); + +void _glfwGetRequiredInstanceExtensionsOS4(char** extensions); +int _glfwGetPhysicalDevicePresentationSupportOS4(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceOS4(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +void _glfwPollMonitorsOS4(void); + diff --git a/src/os4_window.c b/src/os4_window.c new file mode 100644 index 00000000..0b89b545 --- /dev/null +++ b/src/os4_window.c @@ -0,0 +1,1026 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2016 Google Inc. +// Copyright (c) 2016-2019 Camilla Löwy +// +// 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. +// +//======================================================================== +// It is fine to use C99 in this file because it will not be built with VS +//======================================================================== + +#include "internal.h" + +#include +#include +#include + +#include +#include + +#define MIN_WINDOW_SIZE 100 + +static void OS4_CopyIdcmpMessage(struct IntuiMessage * src, struct MyIntuiMessage * dst); +static _GLFWwindow *OS4_FindWindow(struct Window * syswin); +static uint32_t*OS4_CopyImageData(const GLFWimage *surface); +static int OS4_GetButtonState(uint16_t code); +static int OS4_GetButton(uint16_t code); +static char OS4_TranslateUnicode(uint16_t code, uint32_t qualifier); +static int OS4_TranslateState(int state); + +static UWORD fallbackPointerData[2 * 16] = { 0 }; + +static struct BitMap fallbackPointerBitMap = { 2, 16, 0, 2, 0, + { (PLANEPTR)fallbackPointerData, (PLANEPTR)(fallbackPointerData + 16) } }; + +static void applySizeLimits(_GLFWwindow* window, int* width, int* height) +{ + if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) + { + const float ratio = (float) window->numer / (float) window->denom; + *height = (int) (*width / ratio); + } + + if (window->minwidth != GLFW_DONT_CARE && *width < window->minwidth) + *width = window->minwidth; + else if (window->maxwidth != GLFW_DONT_CARE && *width > window->maxwidth) + *width = window->maxwidth; + + if (window->minheight != GLFW_DONT_CARE && *height < window->minheight) + *height = window->minheight; + else if (window->maxheight != GLFW_DONT_CARE && *height > window->maxheight) + *height = window->maxheight; +} + +static void fitToMonitor(_GLFWwindow* window) +{ + GLFWvidmode mode; + _glfwGetVideoModeOS4(window->monitor, &mode); + _glfwGetMonitorPosOS4(window->monitor, + &window->os4.xpos, + &window->os4.ypos); + window->os4.width = mode.width; + window->os4.height = mode.height; +} + +static void acquireMonitor(_GLFWwindow* window) +{ + _glfwInputMonitorWindow(window->monitor, window); +} + +static void releaseMonitor(_GLFWwindow* window) +{ + if (window->monitor->window != window) + return; + + _glfwInputMonitorWindow(window->monitor, NULL); +} + +static int createNativeWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig, + int windowType) +{ + if (window->monitor) + fitToMonitor(window); + else + { + window->os4.xpos = 17; + window->os4.ypos = 17; + window->os4.width = wndconfig->width; + window->os4.height = wndconfig->height; + } + + window->os4.visible = wndconfig->visible; + window->os4.decorated = wndconfig->decorated; + window->os4.maximized = wndconfig->maximized; + window->os4.floating = wndconfig->floating; + if (fbconfig != NULL) + window->os4.transparent = fbconfig->transparent; + else + window->os4.transparent = 0; + window->os4.opacity = 1.f; + + window->os4.windowType = windowType; + + window->os4.handle = IIntuition->OpenWindowTags(NULL, + WA_Left, window->os4.xpos, + WA_Top, window->os4.ypos, + WA_InnerWidth, wndconfig->width, + WA_InnerHeight, wndconfig->height, + WA_Title, wndconfig->title, + WA_IDCMP, IDCMP_CLOSEWINDOW | + IDCMP_MOUSEMOVE | + IDCMP_MOUSEBUTTONS | + IDCMP_EXTENDEDMOUSE | + IDCMP_RAWKEY | + IDCMP_NEWSIZE | + IDCMP_DELTAMOVE | + IDCMP_ACTIVEWINDOW | + IDCMP_INACTIVEWINDOW | + IDCMP_INTUITICKS | + IDCMP_GADGETUP | + IDCMP_CHANGEWINDOW, + WA_SmartRefresh, TRUE, + WA_DepthGadget, TRUE, + WA_DragBar, TRUE, + WA_CloseGadget, TRUE, + WA_Activate, TRUE, + WA_RMBTrap, TRUE, + WA_ReportMouse, TRUE, + WA_Hidden, !wndconfig->visible, + WA_UserPort, _glfw.os4.userPort, + WA_BackFill, LAYERS_NOBACKFILL, // Don't want default backfill + TAG_DONE); + + /* If we have a valid handle return GLFW_TRUE */ + if (window->os4.handle) { + window->os4.lastCursorPosX = window->os4.xpos; + window->os4.lastCursorPosY = window->os4.ypos; + return GLFW_TRUE; + } + else + return GLFW_FALSE; +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +int _glfwCreateWindowOS4(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWctxconfig* ctxconfig, + const _GLFWfbconfig* fbconfig) +{ + if (!createNativeWindow(window, wndconfig, fbconfig, ctxconfig->client)) + return GLFW_FALSE; + + if (ctxconfig->client != GLFW_NO_API) + { + if (!_glfwCreateContextGL(window, ctxconfig, fbconfig)) + return GLFW_FALSE; + } + + if (window->monitor) + { + _glfwShowWindowOS4(window); + _glfwFocusWindowOS4(window); + acquireMonitor(window); + } + + return GLFW_TRUE; +} + +void _glfwDestroyWindowOS4(_GLFWwindow* window) +{ + printf("destroying context\n"); + if (window->context.destroy) + window->context.destroy(window); + printf("destroyed\n"); + + printf("closing window\n"); + IIntuition->CloseWindow(window->os4.handle); + printf("closed\n\n"); + + if (window->monitor) + releaseMonitor(window); + + if (_glfw.os4.focusedWindow == window) + _glfw.os4.focusedWindow = NULL; +} + +void _glfwSetWindowTitleOS4(_GLFWwindow* window, const char* title) +{ + IIntuition->SetWindowTitles(window->os4.handle, title, title); +} + +void _glfwSetWindowIconOS4(_GLFWwindow* window, int count, const GLFWimage* images) +{ + // We don't have window's icon +} + +void _glfwSetWindowMonitorOS4(_GLFWwindow* window, + _GLFWmonitor* monitor, + int xpos, int ypos, + int width, int height, + int refreshRate) +{ + if (window->monitor == monitor) + { + if (!monitor) + { + _glfwSetWindowPosOS4(window, xpos, ypos); + _glfwSetWindowSizeOS4(window, width, height); + } + + return; + } + + if (window->monitor) + releaseMonitor(window); + + _glfwInputWindowMonitor(window, monitor); + + if (window->monitor) + { + window->os4.visible = GLFW_TRUE; + acquireMonitor(window); + fitToMonitor(window); + } + else + { + _glfwSetWindowPosOS4(window, xpos, ypos); + _glfwSetWindowSizeOS4(window, width, height); + } +} + +void _glfwGetWindowPosOS4(_GLFWwindow* window, int* xpos, int* ypos) +{ + if (xpos) + *xpos = window->os4.xpos; + if (ypos) + *ypos = window->os4.ypos; +} + +void _glfwSetWindowPosOS4(_GLFWwindow* window, int xpos, int ypos) +{ + if (window->monitor) + return; + + if (window->os4.xpos != xpos || window->os4.ypos != ypos) + { + window->os4.xpos = xpos; + window->os4.ypos = ypos; + _glfwInputWindowPos(window, xpos, ypos); + + IIntuition->SetWindowAttrs(window->os4.handle, + WA_Left, xpos, + WA_Top, ypos, + TAG_DONE); + + window->os4.lastCursorPosX = xpos; + window->os4.lastCursorPosY = ypos; + } +} + +void _glfwGetWindowSizeOS4(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->os4.width; + if (height) + *height = window->os4.height; +} + +void _glfwSetWindowSizeOS4(_GLFWwindow* window, int width, int height) +{ + if (window->monitor) + return; + + if (window->os4.width != width || window->os4.height != height) + { + window->os4.width = width; + window->os4.height = height; + _glfwInputWindowSize(window, width, height); + _glfwInputFramebufferSize(window, width, height); + + IIntuition->SetWindowAttrs(window->os4.handle, + WA_Width, width, + WA_Height, height, + TAG_DONE); + } +} + +void _glfwSetWindowSizeLimitsOS4(_GLFWwindow* window, + int minwidth, int minheight, + int maxwidth, int maxheight) +{ + int width = window->os4.width; + int height = window->os4.height; + applySizeLimits(window, &width, &height); + _glfwSetWindowSizeOS4(window, width, height); +} + +void _glfwSetWindowAspectRatioOS4(_GLFWwindow* window, int n, int d) +{ + int width = window->os4.width; + int height = window->os4.height; + applySizeLimits(window, &width, &height); + _glfwSetWindowSizeOS4(window, width, height); +} + +void _glfwGetFramebufferSizeOS4(_GLFWwindow* window, int* width, int* height) +{ + if (width) + *width = window->os4.width; + if (height) + *height = window->os4.height; +} + +void _glfwGetWindowFrameSizeOS4(_GLFWwindow* window, + int* left, int* top, + int* right, int* bottom) +{ + if (window->os4.decorated && !window->monitor) + { + if (left) + *left = 1; + if (top) + *top = 10; + if (right) + *right = 1; + if (bottom) + *bottom = 1; + } + else + { + if (left) + *left = 0; + if (top) + *top = 0; + if (right) + *right = 0; + if (bottom) + *bottom = 0; + } +} + +void _glfwGetWindowContentScaleOS4(_GLFWwindow* window, float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + +void _glfwIconifyWindowOS4(_GLFWwindow* window) +{ + if (_glfw.os4.focusedWindow == window) + { + _glfw.os4.focusedWindow = NULL; + _glfwInputWindowFocus(window, GLFW_FALSE); + } + + if (!window->os4.iconified) + { + window->os4.iconified = GLFW_TRUE; + _glfwInputWindowIconify(window, GLFW_TRUE); + + if (window->monitor) + releaseMonitor(window); + } +} + +void _glfwRestoreWindowOS4(_GLFWwindow* window) +{ + if (window->os4.iconified) + { + window->os4.iconified = GLFW_FALSE; + _glfwInputWindowIconify(window, GLFW_FALSE); + + if (window->monitor) + acquireMonitor(window); + } + else if (window->os4.maximized) + { + window->os4.maximized = GLFW_FALSE; + _glfwInputWindowMaximize(window, GLFW_FALSE); + } +} + +void _glfwMaximizeWindowOS4(_GLFWwindow* window) +{ + if (!window->os4.maximized) + { + window->os4.maximized = GLFW_TRUE; + _glfwInputWindowMaximize(window, GLFW_TRUE); + } +} + +int _glfwWindowMaximizedOS4(_GLFWwindow* window) +{ + return window->os4.maximized; +} + +int _glfwWindowHoveredOS4(_GLFWwindow* window) +{ + return _glfw.os4.xcursor >= window->os4.xpos && + _glfw.os4.ycursor >= window->os4.ypos && + _glfw.os4.xcursor <= window->os4.xpos + window->os4.width - 1 && + _glfw.os4.ycursor <= window->os4.ypos + window->os4.height - 1; +} + +int _glfwFramebufferTransparentOS4(_GLFWwindow* window) +{ + return window->os4.transparent; +} + +void _glfwSetWindowResizableOS4(_GLFWwindow* window, GLFWbool enabled) +{ + window->os4.resizable = enabled; +} + +void _glfwSetWindowDecoratedOS4(_GLFWwindow* window, GLFWbool enabled) +{ + window->os4.decorated = enabled; +} + +void _glfwSetWindowFloatingOS4(_GLFWwindow* window, GLFWbool enabled) +{ + window->os4.floating = enabled; +} + +void _glfwSetWindowMousePassthroughOS4(_GLFWwindow* window, GLFWbool enabled) +{ +} + +float _glfwGetWindowOpacityOS4(_GLFWwindow* window) +{ + return window->os4.opacity; +} + +void _glfwSetWindowOpacityOS4(_GLFWwindow* window, float opacity) +{ + window->os4.opacity = opacity; + + int iOpacity = (int)opacity * 255; + + IIntuition->SetWindowAttrs(window->os4.handle, WA_Opaqueness, iOpacity, TAG_DONE); + +} + +void _glfwSetRawMouseMotionOS4(_GLFWwindow *window, GLFWbool enabled) +{ +} + +GLFWbool _glfwRawMouseMotionSupportedOS4(void) +{ + return GLFW_TRUE; +} + +void _glfwShowWindowOS4(_GLFWwindow* window) +{ + window->os4.visible = GLFW_TRUE; + + IIntuition->ShowWindow(window->os4.handle, NULL); +} + +void _glfwRequestWindowAttentionOS4(_GLFWwindow* window) +{ +} + +void _glfwHideWindowOS4(_GLFWwindow* window) +{ + if (_glfw.os4.focusedWindow == window) + { + _glfw.os4.focusedWindow = NULL; + _glfwInputWindowFocus(window, GLFW_FALSE); + } + + window->os4.visible = GLFW_FALSE; + + IIntuition->HideWindow(window->os4.handle); +} + +void _glfwFocusWindowOS4(_GLFWwindow* window) +{ + _GLFWwindow* previous; + + if (_glfw.os4.focusedWindow == window) + return; + + if (!window->os4.visible) + return; + + previous = _glfw.os4.focusedWindow; + _glfw.os4.focusedWindow = window; + + if (previous) + { + _glfwInputWindowFocus(previous, GLFW_FALSE); + if (previous->monitor && previous->autoIconify) + _glfwIconifyWindowOS4(previous); + } + + _glfwInputWindowFocus(window, GLFW_TRUE); +} + +int _glfwWindowFocusedOS4(_GLFWwindow* window) +{ + printf("Focused window: 0x%x\n", window); + return _glfw.os4.focusedWindow == window; +} + +int _glfwWindowIconifiedOS4(_GLFWwindow* window) +{ + return window->os4.iconified; +} + +int _glfwWindowVisibleOS4(_GLFWwindow* window) +{ + return window->os4.visible; +} + +void _glfwPollEventsOS4(void) +{ + struct IntuiMessage *imsg; + struct MyIntuiMessage msg; + + while ((imsg = (struct IntuiMessage *)IExec->GetMsg(_glfw.os4.userPort))) { + + OS4_CopyIdcmpMessage(imsg, &msg); + _GLFWwindow* window = OS4_FindWindow(imsg->IDCMPWindow); + + IExec->ReplyMsg((struct Message *) imsg); + + switch (msg.Class) { + case IDCMP_MOUSEMOVE: + _glfwInputCursorPos(window, msg.WindowMouseX, msg.WindowMouseY); + break; + + case IDCMP_RAWKEY: + uint8_t rawkey = msg.Code & 0x7F; + printf("RAWKEY = 0x%x\n", rawkey); + int key = _glfw.os4.keycodes[rawkey]; + int mods = OS4_TranslateState(msg.Qualifier); + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + + if (imsg->Code < 0x80) { + char text[2]; + + text[0] = OS4_TranslateUnicode(msg.Code, msg.Qualifier); + text[1] = '\0'; + + _glfwInputKey(window, key, rawkey, GLFW_PRESS, mods); + + if (text[0] && text[0] < 0x80) { + _glfwInputChar(window, text, mods, plain); + } + } else { + _glfwInputKey(window, key, rawkey, GLFW_RELEASE, mods); + } + break; + + case IDCMP_MOUSEBUTTONS: + //OS4_HandleMouseButtons(_this, &msg); + int button = OS4_GetButton(imsg->Code); + int state = OS4_GetButtonState(imsg->Code); + + _glfwInputMouseClick(window, + button, + state, + 0); + break; + + case IDCMP_EXTENDEDMOUSE: + //OS4_HandleMouseWheel(_this, &msg); + break; + + case IDCMP_NEWSIZE: + //OS4_HandleResize(_this, &msg); + break; + + case IDCMP_CHANGEWINDOW: + if (window != NULL) { + printf("window %x x=%d y=%d\n", window, imsg->IDCMPWindow->LeftEdge, imsg->IDCMPWindow->TopEdge); + window->os4.xpos = imsg->IDCMPWindow->LeftEdge; + window->os4.ypos = imsg->IDCMPWindow->TopEdge; + } + else + printf("CHANGE: no window found\n"); + + //OS4_HandleMove(_this, &msg); + //OS4_HandleResize(_this, &msg); + break; + + case IDCMP_ACTIVEWINDOW: + //OS4_HandleActivation(_this, &msg, SDL_TRUE); + break; + + case IDCMP_INACTIVEWINDOW: + //OS4_HandleActivation(_this, &msg, SDL_FALSE); + break; + + case IDCMP_CLOSEWINDOW: + if (window != NULL) { + _glfwInputWindowCloseRequest(_glfw.os4.focusedWindow); + } + else + printf("CLOSE: no window found\n"); + + break; + + case IDCMP_INTUITICKS: + //OS4_HandleTicks(_this, &msg); + break; + + case IDCMP_GADGETUP: + //OS4_HandleGadget(_this, &msg); + break; + + default: + //dprintf("Unknown event received class %d, code %d\n", msg.Class, msg.Code); + break; + } + } +} + +void _glfwWaitEventsOS4(void) +{ + _glfwPollEventsOS4(); +} + +void _glfwWaitEventsTimeoutOS4(double timeout) +{ + _glfwPollEventsOS4(); +} + +void _glfwPostEmptyEventOS4(void) +{ +} + +void _glfwGetCursorPosOS4(_GLFWwindow* window, double* xpos, double* ypos) +{ + if (xpos) + *xpos = _glfw.os4.xcursor - window->os4.xpos; + if (ypos) + *ypos = _glfw.os4.ycursor - window->os4.ypos; +} + +void _glfwSetCursorPosOS4(_GLFWwindow* window, double x, double y) +{ + _glfw.os4.xcursor = window->os4.xpos + (int) x; + _glfw.os4.ycursor = window->os4.ypos + (int) y; +} + +void _glfwSetCursorModeOS4(_GLFWwindow* window, int mode) +{ +} + +int _glfwCreateCursorOS4(_GLFWcursor* cursor, + const GLFWimage* image, + int xhot, int yhot) +{ + uint32_t *buffer = OS4_CopyImageData(image); + + /* We need to pass some compatibility parameters even though we are going to use just ARGB pointer */ + Object *object = IIntuition->NewObject( + NULL, + POINTERCLASS, + POINTERA_BitMap, &fallbackPointerBitMap, + POINTERA_XOffset, xhot, + POINTERA_YOffset, yhot, + POINTERA_WordWidth, 1, + POINTERA_XResolution, POINTERXRESN_SCREENRES, + POINTERA_YResolution, POINTERYRESN_SCREENRES, + POINTERA_ImageData, buffer, + POINTERA_Width, image->width, + POINTERA_Height, image->height, + TAG_DONE); + if (object) { + printf("cursor created\n"); + cursor->os4.handle = object; + cursor->os4.imageData = buffer; + return GLFW_TRUE; + } + printf("error creating cursor\n"); + return GLFW_FALSE; +} + +int _glfwCreateStandardCursorOS4(_GLFWcursor* cursor, int shape) +{ + return GLFW_TRUE; +} + +void _glfwDestroyCursorOS4(_GLFWcursor* cursor) +{ + if (cursor->os4.handle) { + IIntuition->DisposeObject(cursor->os4.handle); + if (cursor->os4.imageData) + free(cursor->os4.imageData); + cursor->os4.imageData = NULL; + cursor->os4.handle = NULL; + } +} + +void _glfwSetCursorOS4(_GLFWwindow* window, _GLFWcursor* cursor) +{ +} + +void _glfwSetClipboardStringOS4(const char* string) +{ + char* copy = _glfw_strdup(string); + _glfw_free(_glfw.os4.clipboardString); + _glfw.os4.clipboardString = copy; +} + +const char* _glfwGetClipboardStringOS4(void) +{ + return _glfw.os4.clipboardString; +} + +const char* _glfwGetScancodeNameOS4(int scancode) +{ + if (scancode < GLFW_KEY_SPACE || scancode > GLFW_KEY_LAST) + { + _glfwInputError(GLFW_INVALID_VALUE, "Invalid OS4 scancode %i", scancode); + return NULL; + } + return _glfw.os4.keynames[_glfw.os4.keycodes[scancode]]; + /* + + switch (scancode) + { + case GLFW_KEY_APOSTROPHE: + return "'"; + case GLFW_KEY_COMMA: + return ","; + case GLFW_KEY_MINUS: + case GLFW_KEY_KP_SUBTRACT: + return "-"; + case GLFW_KEY_PERIOD: + case GLFW_KEY_KP_DECIMAL: + return "."; + case GLFW_KEY_SLASH: + case GLFW_KEY_KP_DIVIDE: + return "/"; + case GLFW_KEY_SEMICOLON: + return ";"; + case GLFW_KEY_EQUAL: + case GLFW_KEY_KP_EQUAL: + return "="; + case GLFW_KEY_LEFT_BRACKET: + return "["; + case GLFW_KEY_RIGHT_BRACKET: + return "]"; + case GLFW_KEY_KP_MULTIPLY: + return "*"; + case GLFW_KEY_KP_ADD: + return "+"; + case GLFW_KEY_BACKSLASH: + case GLFW_KEY_WORLD_1: + case GLFW_KEY_WORLD_2: + return "\\"; + case GLFW_KEY_0: + case GLFW_KEY_KP_0: + return "0"; + case GLFW_KEY_1: + case GLFW_KEY_KP_1: + return "1"; + case GLFW_KEY_2: + case GLFW_KEY_KP_2: + return "2"; + case GLFW_KEY_3: + case GLFW_KEY_KP_3: + return "3"; + case GLFW_KEY_4: + case GLFW_KEY_KP_4: + return "4"; + case GLFW_KEY_5: + case GLFW_KEY_KP_5: + return "5"; + case GLFW_KEY_6: + case GLFW_KEY_KP_6: + return "6"; + case GLFW_KEY_7: + case GLFW_KEY_KP_7: + return "7"; + case GLFW_KEY_8: + case GLFW_KEY_KP_8: + return "8"; + case GLFW_KEY_9: + case GLFW_KEY_KP_9: + return "9"; + case GLFW_KEY_A: + return "a"; + case GLFW_KEY_B: + return "b"; + case GLFW_KEY_C: + return "c"; + case GLFW_KEY_D: + return "d"; + case GLFW_KEY_E: + return "e"; + case GLFW_KEY_F: + return "f"; + case GLFW_KEY_G: + return "g"; + case GLFW_KEY_H: + return "h"; + case GLFW_KEY_I: + return "i"; + case GLFW_KEY_J: + return "j"; + case GLFW_KEY_K: + return "k"; + case GLFW_KEY_L: + return "l"; + case GLFW_KEY_M: + return "m"; + case GLFW_KEY_N: + return "n"; + case GLFW_KEY_O: + return "o"; + case GLFW_KEY_P: + return "p"; + case GLFW_KEY_Q: + return "q"; + case GLFW_KEY_R: + return "r"; + case GLFW_KEY_S: + return "s"; + case GLFW_KEY_T: + return "t"; + case GLFW_KEY_U: + return "u"; + case GLFW_KEY_V: + return "v"; + case GLFW_KEY_W: + return "w"; + case GLFW_KEY_X: + return "x"; + case GLFW_KEY_Y: + return "y"; + case GLFW_KEY_Z: + return "z"; + } + + return NULL; + */ +} + +int _glfwGetKeyScancodeOS4(int key) +{ + return key; +} + +void _glfwGetRequiredInstanceExtensionsOS4(char** extensions) +{ +} + +int _glfwGetPhysicalDevicePresentationSupportOS4(VkInstance instance, + VkPhysicalDevice device, + uint32_t queuefamily) +{ + return GLFW_FALSE; +} + +VkResult _glfwCreateWindowSurfaceOS4(VkInstance instance, + _GLFWwindow* window, + const VkAllocationCallbacks* allocator, + VkSurfaceKHR* surface) +{ + // This seems like the most appropriate error to return here + return VK_ERROR_EXTENSION_NOT_PRESENT; +} + + +/* PRIVATE METHODS */ +static _GLFWwindow * +OS4_FindWindow(struct Window * syswin) +{ + _GLFWwindow *glfwWin; + + glfwWin = _glfw.windowListHead; + while (glfwWin) + { + if (glfwWin->os4.handle == syswin) + return glfwWin; + glfwWin = glfwWin->next; + } + + //dprintf("No window found\n"); + + return NULL; +} + +static void +OS4_CopyIdcmpMessage(struct IntuiMessage * src, struct MyIntuiMessage * dst) +{ + // Copy relevant fields. This makes it safer if the window goes away during + // this loop (re-open due to keystroke) + dst->Class = src->Class; + dst->Code = src->Code; + dst->Qualifier = src->Qualifier; + + dst->Gadget = (struct Gadget *) src->IAddress; + + dst->RelativeMouseX = src->MouseX; + dst->RelativeMouseY = src->MouseY; + + dst->IDCMPWindow = src->IDCMPWindow; + + if (src->IDCMPWindow) { + dst->WindowMouseX = src->IDCMPWindow->MouseX - src->IDCMPWindow->BorderLeft; + dst->WindowMouseY = src->IDCMPWindow->MouseY - src->IDCMPWindow->BorderTop; + + dst->ScreenMouseX = src->IDCMPWindow->WScreen->MouseX; + dst->ScreenMouseY = src->IDCMPWindow->WScreen->MouseY; + + dst->Width = src->IDCMPWindow->Width - src->IDCMPWindow->BorderLeft - src->IDCMPWindow->BorderRight; + dst->Height = src->IDCMPWindow->Height - src->IDCMPWindow->BorderTop - src->IDCMPWindow->BorderBottom; + } +} + +static uint32_t* +OS4_CopyImageData(const GLFWimage *surface) +{ + const size_t bytesPerRow = surface->width * sizeof(uint32_t); + uint32_t* buffer = malloc(bytesPerRow * surface->height); + + //dprintf("Copying cursor data %d*%d from surface %p to buffer %p\n", surface->w, surface->h, surface, buffer); + + if (buffer) { + uint8_t* source = surface->pixels; + uint32_t* destination = buffer; + int y; + + for (y = 0; y < surface->height; y++) { + memcpy(destination, source, bytesPerRow); + destination += surface->width; + source += 4; + } + } else { + //dprintf("Failed to allocate memory\n"); + } + + return buffer; +} + +static int +OS4_GetButtonState(uint16_t code) +{ + return (code & IECODE_UP_PREFIX) ? GLFW_RELEASE : GLFW_PRESS; +} + +static int +OS4_GetButton(uint16_t code) +{ + switch (code & ~IECODE_UP_PREFIX) { + case IECODE_LBUTTON: + return GLFW_MOUSE_BUTTON_LEFT; + case IECODE_RBUTTON: + return GLFW_MOUSE_BUTTON_RIGHT; + case IECODE_MBUTTON: + return GLFW_MOUSE_BUTTON_MIDDLE; + default: + return 0; + } +} + +static char +OS4_TranslateUnicode(uint16_t code, uint32_t qualifier) +{ + struct InputEvent ie; + uint16_t res; + char buffer[10]; + + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_SubClass = 0; + ie.ie_Code = code & ~(IECODE_UP_PREFIX); + ie.ie_Qualifier = qualifier; + ie.ie_EventAddress = NULL; + + res = IKeymap->MapRawKey(&ie, buffer, sizeof(buffer), 0); + + if (res != 1) + return 0; + else + return buffer[0]; +} + +static int OS4_TranslateState(int state) +{ + int mods = 0; + + if (state & IEQUALIFIER_LSHIFT || state & IEQUALIFIER_RSHIFT) + mods |= GLFW_MOD_SHIFT; + if (state & IEQUALIFIER_CONTROL) + mods |= GLFW_MOD_CONTROL; + if (state & IEQUALIFIER_LALT || state & IEQUALIFIER_RALT) + mods |= GLFW_MOD_ALT; + if (state & IEQUALIFIER_LCOMMAND || state & IEQUALIFIER_RCOMMAND) + mods |= GLFW_MOD_SUPER; + if (state & IEQUALIFIER_CAPSLOCK) + mods |= GLFW_MOD_CAPS_LOCK; + + return mods; +} \ No newline at end of file diff --git a/src/platform.c b/src/platform.c index d0bbd06d..c7ba937a 100644 --- a/src/platform.c +++ b/src/platform.c @@ -51,6 +51,9 @@ static const struct #if defined(_GLFW_WAYLAND) { GLFW_PLATFORM_WAYLAND, _glfwConnectWayland }, #endif +#if defined(_GLFW_OS4) + { GLFW_PLATFORM_OS4, _glfwConnectOS4 }, +#endif }; GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) @@ -63,7 +66,8 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) desiredID != GLFW_PLATFORM_COCOA && desiredID != GLFW_PLATFORM_WAYLAND && desiredID != GLFW_PLATFORM_X11 && - desiredID != GLFW_PLATFORM_NULL) + desiredID != GLFW_PLATFORM_NULL && + desiredID != GLFW_PLATFORM_OS4) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", desiredID); return GLFW_FALSE; diff --git a/src/platform.h b/src/platform.h index cc842eb8..04dce761 100644 --- a/src/platform.h +++ b/src/platform.h @@ -69,6 +69,17 @@ #define GLFW_GLX_LIBRARY_CONTEXT_STATE #endif +#if defined(_GLFW_OS4) + #include "os4_platform.h" +#else + #define GLFW_OS4_WINDOW_STATE + #define GLFW_OS4_MONITOR_STATE + #define GLFW_OS4_CURSOR_STATE + #define GLFW_OS4_LIBRARY_WINDOW_STATE + #define GLFW_GLX_CONTEXT_STATE + #define GLFW_GLX_LIBRARY_CONTEXT_STATE +#endif + #include "null_joystick.h" #if defined(_GLFW_WIN32) @@ -122,6 +133,7 @@ GLFW_WAYLAND_WINDOW_STATE \ GLFW_X11_WINDOW_STATE \ GLFW_NULL_WINDOW_STATE \ + GLFW_OS4_WINDOW_STATE \ #define GLFW_PLATFORM_MONITOR_STATE \ GLFW_WIN32_MONITOR_STATE \ @@ -129,6 +141,7 @@ GLFW_WAYLAND_MONITOR_STATE \ GLFW_X11_MONITOR_STATE \ GLFW_NULL_MONITOR_STATE \ + GLFW_OS4_MONITOR_STATE \ #define GLFW_PLATFORM_CURSOR_STATE \ GLFW_WIN32_CURSOR_STATE \ @@ -136,6 +149,7 @@ GLFW_WAYLAND_CURSOR_STATE \ GLFW_X11_CURSOR_STATE \ GLFW_NULL_CURSOR_STATE \ + GLFW_OS4_CURSOR_STATE \ #define GLFW_PLATFORM_JOYSTICK_STATE \ GLFW_WIN32_JOYSTICK_STATE \ @@ -156,6 +170,7 @@ GLFW_WAYLAND_LIBRARY_WINDOW_STATE \ GLFW_X11_LIBRARY_WINDOW_STATE \ GLFW_NULL_LIBRARY_WINDOW_STATE \ + GLFW_OS4_LIBRARY_WINDOW_STATE \ #define GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \ GLFW_WIN32_LIBRARY_JOYSTICK_STATE \ @@ -170,10 +185,12 @@ #define GLFW_PLATFORM_CONTEXT_STATE \ GLFW_WGL_CONTEXT_STATE \ GLFW_NSGL_CONTEXT_STATE \ - GLFW_GLX_CONTEXT_STATE + GLFW_GLX_CONTEXT_STATE \ + GLFW_OS4_CONTEXT_STATE #define GLFW_PLATFORM_LIBRARY_CONTEXT_STATE \ GLFW_WGL_LIBRARY_CONTEXT_STATE \ GLFW_NSGL_LIBRARY_CONTEXT_STATE \ - GLFW_GLX_LIBRARY_CONTEXT_STATE + GLFW_GLX_LIBRARY_CONTEXT_STATE \ + GLFW_OS4_LIBRARY_CONTEXT_STATE \ diff --git a/tests/threads.c b/tests/threads.c index ec13b001..5ba7c869 100644 --- a/tests/threads.c +++ b/tests/threads.c @@ -148,6 +148,7 @@ int main(void) for (i = 0; i < count; i++) thrd_join(threads[i].id, &result); + glfwTerminate(); exit(EXIT_SUCCESS); }