Optimized build that works

This commit is contained in:
Synthasmagoria 2026-08-30 21:05:55 +02:00
commit 400c5a02d1
105 changed files with 13399 additions and 8732 deletions

View file

@ -9,6 +9,9 @@ if [[ -v 1 ]]; then
elif [ "$1" = "RELEASE" ]; then elif [ "$1" = "RELEASE" ]; then
MFLAGS="RAYLIB_BUILD_MODE=RELEASE" MFLAGS="RAYLIB_BUILD_MODE=RELEASE"
CFLAGS="-Os -ffunction-sections -fdata-sections" CFLAGS="-Os -ffunction-sections -fdata-sections"
elif [ "$1" = "TEST" ]; then
MFLAGS="RAYLIB_BUILD_MODE=RELEASE"
CFLAGS="-Os"
else else
echo "Usage: <script> <DEBUG/RELEASE>" echo "Usage: <script> <DEBUG/RELEASE>"
exit 1 exit 1
@ -34,67 +37,67 @@ config_cflags="\
-DSUPPORT_MODULE_RSHAPES=1 \ -DSUPPORT_MODULE_RSHAPES=1 \
-DSUPPORT_MODULE_RTEXTURES=1 \ -DSUPPORT_MODULE_RTEXTURES=1 \
-DSUPPORT_MODULE_RTEXT=1 \ -DSUPPORT_MODULE_RTEXT=1 \
-DSUPPORT_MODULE_RMODELS=0 \ -DSUPPORT_MODULE_RMODELS=1 \
-DSUPPORT_MODULE_RAUDIO=0 \ -DSUPPORT_MODULE_RAUDIO=1 \
-DSUPPORT_TRACELOG=1 \ -DSUPPORT_TRACELOG=1 \
-DSUPPORT_CAMERA_SYSTEM=0 \ -DSUPPORT_CAMERA_SYSTEM=1 \
-DSUPPORT_GESTURES_SYSTEM=0 \ -DSUPPORT_GESTURES_SYSTEM=1 \
-DSUPPORT_RPRAND_GENERATOR=0 \ -DSUPPORT_RPRAND_GENERATOR=1 \
-DSUPPORT_MOUSE_GESTURES=0 \ -DSUPPORT_MOUSE_GESTURES=1 \
-DSUPPORT_SSH_KEYBOARD_RPI=0 \ -DSUPPORT_SSH_KEYBOARD_RPI=1 \
-DSUPPORT_WINMM_HIGHRES_TIMER=0 \ -DSUPPORT_WINMM_HIGHRES_TIMER=1 \
-DSUPPORT_BUSY_WAIT_LOOP=0 \ -DSUPPORT_BUSY_WAIT_LOOP=1 \
-DSUPPORT_PARTIALBUSY_WAIT_LOOP=0 \ -DSUPPORT_PARTIALBUSY_WAIT_LOOP=1 \
-DSUPPORT_SCREEN_CAPTURE=0 \ -DSUPPORT_SCREEN_CAPTURE=1 \
-DSUPPORT_COMPRESSION_API=0 \ -DSUPPORT_COMPRESSION_API=1 \
-DSUPPORT_AUTOMATION_EVENTS=0 \ -DSUPPORT_AUTOMATION_EVENTS=1 \
-DSUPPORT_CUSTOM_FRAME_CONTROL=0 \ -DSUPPORT_CUSTOM_FRAME_CONTROL=1 \
-DSUPPORT_CLIPBOARD_IMAGE=0 \ -DSUPPORT_CLIPBOARD_IMAGE=1 \
-DRLGL_ENABLE_OPENGL_DEBUG_CONTEXT=0 \ -DRLGL_ENABLE_OPENGL_DEBUG_CONTEXT=1 \
-DRLGL_SHOW_GL_DETAILS_INFO=0 \ -DRLGL_SHOW_GL_DETAILS_INFO=1 \
-DSUPPORT_QUADS_DRAW_MODE=0 \ -DSUPPORT_QUADS_DRAW_MODE=1 \
-DSUPPORT_FILEFORMAT_PNG=0 \ -DSUPPORT_FILEFORMAT_PNG=1 \
-DSUPPORT_FILEFORMAT_BMP=0 \ -DSUPPORT_FILEFORMAT_BMP=1 \
-DSUPPORT_FILEFORMAT_TGA=0 \ -DSUPPORT_FILEFORMAT_TGA=1 \
-DSUPPORT_FILEFORMAT_JPG=0 \ -DSUPPORT_FILEFORMAT_JPG=1 \
-DSUPPORT_FILEFORMAT_GIF=0 \ -DSUPPORT_FILEFORMAT_GIF=1 \
-DSUPPORT_FILEFORMAT_QOI=0 \ -DSUPPORT_FILEFORMAT_QOI=1 \
-DSUPPORT_FILEFORMAT_PEP=0 \ -DSUPPORT_FILEFORMAT_PEP=1 \
-DSUPPORT_FILEFORMAT_PSD=0 \ -DSUPPORT_FILEFORMAT_PSD=1 \
-DSUPPORT_FILEFORMAT_DDS=0 \ -DSUPPORT_FILEFORMAT_DDS=1 \
-DSUPPORT_FILEFORMAT_HDR=0 \ -DSUPPORT_FILEFORMAT_HDR=1 \
-DSUPPORT_FILEFORMAT_PIC=0 \ -DSUPPORT_FILEFORMAT_PIC=1 \
-DSUPPORT_FILEFORMAT_PNM=0 \ -DSUPPORT_FILEFORMAT_PNM=1 \
-DSUPPORT_FILEFORMAT_KTX=0 \ -DSUPPORT_FILEFORMAT_KTX=1 \
-DSUPPORT_FILEFORMAT_ASTC=0 \ -DSUPPORT_FILEFORMAT_ASTC=1 \
-DSUPPORT_FILEFORMAT_PKM=0 \ -DSUPPORT_FILEFORMAT_PKM=1 \
-DSUPPORT_FILEFORMAT_PVR=0 \ -DSUPPORT_FILEFORMAT_PVR=1 \
-DSUPPORT_IMAGE_EXPORT=0 \ -DSUPPORT_IMAGE_EXPORT=1 \
-DSUPPORT_IMAGE_GENERATION=0 \ -DSUPPORT_IMAGE_GENERATION=1 \
-DSUPPORT_FILEFORMAT_TTF=1 \ -DSUPPORT_FILEFORMAT_TTF=1 \
-DSUPPORT_FILEFORMAT_FNT=0 \ -DSUPPORT_FILEFORMAT_FNT=1 \
-DSUPPORT_FILEFORMAT_BDF=0 \ -DSUPPORT_FILEFORMAT_BDF=1 \
-DSUPPORT_FILEFORMAT_OBJ=0 \ -DSUPPORT_FILEFORMAT_OBJ=1 \
-DSUPPORT_FILEFORMAT_MTL=0 \ -DSUPPORT_FILEFORMAT_MTL=1 \
-DSUPPORT_FILEFORMAT_IQM=0 \ -DSUPPORT_FILEFORMAT_IQM=1 \
-DSUPPORT_FILEFORMAT_GLTF=0 \ -DSUPPORT_FILEFORMAT_GLTF=1 \
-DSUPPORT_FILEFORMAT_VOX=0 \ -DSUPPORT_FILEFORMAT_VOX=1 \
-DSUPPORT_FILEFORMAT_M3D=0 \ -DSUPPORT_FILEFORMAT_M3D=1 \
-DSUPPORT_MESH_GENERATION=0 \ -DSUPPORT_MESH_GENERATION=1 \
-DSUPPORT_GPU_SKINNING=0 \ -DSUPPORT_GPU_SKINNING=1 \
-DSUPPORT_FILEFORMAT_WAV=0 \ -DSUPPORT_FILEFORMAT_WAV=1 \
-DSUPPORT_FILEFORMAT_OGG=0 \ -DSUPPORT_FILEFORMAT_OGG=1 \
-DSUPPORT_FILEFORMAT_MP3=0 \ -DSUPPORT_FILEFORMAT_MP3=1 \
-DSUPPORT_FILEFORMAT_QOA=0 \ -DSUPPORT_FILEFORMAT_QOA=1 \
-DSUPPORT_FILEFORMAT_FLAC=0 \ -DSUPPORT_FILEFORMAT_FLAC=1 \
-DSUPPORT_FILEFORMAT_XM=0 \ -DSUPPORT_FILEFORMAT_XM=1 \
-DSUPPORT_FILEFORMAT_MOD=0" -DSUPPORT_FILEFORMAT_MOD=1"
source $emsdk_env source $emsdk_env
pushd raylib/src pushd raylib/src
echo "Compiling raylib static library for linux" echo "Compiling raylib static library for linux"
make --silent $modules $MFLAGS RAYLIB_CONFIG_FLAGS="$config_cflags" CUSTOM_CFLAGS="$CFLAGS" PLATFORM_OS=LINUX make --silent $modules $MFLAGS CUSTOM_CFLAGS="$CFLAGS" PLATFORM_OS=LINUX
mv libraylib.a "../../${linux_library_dest}" mv libraylib.a "../../${linux_library_dest}"
make --silent clean make --silent clean
@ -104,7 +107,7 @@ make --silent clean
# make --silent clean # make --silent clean
echo "Compiling raylib static library for web" echo "Compiling raylib static library for web"
make --silent $modules RAYLIB_CONFIG_FLAGS="$config_cflags" PLATFORM=PLATFORM_WEB make --silent $modules PLATFORM=PLATFORM_WEB
mv libraylib.web.a libraylib.a mv libraylib.web.a libraylib.a
mv libraylib.a "../../${wasm_library_dest}" mv libraylib.a "../../${wasm_library_dest}"
make --silent clean make --silent clean

View file

@ -4214,7 +4214,7 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
// NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used
Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
if (result != RESULT_CHANGED) result = GuiColorBarHue(boundsHue, NULL, &hsv.x); result = GuiColorBarHue(boundsHue, NULL, &hsv.x);
//color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
Vector3 rgb = ConvertHSVtoRGB(hsv); Vector3 rgb = ConvertHSVtoRGB(hsv);
@ -4449,11 +4449,11 @@ int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, ch
Rectangle textBounds = { 0 }; Rectangle textBounds = { 0 };
if (message != NULL) if (message != NULL)
{ {
int textSize = GuiGetTextWidth(message) + 2; int messageTextSize = GuiGetTextWidth(message) + 2;
textBounds.x = bounds.x + bounds.width/2 - textSize/2; textBounds.x = bounds.x + bounds.width/2 - messageTextSize/2;
textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
textBounds.width = (float)textSize; textBounds.width = (float)messageTextSize;
textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
} }
@ -4641,8 +4641,8 @@ void GuiLoadStyle(const char *fileName)
{ {
case 'v': case 'v':
{ {
sscanf(buffer, "v %d", &version); sscanf(buffer, "v %u", &version);
} } break;
case 'p': case 'p':
{ {
// Style property: p <control_id> <property_id> <property_value> <property_name> // Style property: p <control_id> <property_id> <property_value> <property_name>

View file

@ -30,14 +30,22 @@ set(raylib_public_headers
# Sources to be compiled # Sources to be compiled
set(raylib_sources set(raylib_sources
raudio.c
rcore.c rcore.c
rmodels.c
rshapes.c rshapes.c
rtext.c rtext.c
rtextures.c rtextures.c
) )
# Only build raudio if it's enabled
if (NOT DEFINED SUPPORT_MODULE_RAUDIO OR SUPPORT_MODULE_RAUDIO)
list(APPEND raylib_sources raudio.c)
endif()
# Only build rmodels if it's enabled
if (NOT DEFINED SUPPORT_MODULE_RMODELS OR SUPPORT_MODULE_RMODELS)
list(APPEND raylib_sources rmodels.c)
endif()
# <root>/cmake/GlfwImport.cmake handles the details around the inclusion of glfw # <root>/cmake/GlfwImport.cmake handles the details around the inclusion of glfw
if (NOT ${PLATFORM} MATCHES "Web") if (NOT ${PLATFORM} MATCHES "Web")
include(GlfwImport) include(GlfwImport)
@ -48,10 +56,10 @@ endif ()
# Produces a variable LIBS_PRIVATE that will be used later # Produces a variable LIBS_PRIVATE that will be used later
include(LibraryConfigurations) include(LibraryConfigurations)
if (SUPPORT_MODULE_RAUDIO) if (DEFINED SUPPORT_MODULE_RAUDIO AND NOT SUPPORT_MODULE_RAUDIO)
MESSAGE(STATUS "Audio Backend: miniaudio")
else ()
MESSAGE(STATUS "Audio Backend: None (-DCUSTOMIZE_BUILD=ON -DSUPPORT_MODULE_RAUDIO=OFF)") MESSAGE(STATUS "Audio Backend: None (-DCUSTOMIZE_BUILD=ON -DSUPPORT_MODULE_RAUDIO=OFF)")
else ()
MESSAGE(STATUS "Audio Backend: miniaudio")
endif () endif ()
add_library(raylib ${raylib_sources} ${raylib_public_headers}) add_library(raylib ${raylib_sources} ${raylib_public_headers})
@ -99,6 +107,34 @@ endif ()
target_link_libraries(raylib PRIVATE $<BUILD_INTERFACE:${LIBS_PRIVATE}>) target_link_libraries(raylib PRIVATE $<BUILD_INTERFACE:${LIBS_PRIVATE}>)
target_link_libraries(raylib PUBLIC ${LIBS_PUBLIC}) target_link_libraries(raylib PUBLIC ${LIBS_PUBLIC})
# Static libraries must export their private link dependencies for installed consumers.
# LINK_ONLY keeps those dependencies out of the compile interface.
if (NOT BUILD_SHARED_LIBS)
set(raylib_install_private_libs ${LIBS_PRIVATE})
if (NOT glfw3_FOUND)
list(REMOVE_ITEM raylib_install_private_libs glfw)
# Bundled GLFW links its Cocoa backend frameworks privately, so they
# must be propagated to consumers of the static library, whose final
# link line would otherwise miss them. Only the Desktop platform uses
# bundled GLFW; other platforms (e.g. Memory) have no Cocoa/GLFW symbols.
if (APPLE AND PLATFORM STREQUAL "Desktop")
find_library(COCOA_FRAMEWORK Cocoa)
find_library(IOKIT_FRAMEWORK IOKit)
find_library(QUARTZCORE_FRAMEWORK QuartzCore)
list(APPEND raylib_install_private_libs
${COCOA_FRAMEWORK}
${IOKIT_FRAMEWORK}
${QUARTZCORE_FRAMEWORK})
endif ()
endif()
foreach(lib IN LISTS raylib_install_private_libs)
target_link_libraries(raylib INTERFACE $<INSTALL_INTERFACE:$<LINK_ONLY:${lib}>>)
endforeach()
endif()
# Sets some compile time definitions for the pre-processor # Sets some compile time definitions for the pre-processor
# If CUSTOMIZE_BUILD option is on you will not use config.h by default # If CUSTOMIZE_BUILD option is on you will not use config.h by default
# and you will be able to select more build options # and you will be able to select more build options

View file

@ -240,6 +240,9 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_ANDROID)
ifeq ($(ANDROID_ARCH),x86_64) ifeq ($(ANDROID_ARCH),x86_64)
ANDROID_COMPILER_ARCH = x86_64 ANDROID_COMPILER_ARCH = x86_64
endif endif
ifndef ANDROID_COMPILER_ARCH
$(error ANDROID_COMPILER_ARCH: Unknown ANDROID_ARCH=$(ANDROID_ARCH))
endif
endif endif
# Define raylib graphics api depending on selected platform # Define raylib graphics api depending on selected platform
@ -652,7 +655,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_GLFW)
#LDLIBS += -latomic #LDLIBS += -latomic
endif endif
ifeq ($(PLATFORM_OS),OSX) ifeq ($(PLATFORM_OS),OSX)
LDLIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo LDLIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo -framework QuartzCore
endif endif
ifeq ($(PLATFORM_OS),BSD) ifeq ($(PLATFORM_OS),BSD)
LDLIBS = -lGL -lpthread LDLIBS = -lGL -lpthread
@ -704,7 +707,7 @@ ifeq ($(TARGET_PLATFORM),PLATFORM_DESKTOP_RGFW)
ifeq ($(PLATFORM_OS),OSX) ifeq ($(PLATFORM_OS),OSX)
# Libraries for Debian MacOS desktop compiling # Libraries for Debian MacOS desktop compiling
# NOTE: Required packages: libegl1-mesa-dev # NOTE: Required packages: libegl1-mesa-dev
LDLIBS += -lm -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo LDLIBS += -lm -framework Foundation -framework AppKit -framework IOKit -framework OpenGL -framework CoreVideo -framework QuartzCore
endif endif
endif endif
ifeq ($(TARGET_PLATFORM),PLATFORM_DRM) ifeq ($(TARGET_PLATFORM),PLATFORM_DRM)

View file

@ -173,6 +173,7 @@
//#define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance //#define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance
// Default shader vertex attribute locations // Default shader vertex attribute locations
// NOTE: Locations can be redefined by user if required
//#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 //#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
//#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1 //#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
//#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2 //#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
@ -186,7 +187,8 @@
// Default shader vertex attribute/uniform names to set location points // Default shader vertex attribute/uniform names to set location points
// NOTE: When a new shader is loaded, locations are tried to be set for convenience, looking for the names defined here // NOTE: When a new shader is loaded, locations are tried to be set for convenience, looking for the names defined here
// In case custom shader names are used, it's up to the user to set locations with GetShaderLocation*() functions // WARNING: Location pre-defined names can not be changed, they are used by default shaders and all raylib examples shaders, they are just listed here for reference
// WARNING: In case custom shader names are used, it's up to the user to set locations with GetShaderLocation*() functions
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION //#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD //#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL //#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
@ -196,6 +198,7 @@
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES //#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS //#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
//#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM //#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix //#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix //#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix //#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
@ -203,6 +206,7 @@
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)) //#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (tint color, multiplied by texture color) //#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (tint color, multiplied by texture color)
//#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices //#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices
//#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) //#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
//#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) //#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
//#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) //#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
@ -240,6 +244,9 @@
#ifndef SUPPORT_FILEFORMAT_QOI #ifndef SUPPORT_FILEFORMAT_QOI
#define SUPPORT_FILEFORMAT_QOI 1 #define SUPPORT_FILEFORMAT_QOI 1
#endif #endif
#ifndef SUPPORT_FILEFORMAT_PEP
#define SUPPORT_FILEFORMAT_PEP 0
#endif
#ifndef SUPPORT_FILEFORMAT_PSD #ifndef SUPPORT_FILEFORMAT_PSD
#define SUPPORT_FILEFORMAT_PSD 0 // Disabled by default #define SUPPORT_FILEFORMAT_PSD 0 // Disabled by default
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* /*
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file. FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_flac - v0.13.3 - 2026-01-17 dr_flac - v0.13.4 - TBD
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -126,7 +126,7 @@ extern "C" {
#define DRFLAC_VERSION_MAJOR 0 #define DRFLAC_VERSION_MAJOR 0
#define DRFLAC_VERSION_MINOR 13 #define DRFLAC_VERSION_MINOR 13
#define DRFLAC_VERSION_REVISION 3 #define DRFLAC_VERSION_REVISION 4
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION) #define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
#include <stddef.h> /* For size_t. */ #include <stddef.h> /* For size_t. */
@ -1547,6 +1547,8 @@ static DRFLAC_INLINE drflac_bool32 drflac_has_sse41(void)
#define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p))) #define DRFLAC_ZERO_OBJECT(p) DRFLAC_ZERO_MEMORY((p), sizeof(*(p)))
#endif #endif
#define DRFLAC_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */ #define DRFLAC_MAX_SIMD_VECTOR_SIZE 64 /* 64 for AVX-512 in the future. */
/* Result Codes */ /* Result Codes */
@ -5980,8 +5982,6 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
break; /* Failed to seek to FLAC frame. */ break; /* Failed to seek to FLAC frame. */
} }
} else { } else {
const float approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0f);
if (pcmRangeLo > pcmFrameIndex) { if (pcmRangeLo > pcmFrameIndex) {
/* We seeked too far forward. We need to move our target byte backward and try again. */ /* We seeked too far forward. We need to move our target byte backward and try again. */
byteRangeHi = lastSuccessfulSeekOffset; byteRangeHi = lastSuccessfulSeekOffset;
@ -6004,12 +6004,14 @@ static drflac_bool32 drflac__seek_to_pcm_frame__binary_search_internal(drflac* p
break; /* Failed to seek to FLAC frame. */ break; /* Failed to seek to FLAC frame. */
} }
} else { } else {
const double approxCompressionRatio = (drflac_int64)(lastSuccessfulSeekOffset - pFlac->firstFLACFramePosInBytes) / ((drflac_int64)(pcmRangeLo * pFlac->channels * pFlac->bitsPerSample)/8.0);
byteRangeLo = lastSuccessfulSeekOffset; byteRangeLo = lastSuccessfulSeekOffset;
if (byteRangeHi < byteRangeLo) { if (byteRangeHi < byteRangeLo) {
byteRangeHi = byteRangeLo; byteRangeHi = byteRangeLo;
} }
targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0f) * approxCompressionRatio); targetByte = lastSuccessfulSeekOffset + (drflac_uint64)(((drflac_int64)((pcmFrameIndex-pcmRangeLo) * pFlac->channels * pFlac->bitsPerSample)/8.0) * approxCompressionRatio);
if (targetByte > byteRangeHi) { if (targetByte > byteRangeHi) {
targetByte = byteRangeHi; targetByte = byteRangeHi;
} }
@ -6402,7 +6404,7 @@ static void* drflac__realloc_from_callbacks(void* p, size_t szNew, size_t szOld,
} }
if (p != NULL) { if (p != NULL) {
DRFLAC_COPY_MEMORY(p2, p, szOld); DRFLAC_COPY_MEMORY(p2, p, DRFLAC_MIN(szNew, szOld));
pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData); pAllocationCallbacks->onFree(p, pAllocationCallbacks->pUserData);
} }
@ -6433,8 +6435,19 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
drflac_uint64 runningFilePos = 42; drflac_uint64 runningFilePos = 42;
drflac_uint64 seektablePos = 0; drflac_uint64 seektablePos = 0;
drflac_uint32 seektableSize = 0; drflac_uint32 seektableSize = 0;
drflac_int64 fileSize = 0;
drflac_bool32 hasKnownFileSize = DRFLAC_FALSE;
(void)onTell; /* We'll be doing some memory allocations here against untrusted data. We'll do a basic validation check that they don't exceed the size of the file. */
if (onTell != NULL && onSeek != NULL) {
if (onSeek(pUserData, 0, DRFLAC_SEEK_END)) {
if (onTell(pUserData, &fileSize)) {
hasKnownFileSize = DRFLAC_TRUE;
}
onSeek(pUserData, runningFilePos, DRFLAC_SEEK_SET);
}
}
for (;;) { for (;;) {
drflac_metadata metadata; drflac_metadata metadata;
@ -6444,6 +6457,11 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) { if (drflac__read_and_decode_block_header(onRead, pUserData, &isLastBlock, &blockType, &blockSize) == DRFLAC_FALSE) {
return DRFLAC_FALSE; return DRFLAC_FALSE;
} }
if (hasKnownFileSize && (blockSize > ((drflac_uint64)fileSize - runningFilePos))) {
return DRFLAC_FALSE; /* Block size exceeds the size of the file. */
}
runningFilePos += 4; runningFilePos += 4;
metadata.type = blockType; metadata.type = blockType;
@ -6747,13 +6765,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength); metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
if (blockSizeRemaining < metadata.data.picture.mimeLength) {
result = DRFLAC_FALSE;
goto done_flac;
}
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
if (pMime == NULL) { if (pMime == NULL) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) { if (onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
@ -6769,13 +6792,18 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
blockSizeRemaining -= 4; blockSizeRemaining -= 4;
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength); metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
if (blockSizeRemaining < metadata.data.picture.descriptionLength) {
result = DRFLAC_FALSE;
goto done_flac;
}
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */ pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
if (pDescription == NULL) { if (pDescription == NULL) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) { if (onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
result = DRFLAC_FALSE; result = DRFLAC_FALSE;
goto done_flac; goto done_flac;
} }
@ -8094,11 +8122,17 @@ static drflac* drflac_open_with_metadata_private(drflac_read_proc onRead, drflac
return NULL; return NULL;
} }
if ((0xFFFFFFFF - (seekpointCount * sizeof(drflac_seekpoint))) < allocationSize) {
#ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
#endif
return NULL;
}
allocationSize += seekpointCount * sizeof(drflac_seekpoint); allocationSize += seekpointCount * sizeof(drflac_seekpoint);
} }
pFlac = (drflac*)drflac__malloc_from_callbacks((size_t)allocationSize, &allocationCallbacks);
pFlac = (drflac*)drflac__malloc_from_callbacks(allocationSize, &allocationCallbacks);
if (pFlac == NULL) { if (pFlac == NULL) {
#ifndef DR_FLAC_NO_OGG #ifndef DR_FLAC_NO_OGG
drflac__free_from_callbacks(pOggbs, &allocationCallbacks); drflac__free_from_callbacks(pOggbs, &allocationCallbacks);
@ -12169,6 +12203,10 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.13.4 - TBD
- Add a bounds check when allocating memory during metadata processing.
- Fix a possible overflow error when parsing picture metadata.
v0.13.3 - 2026-01-17 v0.13.3 - 2026-01-17
- Fix a compiler compatibility issue with some inlined assembly. - Fix a compiler compatibility issue with some inlined assembly.
- Fix a compilation warning. - Fix a compilation warning.

View file

@ -3188,6 +3188,10 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8); pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
pTagData = pTagDataBeg; pTagData = pTagDataBeg;
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 8) {
goto done_xing_info; /* Frame too small for a Xing/Info tag. */
}
/* Check for both "Xing" and "Info" identifiers. */ /* Check for both "Xing" and "Info" identifiers. */
isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g'); isXing = (pTagData[0] == 'X' && pTagData[1] == 'i' && pTagData[2] == 'n' && pTagData[3] == 'g');
isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o'); isInfo = (pTagData[0] == 'I' && pTagData[1] == 'n' && pTagData[2] == 'f' && pTagData[3] == 'o');
@ -3199,33 +3203,52 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
pTagData += 8; /* Skip past the ID and flags. */ pTagData += 8; /* Skip past the ID and flags. */
if (flags & 0x01) { /* FRAMES flag. */ if (flags & 0x01) { /* FRAMES flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; detectedMP3FrameCount = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
pTagData += 4; pTagData += 4;
} }
if (flags & 0x02) { /* BYTES flag. */ if (flags & 0x02) { /* BYTES flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3]; bytes = (drmp3_uint32)pTagData[0] << 24 | (drmp3_uint32)pTagData[1] << 16 | (drmp3_uint32)pTagData[2] << 8 | (drmp3_uint32)pTagData[3];
(void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */ (void)bytes; /* <-- Just to silence a warning about `bytes` being assigned but unused. Want to leave this here in case I want to make use of it later. */
pTagData += 4; pTagData += 4;
} }
if (flags & 0x04) { /* TOC flag. */ if (flags & 0x04) { /* TOC flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 100) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
/* TODO: Extract and bind seek points. */ /* TODO: Extract and bind seek points. */
pTagData += 100; pTagData += 100;
} }
if (flags & 0x08) { /* SCALE flag. */ if (flags & 0x08) { /* SCALE flag. */
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 4) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
pTagData += 4; pTagData += 4;
} }
/* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */ /* At this point we're done with the Xing/Info header. Now we can look at the LAME data. */
if (pTagData[0]) { if (pTagData[0]) {
pTagData += 21;
if (pTagData - pFirstFrameData + 14 < firstFrameInfo.frame_bytes) {
int delayInPCMFrames; int delayInPCMFrames;
int paddingInPCMFrames; int paddingInPCMFrames;
if (firstFrameInfo.frame_bytes - (size_t)(pTagData - pFirstFrameData) < 36) {
goto done_xing_info; /* Invalid Xing/Info tag. */
}
pTagData += 21;
delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1); delayInPCMFrames = (( (drmp3_uint32)pTagData[0] << 4) | ((drmp3_uint32)pTagData[1] >> 4)) + (528 + 1);
paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1); paddingInPCMFrames = ((((drmp3_uint32)pTagData[1] & 0xF) << 8) | ((drmp3_uint32)pTagData[2] )) - (528 + 1);
if (paddingInPCMFrames < 0) { if (paddingInPCMFrames < 0) {
@ -3235,7 +3258,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames; pMP3->delayInPCMFrames = (drmp3_uint32)delayInPCMFrames;
pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames; pMP3->paddingInPCMFrames = (drmp3_uint32)paddingInPCMFrames;
} }
}
/* /*
My understanding is that if the "Xing" header is present we can consider this to be a VBR stream and if the "Info" header is My understanding is that if the "Xing" header is present we can consider this to be a VBR stream and if the "Info" header is
@ -3273,6 +3295,8 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
*/ */
drmp3dec_init(&pMP3->decoder); drmp3dec_init(&pMP3->decoder);
} }
done_xing_info:;
} else { } else {
/* Failed to read the side info. */ /* Failed to read the side info. */
} }
@ -3285,7 +3309,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
} }
if (detectedMP3FrameCount != 0xFFFFFFFF) { if (detectedMP3FrameCount != 0xFFFFFFFF) {
pMP3->totalPCMFrameCount = detectedMP3FrameCount * firstFramePCMFrameCount; pMP3->totalPCMFrameCount = (drmp3_uint64)detectedMP3FrameCount * firstFramePCMFrameCount;
} }
pMP3->channels = pMP3->mp3FrameChannels; pMP3->channels = pMP3->mp3FrameChannels;
@ -4247,7 +4271,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_f32(drmp3* pMP3, drmp3_uint64 frame
#else #else
/* Slow path. Convert from s16 to f32. */ /* Slow path. Convert from s16 to f32. */
{ {
drmp3_int16 pTempS16[8192]; drmp3_int16 pTempS16[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
drmp3_uint64 totalPCMFramesRead = 0; drmp3_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
@ -4284,7 +4308,7 @@ DRMP3_API drmp3_uint64 drmp3_read_pcm_frames_s16(drmp3* pMP3, drmp3_uint64 frame
#else #else
/* Slow path. Convert from f32 to s16. */ /* Slow path. Convert from f32 to s16. */
{ {
float pTempF32[4096]; float pTempF32[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
drmp3_uint64 totalPCMFramesRead = 0; drmp3_uint64 totalPCMFramesRead = 0;
while (totalPCMFramesRead < framesToRead) { while (totalPCMFramesRead < framesToRead) {
@ -4772,7 +4796,7 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
drmp3_uint64 totalFramesRead = 0; drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0; drmp3_uint64 framesCapacity = 0;
float* pFrames = NULL; float* pFrames = NULL;
float temp[4096]; float temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
DRMP3_ASSERT(pMP3 != NULL); DRMP3_ASSERT(pMP3 != NULL);
@ -4841,7 +4865,7 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
drmp3_uint64 totalFramesRead = 0; drmp3_uint64 totalFramesRead = 0;
drmp3_uint64 framesCapacity = 0; drmp3_uint64 framesCapacity = 0;
drmp3_int16* pFrames = NULL; drmp3_int16* pFrames = NULL;
drmp3_int16 temp[4096]; drmp3_int16 temp[1152*2]; /* MP3 frames have a maximum per-channel sample count of 1152. Times 2 to account for stereo. */
DRMP3_ASSERT(pMP3 != NULL); DRMP3_ASSERT(pMP3 != NULL);
@ -5010,6 +5034,9 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
REVISION HISTORY REVISION HISTORY
================ ================
v0.7.4 - TBD v0.7.4 - TBD
- Fix an overflow error with "Xing" and "Info" tag parsing.
- Add some validation checks for "Xing" and "Info" tag parsing.
- Reduce size of some stack allocations.
- Improvements to SIMD detection. - Improvements to SIMD detection.
v0.7.3 - 2026-01-17 v0.7.3 - 2026-01-17

View file

@ -1,6 +1,6 @@
/* /*
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file. WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
dr_wav - v0.14.5 - 2026-03-03 dr_wav - v0.14.6 - TBD
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -147,7 +147,7 @@ extern "C" {
#define DRWAV_VERSION_MAJOR 0 #define DRWAV_VERSION_MAJOR 0
#define DRWAV_VERSION_MINOR 14 #define DRWAV_VERSION_MINOR 14
#define DRWAV_VERSION_REVISION 5 #define DRWAV_VERSION_REVISION 6
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION) #define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
#include <stddef.h> /* For size_t. */ #include <stddef.h> /* For size_t. */
@ -1971,7 +1971,15 @@ DRWAV_PRIVATE drwav_result drwav__read_chunk_header(drwav_read_proc onRead, void
return DRWAV_INVALID_FILE; return DRWAV_INVALID_FILE;
} }
pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes) - 24; /* <-- Subtract 24 because w64 includes the size of the header. */ pHeaderOut->sizeInBytes = drwav_bytes_to_u64(sizeInBytes);
/* Subtract 24 from the size because with w64 the reported chunk size includes the size of the header itself. */
if (pHeaderOut->sizeInBytes >= 24) {
pHeaderOut->sizeInBytes -= 24;
} else {
return DRWAV_INVALID_FILE;
}
pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes); pHeaderOut->paddingSize = drwav__chunk_padding_size_w64(pHeaderOut->sizeInBytes);
*pRunningBytesReadOut += 24; *pRunningBytesReadOut += 24;
} else { } else {
@ -2201,7 +2209,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
so it's consistent with how we do it in the first stage. so it's consistent with how we do it in the first stage.
*/ */
loopCount = drwav_bytes_to_u32(smplHeaderData + 28); loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
if (loopCount != calculatedLoopCount) { if (loopCount != calculatedLoopCount) {
return totalBytesRead; return totalBytesRead;
} }
@ -2580,8 +2588,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_bext_to_metadata_obj(drwav__metadata_pars
pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1); pMetadata->data.bext.pCodingHistory = (char*)drwav__metadata_get_memory(pParser, extraBytes + 1, 1);
DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL); DRWAV_ASSERT(pMetadata->data.bext.pCodingHistory != NULL);
bytesRead += drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL); pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__metadata_parser_read(pParser, pMetadata->data.bext.pCodingHistory, extraBytes, NULL);
pMetadata->data.bext.codingHistorySize = (drwav_uint32)drwav__strlen(pMetadata->data.bext.pCodingHistory); pMetadata->data.bext.pCodingHistory[pMetadata->data.bext.codingHistorySize] = '\0'; /* <-- Explicit null terminator in case of a badly formed file. */
bytesRead += pMetadata->data.bext.codingHistorySize;
} else { } else {
pMetadata->data.bext.pCodingHistory = NULL; pMetadata->data.bext.pCodingHistory = NULL;
pMetadata->data.bext.codingHistorySize = 0; pMetadata->data.bext.codingHistorySize = 0;
@ -2755,10 +2765,10 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
drwav_uint32 loopCount = drwav_bytes_to_u32(buffer); drwav_uint32 loopCount = drwav_bytes_to_u32(buffer);
drwav_uint64 calculatedLoopCount; drwav_uint32 calculatedLoopCount;
/* The loop count must be validated against the size of the chunk. */ /* The loop count must be validated against the size of the chunk. */
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES; calculatedLoopCount = (drwav_uint32)((pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES);
if (calculatedLoopCount == loopCount) { if (calculatedLoopCount == loopCount) {
bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead); bytesJustRead = drwav__metadata_parser_read(pParser, buffer, sizeof(buffer), &bytesRead);
if (bytesJustRead == sizeof(buffer)) { if (bytesJustRead == sizeof(buffer)) {
@ -2860,7 +2870,9 @@ DRWAV_PRIVATE drwav_uint64 drwav__metadata_process_chunk(drwav__metadata_parser*
return bytesRead; return bytesRead;
} }
allocSizeNeeded += drwav__strlen(buffer) + 1; allocSizeNeeded += drwav__strlen(buffer) + 1;
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1; /* Coding history. */
/* Coding history. */
allocSizeNeeded += (size_t)pChunkHeader->sizeInBytes - DRWAV_BEXT_BYTES + 1;
drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1); drwav__metadata_request_extra_memory_for_stage_2(pParser, allocSizeNeeded, 1);
@ -3321,6 +3333,10 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) { ((pWav->container == drwav_container_w64) && drwav_guid_equal(header.id.guid, drwavGUID_W64_FMT))) {
drwav_uint8 fmtData[16]; drwav_uint8 fmtData[16];
if (header.sizeInBytes < sizeof(fmtData)) {
return DRWAV_FALSE; /* Invalid fmt chunk. */
}
foundChunk_fmt = DRWAV_TRUE; foundChunk_fmt = DRWAV_TRUE;
if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) { if (pWav->onRead(pWav->pUserData, fmtData, sizeof(fmtData)) != sizeof(fmtData)) {
@ -3833,6 +3849,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (6*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return DRWAV_FALSE; /* Invalid file. */
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
} }
if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) { if (pWav->translatedFormatTag == DR_WAVE_FORMAT_DVI_ADPCM) {
@ -3846,6 +3867,11 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
/* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */ /* We decode two samples per byte. There will be blockCount headers in the data chunk. This is enough to know how to calculate the total PCM frame count. */
totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels); totalBlockHeaderSizeInBytes = blockCount * (4*fmt.channels);
if (totalBlockHeaderSizeInBytes >= dataChunkSize) { /* <-- We'll be subtracting totalBlockHeaderSizeInBytes from dataChunkSize next so it must be validated. */
drwav_free(pWav->pMetadata, &pWav->allocationCallbacks);
return DRWAV_FALSE; /* Invalid file. */
}
pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels; pWav->totalPCMFrameCount = ((dataChunkSize - totalBlockHeaderSizeInBytes) * 2) / fmt.channels;
/* The header includes a decoded sample for each channel which acts as the initial predictor sample. */ /* The header includes a decoded sample for each channel which acts as the initial predictor sample. */
@ -6725,6 +6751,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s16(drwav_int16* pOut, const drwav_uint8* pIn,
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (drwav_int16)((drwav_int64)sample >> 48); *pOut++ = (drwav_int16)((drwav_int64)sample >> 48);
} }
@ -7166,6 +7196,10 @@ DRWAV_PRIVATE void drwav__pcm_to_f32(float* pOut, const drwav_uint8* pIn, size_t
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0); *pOut++ = (float)((drwav_int64)sample / 9223372036854775807.0);
} }
@ -7650,6 +7684,10 @@ DRWAV_PRIVATE void drwav__pcm_to_s32(drwav_int32* pOut, const drwav_uint8* pIn,
shift += 8; shift += 8;
} }
if (!drwav__is_little_endian()) {
sample = drwav__bswap64(sample);
}
pIn += j; pIn += j;
*pOut++ = (drwav_int32)((drwav_int64)sample >> 32); *pOut++ = (drwav_int32)((drwav_int64)sample >> 32);
} }
@ -8557,6 +8595,13 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
/* /*
REVISION HISTORY REVISION HISTORY
================ ================
v0.14.6 - TBD
- Fix an error when loading files with a malformed "bext" chunk.
- Fix an error when loading files with a malformed "fmt" chunk.
- Fix an underflow error with badly formed ADPCM encoded files.
- Fix an underflow error with badly formed W64 files.
- Fix an error when converting from >32 bit samples to s16/f32/s32 on big-endian architectures.
v0.14.5 - 2026-03-03 v0.14.5 - 2026-03-03
- Fix a crash when loading files with a malformed "smpl" chunk. - Fix a crash when loading files with a malformed "smpl" chunk.
- Fix a signed overflow bug with the MS-ADPCM decoder. - Fix a signed overflow bug with the MS-ADPCM decoder.

View file

@ -2,7 +2,7 @@
* *
* fix_win32_compatibility.h Utility to help include windows.h with raylib projects * fix_win32_compatibility.h Utility to help include windows.h with raylib projects
* *
* Useage: #include "fix_win32_compatibility.h" any library that uses windows.h * Usage: #include "fix_win32_compatibility.h" any library that uses windows.h
* order is critical, this must be done before raylib * order is critical, this must be done before raylib
* *
* LICENSE: MIT * LICENSE: MIT
@ -32,7 +32,7 @@
#pragma once #pragma once
// move the windows functions to new names // move the windows functions to new names
// note that you can't call these functions or structures from your code, but you should not neeed to // note that you can't call these functions or structures from your code, but you should not need to
#define CloseWindow CloseWindowWin32 #define CloseWindow CloseWindowWin32
#define Rectangle RectangleWin32 #define Rectangle RectangleWin32
#define ShowCursor ShowCursorWin32 #define ShowCursor ShowCursorWin32
@ -46,8 +46,9 @@
// include windows // include windows
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <playsoundapi.h>
// remove all our redfintions so that raylib can define them properly // remove all our redefinitions so that raylib can define them properly
#undef CloseWindow #undef CloseWindow
#undef Rectangle #undef Rectangle
#undef ShowCursor #undef ShowCursor

View file

@ -1,6 +1,8 @@
# Usage: # Usage:
# cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h> # cmake -P GenerateMappings.cmake <path/to/mappings.h.in> <path/to/mappings.h>
cmake_policy(VERSION 3.16)
set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt") set(source_url "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt")
set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt") set(source_path "${CMAKE_CURRENT_BINARY_DIR}/gamecontrollerdb.txt")
set(template_path "${CMAKE_ARGV3}") set(template_path "${CMAKE_ARGV3}")
@ -22,8 +24,9 @@ if (status_code)
endif() endif()
file(STRINGS "${source_path}" lines) file(STRINGS "${source_path}" lines)
foreach(line ${lines}) list(FILTER lines INCLUDE REGEX "^[0-9a-fA-F]")
if (line MATCHES "^[0-9a-fA-F]")
foreach(line IN LISTS lines)
if (line MATCHES "platform:Windows") if (line MATCHES "platform:Windows")
if (GLFW_WIN32_MAPPINGS) if (GLFW_WIN32_MAPPINGS)
string(APPEND GLFW_WIN32_MAPPINGS "\n") string(APPEND GLFW_WIN32_MAPPINGS "\n")
@ -40,7 +43,6 @@ foreach(line ${lines})
endif() endif()
string(APPEND GLFW_LINUX_MAPPINGS "\"${line}\",") string(APPEND GLFW_LINUX_MAPPINGS "\"${line}\",")
endif() endif()
endif()
endforeach() endforeach()
configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX) configure_file("${template_path}" "${target_path}" @ONLY NEWLINE_STYLE UNIX)

View file

@ -1,14 +1,6 @@
cmake_minimum_required(VERSION 3.4...3.28 FATAL_ERROR) cmake_minimum_required(VERSION 3.16...3.28 FATAL_ERROR)
project(GLFW VERSION 3.4.0 LANGUAGES C) project(GLFW VERSION 3.5.1 LANGUAGES C HOMEPAGE_URL "https://www.glfw.org/")
if (POLICY CMP0069)
cmake_policy(SET CMP0069 NEW)
endif()
if (POLICY CMP0077)
cmake_policy(SET CMP0077 NEW)
endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -46,11 +38,7 @@ set(GLFW_LIBRARY_TYPE "${GLFW_LIBRARY_TYPE}" CACHE STRING
"Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)") "Library type override for GLFW (SHARED, STATIC, OBJECT, or empty to follow BUILD_SHARED_LIBS)")
if (GLFW_LIBRARY_TYPE) if (GLFW_LIBRARY_TYPE)
if (GLFW_LIBRARY_TYPE STREQUAL "SHARED") string(COMPARE EQUAL "${GLFW_LIBRARY_TYPE}" "SHARED" GLFW_BUILD_SHARED_LIBRARY)
set(GLFW_BUILD_SHARED_LIBRARY TRUE)
else()
set(GLFW_BUILD_SHARED_LIBRARY FALSE)
endif()
else() else()
set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) set(GLFW_BUILD_SHARED_LIBRARY ${BUILD_SHARED_LIBS})
endif() endif()
@ -80,24 +68,7 @@ endif()
# This is here because it also applies to tests and examples # This is here because it also applies to tests and examples
#-------------------------------------------------------------------- #--------------------------------------------------------------------
if (MSVC AND NOT USE_MSVC_RUNTIME_LIBRARY_DLL) if (MSVC AND NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
if (CMAKE_VERSION VERSION_LESS 3.15)
foreach (flag CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO)
if (flag MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
endif()
if (flag MATCHES "/MDd")
string(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
endif()
endforeach()
else()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif() endif()
#-------------------------------------------------------------------- #--------------------------------------------------------------------

View file

@ -6,10 +6,12 @@ excludes other invaluable contributions like language bindings and text and
video tutorials. video tutorials.
- Bobyshev Alexander - Bobyshev Alexander
- Alzathar
- Laurent Aphecetche - Laurent Aphecetche
- Matt Arsenault - Matt Arsenault
- Takuro Ashie - Takuro Ashie
- ashishgamedev - ashishgamedev
- avagordon01
- David Avedissian - David Avedissian
- Luca Bacci - Luca Bacci
- Keith Bauer - Keith Bauer
@ -23,6 +25,7 @@ video tutorials.
- Denis Bernard - Denis Bernard
- BiBi - BiBi
- Doug Binks - Doug Binks
- bitb4ker
- blanco - blanco
- Waris Boonyasiriwat - Waris Boonyasiriwat
- Kyle Brenneman - Kyle Brenneman
@ -33,6 +36,7 @@ video tutorials.
- Nicolas Caramelli - Nicolas Caramelli
- David Carlier - David Carlier
- Arturo Castro - Arturo Castro
- Jose Luis Cercós Pita
- Chi-kwan Chan - Chi-kwan Chan
- Victor Chernyakin - Victor Chernyakin
- TheChocolateOre - TheChocolateOre
@ -48,11 +52,15 @@ video tutorials.
- Andrew Corrigan - Andrew Corrigan
- Bailey Cosier - Bailey Cosier
- Noel Cower - Noel Cower
- James Cowgill
- CuriouserThing - CuriouserThing
- Bill Currie - Bill Currie
- Jason Daly - Jason Daly
- danhambleton - danhambleton
- danijel1023
- Jarrod Davis - Jarrod Davis
- Aaron Day
- decce
- Olivier Delannoy - Olivier Delannoy
- Paul R. Deppe - Paul R. Deppe
- Michael Dickens - Michael Dickens
@ -65,14 +73,18 @@ video tutorials.
- Robin Eklind - Robin Eklind
- Jan Ekström - Jan Ekström
- Siavash Eliasi - Siavash Eliasi
- er-azh
- Jan Hendrik Farr
- Ahmad Fatoum - Ahmad Fatoum
- Nikita Fediuchin - Nikita Fediuchin
- Felipe Ferreira - Felipe Ferreira
- Michael Fogleman - Michael Fogleman
- Folling
- forworldm - forworldm
- Jason Francis - Jason Francis
- Gerald Franz - Gerald Franz
- Mário Freitas - Mário Freitas
- Friz64
- GeO4d - GeO4d
- Marcus Geelnard - Marcus Geelnard
- Gegy - Gegy
@ -88,6 +100,7 @@ video tutorials.
- Andrew Gutekanst - Andrew Gutekanst
- Stephen Gutekanst - Stephen Gutekanst
- Jonathan Hale - Jonathan Hale
- halx99
- Daniel Hauser - Daniel Hauser
- hdf89shfdfs - hdf89shfdfs
- Moritz Heinemann - Moritz Heinemann
@ -118,6 +131,7 @@ video tutorials.
- Josh Kilmer - Josh Kilmer
- Byunghoon Kim - Byunghoon Kim
- Cameron King - Cameron King
- knokko
- Peter Knut - Peter Knut
- Christoph Kubisch - Christoph Kubisch
- Yuri Kunde Schlesner - Yuri Kunde Schlesner
@ -153,8 +167,10 @@ video tutorials.
- Bryce Mehring - Bryce Mehring
- Jonathan Mercier - Jonathan Mercier
- Marcel Metz - Marcel Metz
- Lucas Michaudel
- Liam Middlebrook - Liam Middlebrook
- mightgoyardstill - mightgoyardstill
- Mihail
- Ave Milia - Ave Milia
- Icyllis Milica - Icyllis Milica
- Jonathan Miller - Jonathan Miller
@ -168,6 +184,7 @@ video tutorials.
- Jon Morton - Jon Morton
- Pierre Moulon - Pierre Moulon
- Martins Mozeiko - Martins Mozeiko
- Tomáš Mráz
- Pascal Muetschard - Pascal Muetschard
- James Murphy - James Murphy
- Julian Møller - Julian Møller
@ -214,6 +231,7 @@ video tutorials.
- Philip Rideout - Philip Rideout
- Eddie Ringle - Eddie Ringle
- Max Risuhin - Max Risuhin
- road2react
- Joe Roback - Joe Roback
- Jorge Rodriguez - Jorge Rodriguez
- Jari Ronkainen - Jari Ronkainen
@ -221,12 +239,13 @@ video tutorials.
- Ed Ropple - Ed Ropple
- Aleksey Rybalkin - Aleksey Rybalkin
- Mikko Rytkönen - Mikko Rytkönen
- saikyun
- Riku Salminen - Riku Salminen
- Yoshinori Sano - Yoshinori Sano
- Brandon Schaefer - Brandon Schaefer
- Sebastian Schuberth - Sebastian Schuberth
- Scr3amer - Scr3amer
- Jan Schuerkamp - Jan Schürkamp
- Christian Sdunek - Christian Sdunek
- Matt Sealey - Matt Sealey
- Steve Sexton - Steve Sexton
@ -275,10 +294,12 @@ video tutorials.
- Corentin Wallez - Corentin Wallez
- Torsten Walluhn - Torsten Walluhn
- Patrick Walton - Patrick Walton
- Ivor Wanders
- Jim Wang - Jim Wang
- Xo Wang - Xo Wang
- Andre Weissflog - Andre Weissflog
- Jay Weisskopf - Jay Weisskopf
- Drew Weymouth
- Frank Wille - Frank Wille
- Andy Williams - Andy Williams
- Joel Winarske - Joel Winarske

View file

@ -1,18 +1,198 @@
# GLFW (modified for raylib) # GLFW
This directory contains a modification of GLFW, whose official website and [![Build status](https://github.com/glfw/glfw/actions/workflows/build.yml/badge.svg)](https://github.com/glfw/glfw/actions)
upstream repository are https://glfw.org and https://github.com/glfw/glfw, [![Build status](https://ci.appveyor.com/api/projects/status/0kf0ct9831i5l6sp/branch/master?svg=true)](https://ci.appveyor.com/project/elmindreda/glfw)
respectively.
In this modification, some static functions sharing the same name in different ## Introduction
platforms have been renamed so all of GLFW's source files can be combined into
one (as done by ``rglfw.c``). Also, the Null platform, which is not used by
raylib, has been disabled. The renamed functions are:
`` GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
createKeyTables() application development. It provides a simple, platform-independent API for
translateKey() creating windows, contexts and surfaces, reading input, handling events, etc.
acquireMonitor()
releaseMonitor() GLFW is written primarily in C99, with parts of macOS support being written in
`` Objective-C.
GLFW supports Windows, macOS and Linux, and also works on many other Unix-like
systems. On Linux both Wayland and X11 are supported.
GLFW is licensed under the [zlib/libpng
license](https://www.glfw.org/license.html).
You can [download](https://www.glfw.org/download.html) the latest stable release
as source or Windows and macOS binaries. There are [release
tags](https://github.com/glfw/glfw/releases) with source and binary archives
attached for every version since 3.0.
The [documentation](https://www.glfw.org/docs/latest/) is available online and is
also included in source and binary archives, except those generated
automatically by Github. The documentation contains guides, a tutorial and the
API reference. The [release
notes](https://www.glfw.org/docs/latest/news.html) list the new features,
caveats and deprecations in the latest release. The [version
history](https://www.glfw.org/changelog.html) lists every user-visible change
for every release.
GLFW exists because of the contributions of [many people](CONTRIBUTORS.md)
around the world, whether by reporting bugs, providing community support, adding
features, reviewing or testing code, debugging, proofreading docs, suggesting
features or fixing bugs.
## System requirements
GLFW supports Windows 7 and later and macOS 10.11 and later. On GNOME Wayland,
window decorations will be very basic unless the
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) package is
installed. Linux and other Unix-like systems running X11 are supported even
without a desktop environment or modern extensions, although some features
require a clipboard manager or a modern window manager.
See the [compatibility guide](https://www.glfw.org/docs/latest/compat.html)
for more detailed information.
## Compiling GLFW
GLFW supports compilation with Visual C++ (2013 and later), GCC and Clang. Both
Clang-CL and MinGW-w64 are supported. Other C99 compilers will likely also
work, but this is not regularly tested.
There are [pre-compiled binaries](https://www.glfw.org/download.html)
available for Windows and macOS.
GLFW itself needs only CMake and the headers and libraries for your operating
system and window system. No other SDKs are required.
See the [compilation guide](https://www.glfw.org/docs/latest/compile.html) for
more information about compiling GLFW and the exact dependencies required for
each window system.
The examples and test programs depend on a number of tiny libraries. These are
bundled in the `deps/` directory. The repository has no submodules.
- [getopt\_port](https://github.com/kimgr/getopt_port/) for examples
with command-line options
- [TinyCThread](https://github.com/tinycthread/tinycthread) for threaded
examples
- [glad2](https://github.com/Dav1dde/glad) for loading OpenGL and Vulkan
functions
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
examples
- [Nuklear](https://github.com/Immediate-Mode-UI/Nuklear) for test and example UI
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
The documentation is generated with [Doxygen](https://doxygen.org/) when the
library is built, provided CMake could find a sufficiently new version of it
during configuration.
## Using GLFW
See the [HTML documentation](https://www.glfw.org/docs/latest/) for a tutorial,
guides and the API reference.
## Contributing to GLFW
See the [contribution
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
more information.
The `master` branch is the stable integration branch and _should_ always compile
and run on all supported platforms. Details of a newly added feature,
including the public API, may change until it has been included in a release.
The `latest` branch is equivalent to the [highest numbered](https://semver.org/)
release, although it may not always point to the same commit as the tag for that
release.
The `ci` branch is used to trigger continuous integration jobs for code under
testing and should never be relied on for any purpose.
## Reporting bugs
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
Please check the [contribution
guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
information on what to include when reporting a bug.
## Changelog since 3.5
None.
## Changelog since 3.4
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
the limit of the mouse button tokens to be reported (#2423)
- Added `glfwGetEGLConfig` function to query the `EGLConfig` of a window (#2045)
- Added `glfwGetGLXFBConfig` function to query the `GLXFBConfig` of a window (#1925)
- Updated minimum CMake version to 3.16 (#2541)
- Removed support for building with original MinGW (#2540)
- [Win32] Removed support for Windows XP and Vista (#2505)
- [Win32] Bugfix: Media keys were reported with a scancode of 256 (#1768,#2417,#2625)
- [Cocoa] Added `QuartzCore` framework as link-time dependency
- [Cocoa] Removed support for OS X 10.10 Yosemite and earlier (#2506)
- [Cocoa] Bugfix: Cmd+Period, Ctrl+Tab and Ctrl+Esc key events were not emitted
(#1362,#2278)
- [Wayland] Bugfix: The fractional scaling related objects were not destroyed
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
fallback decorations
- [Wayland] Bugfix: Fallback decorations would report scroll events
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
- [Wayland] Bugfix: Fallback decorations would show menu at wrong position
- [Wayland] Bugfix: The cursor was not updated when clicking through from
a modal to a fallback decoration
- [Wayland] Bugfix: The cursor position was not updated when clicking through
from a modal to the content area
- [Wayland] Bugfix: free modules at end of terminate function to resolve
potential segmentation fault (#2744)
- [Wayland] Bugfix: Confining or disabling the cursor could segfault on
compositors without `pointer-constraints-unstable-v1`
- [Wayland] Bugfix: Key repeat did not function on very old compositors
- [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination
- [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494)
- [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes
- [Wayland] Bugfix: Mouse wheel scroll distance was incorrect on some compositors
- [Wayland] Bugfix: `glfwSwapBuffers` would halt with nonzero swap interval when window
was suspended (#1350,#2582,#2640,#2719,#2723,#2800,#2827)
- [Wayland] Bugfix: `glfwPostEmptyEvent` would leak a callback proxy (#2836)
- [Wayland] Bugfix: `glfwHideWindow` did not always send its request immediately
- [Wayland] Bugfix: Some event types were not always processed by `glfwPollEvents` or
`glfwWait*Events` (#2793,#2795)
- [Wayland] Bugfix: Scaled framebuffer size was sometimes incorect (#2713,#2810)
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
less than 1 (#2754)
- [X11] Bugfix: Clamp width and height to >= 1 to prevent BadValue error and app exit
- [X11] Bugfix: Floating windows silently became non-floating when hidden (#2276)
- [X11] Bugfix: The `libXext` library was not unloaded at termination
- [Linux] Bugfix: The header for `ioctl` was only implicitly included (#2778)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
- [EGL] Allowed native access on Wayland with `GLFW_CONTEXT_CREATION_API` set to
`GLFW_NATIVE_CONTEXT_API` (#2518)
## Contact
On [glfw.org](https://www.glfw.org/) you can find the latest version of GLFW, as
well as news, documentation and other information about the project.
If you have questions related to the use of GLFW, we have a
[forum](https://discourse.glfw.org/).
If you have a bug to report, a patch to submit or a feature you'd like to
request, please file it in the
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
Finally, if you're interested in helping out with the development of GLFW or
porting it to your favorite platform, join us on the forum or GitHub.

View file

@ -1,5 +1,5 @@
/************************************************************************* /*************************************************************************
* GLFW 3.4 - www.glfw.org * GLFW 3.5 - www.glfw.org
* A library for OpenGL, window and input * A library for OpenGL, window and input
*------------------------------------------------------------------------ *------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard * Copyright (c) 2002-2006 Marcus Geelnard
@ -291,14 +291,14 @@ extern "C" {
* features are added to the API but it remains backward-compatible. * features are added to the API but it remains backward-compatible.
* @ingroup init * @ingroup init
*/ */
#define GLFW_VERSION_MINOR 4 #define GLFW_VERSION_MINOR 5
/*! @brief The revision number of the GLFW header. /*! @brief The revision number of the GLFW header.
* *
* The revision number of the GLFW header. This is incremented when a bug fix * The revision number of the GLFW header. This is incremented when a bug fix
* release is made that does not contain any API changes. * release is made that does not contain any API changes.
* @ingroup init * @ingroup init
*/ */
#define GLFW_VERSION_REVISION 0 #define GLFW_VERSION_REVISION 1
/*! @} */ /*! @} */
/*! @brief One. /*! @brief One.
@ -1154,6 +1154,7 @@ extern "C" {
#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 #define GLFW_STICKY_MOUSE_BUTTONS 0x00033003
#define GLFW_LOCK_KEY_MODS 0x00033004 #define GLFW_LOCK_KEY_MODS 0x00033004
#define GLFW_RAW_MOUSE_MOTION 0x00033005 #define GLFW_RAW_MOUSE_MOTION 0x00033005
#define GLFW_UNLIMITED_MOUSE_BUTTONS 0x00033006
#define GLFW_CURSOR_NORMAL 0x00034001 #define GLFW_CURSOR_NORMAL 0x00034001
#define GLFW_CURSOR_HIDDEN 0x00034002 #define GLFW_CURSOR_HIDDEN 0x00034002
@ -1227,13 +1228,13 @@ extern "C" {
* The top-left to bottom-right diagonal resize/move shape. This is usually * The top-left to bottom-right diagonal resize/move shape. This is usually
* a diagonal double-headed arrow. * a diagonal double-headed arrow.
* *
* @note @macos This shape is provided by a private system API and may fail * @note __macOS:__ This shape is provided by a private system API and may fail
* with @ref GLFW_CURSOR_UNAVAILABLE in the future. * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_RESIZE_NWSE_CURSOR 0x00036007 #define GLFW_RESIZE_NWSE_CURSOR 0x00036007
@ -1242,13 +1243,13 @@ extern "C" {
* The top-right to bottom-left diagonal resize/move shape. This is usually * The top-right to bottom-left diagonal resize/move shape. This is usually
* a diagonal double-headed arrow. * a diagonal double-headed arrow.
* *
* @note @macos This shape is provided by a private system API and may fail * @note __macOS:__ This shape is provided by a private system API and may fail
* with @ref GLFW_CURSOR_UNAVAILABLE in the future. * with @ref GLFW_CURSOR_UNAVAILABLE in the future.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_RESIZE_NESW_CURSOR 0x00036008 #define GLFW_RESIZE_NESW_CURSOR 0x00036008
@ -1263,10 +1264,10 @@ extern "C" {
* The operation-not-allowed shape. This is usually a circle with a diagonal * The operation-not-allowed shape. This is usually a circle with a diagonal
* line through it. * line through it.
* *
* @note @wayland This shape is provided by a newer standard not supported by * @note __Wayland:__ This shape is provided by a newer standard not supported by
* all cursor themes. * all cursor themes.
* *
* @note @x11 This shape is provided by a newer standard not supported by all * @note __X11:__ This shape is provided by a newer standard not supported by all
* cursor themes. * cursor themes.
*/ */
#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A #define GLFW_NOT_ALLOWED_CURSOR 0x0003600A
@ -1343,6 +1344,10 @@ extern "C" {
#define GLFW_PLATFORM_NULL 0x00060005 #define GLFW_PLATFORM_NULL 0x00060005
/*! @} */ /*! @} */
/* Reserved platform define for external Emscripten ports: 0x00060006
* See https://github.com/pongasoft/emscripten-glfw
*/
#define GLFW_DONT_CARE -1 #define GLFW_DONT_CARE -1
@ -1628,7 +1633,7 @@ typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos);
* @sa @ref glfwSetWindowSizeCallback * @sa @ref glfwSetWindowSizeCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1648,7 +1653,7 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height);
* @sa @ref glfwSetWindowCloseCallback * @sa @ref glfwSetWindowCloseCallback
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1668,7 +1673,7 @@ typedef void (* GLFWwindowclosefun)(GLFWwindow* window);
* @sa @ref glfwSetWindowRefreshCallback * @sa @ref glfwSetWindowRefreshCallback
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -1799,7 +1804,7 @@ typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, flo
* @sa @ref glfwSetMouseButtonCallback * @sa @ref glfwSetMouseButtonCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle and modifier mask parameters. * __GLFW 3:__ Added window handle and modifier mask parameters.
* *
* @ingroup input * @ingroup input
*/ */
@ -1890,7 +1895,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffse
* @sa @ref glfwSetKeyCallback * @sa @ref glfwSetKeyCallback
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle, scancode and modifier mask parameters. * __GLFW 3:__ Added window handle, scancode and modifier mask parameters.
* *
* @ingroup input * @ingroup input
*/ */
@ -1911,7 +1916,7 @@ typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int actio
* @sa @ref glfwSetCharCallback * @sa @ref glfwSetCharCallback
* *
* @since Added in version 2.4. * @since Added in version 2.4.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -2019,7 +2024,7 @@ typedef void (* GLFWjoystickfun)(int jid, int event);
* @sa @ref glfwGetVideoModes * @sa @ref glfwGetVideoModes
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added refresh rate member. * __GLFW 3:__ Added refresh rate member.
* *
* @ingroup monitor * @ingroup monitor
*/ */
@ -2082,7 +2087,7 @@ typedef struct GLFWgammaramp
* @sa @ref window_icon * @sa @ref window_icon
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Removed format and bytes-per-pixel members. * __GLFW 3:__ Removed format and bytes-per-pixel members.
* *
* @ingroup window * @ingroup window
*/ */
@ -2182,12 +2187,12 @@ typedef struct GLFWallocator
* @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos This function will change the current directory of the * @remark __macOS:__ This function will change the current directory of the
* application to the `Contents/Resources` subdirectory of the application's * application to the `Contents/Resources` subdirectory of the application's
* bundle, if present. This can be disabled with the @ref * bundle, if present. This can be disabled with the @ref
* GLFW_COCOA_CHDIR_RESOURCES init hint. * GLFW_COCOA_CHDIR_RESOURCES init hint.
* *
* @remark @macos This function will create the main menu and dock icon for the * @remark __macOS:__ This function will create the main menu and dock icon for the
* application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to * application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to
* contain a menu bar. Otherwise a minimal menu bar is created manually with * contain a menu bar. Otherwise a minimal menu bar is created manually with
* common commands like Hide, Quit and About. The About entry opens a minimal * common commands like Hide, Quit and About. The About entry opens a minimal
@ -2202,7 +2207,7 @@ typedef struct GLFWallocator
* to something other than `wayland` or `x11`, the regular detection mechanism * to something other than `wayland` or `x11`, the regular detection mechanism
* will be used instead. * will be used instead.
* *
* @remark @x11 This function will set the `LC_CTYPE` category of the * @remark __X11:__ This function will set the `LC_CTYPE` category of the
* application locale according to the current environment if that category is * application locale according to the current environment if that category is
* still "C". This is because the "C" locale breaks Unicode text input. * still "C". This is because the "C" locale breaks Unicode text input.
* *
@ -2678,7 +2683,7 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos,
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @win32 On Windows 8 and earlier the physical size is calculated from * @remark __Win32:__ On Windows 8 and earlier the physical size is calculated from
* the current resolution and system DPI instead of querying the monitor EDID data. * the current resolution and system DPI instead of querying the monitor EDID data.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -2712,7 +2717,7 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Fractional scaling information is not yet available for * @remark __Wayland:__ Fractional scaling information is not yet available for
* monitors, so this function only returns integer content scales. * monitors, so this function only returns integer content scales.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -2860,7 +2865,7 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback);
* @sa @ref glfwGetVideoMode * @sa @ref glfwGetVideoMode
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Changed to return an array of modes for a specific monitor. * __GLFW 3:__ Changed to return an array of modes for a specific monitor.
* *
* @ingroup monitor * @ingroup monitor
*/ */
@ -2914,8 +2919,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE, * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
* @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -2938,8 +2943,8 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* returning `NULL`. * returning `NULL`.
* *
* @pointer_lifetime The returned structure and its arrays are allocated and * @pointer_lifetime The returned structure and its arrays are allocated and
@ -2980,10 +2985,10 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @remark The size of the specified gamma ramp should match the size of the * @remark The size of the specified gamma ramp should match the size of the
* current ramp for that monitor. * current ramp for that monitor.
* *
* @remark @win32 The gamma ramp size must be 256. * @remark __Win32:__ The gamma ramp size must be 256.
* *
* @remark @wayland Gamma handling is a privileged protocol, this function * @remark __Wayland:__ Monitor gamma is a privileged protocol, so this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE. * cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @pointer_lifetime The specified gamma ramp is copied before this function * @pointer_lifetime The specified gamma ramp is copied before this function
* returns. * returns.
@ -3158,32 +3163,32 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @win32 Window creation will fail if the Microsoft GDI software * @remark __Win32:__ Window creation will fail if the Microsoft GDI software
* OpenGL implementation is the only one available. * OpenGL implementation is the only one available.
* *
* @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it * @remark __Win32:__ If the executable has an icon resource named `GLFW_ICON,` it
* will be set as the initial icon for the window. If no such icon is present, * will be set as the initial icon for the window. If no such icon is present,
* the `IDI_APPLICATION` icon will be used instead. To set a different icon, * the `IDI_APPLICATION` icon will be used instead. To set a different icon,
* see @ref glfwSetWindowIcon. * see @ref glfwSetWindowIcon.
* *
* @remark @win32 The context to share resources with must not be current on * @remark __Win32:__ The context to share resources with must not be current on
* any other thread. * any other thread.
* *
* @remark @macos The OS only supports core profile contexts for OpenGL * @remark __macOS:__ The OS only supports core profile contexts for OpenGL
* versions 3.2 and later. Before creating an OpenGL context of version 3.2 or * versions 3.2 and later. Before creating an OpenGL context of version 3.2 or
* later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) * later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint)
* hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all * hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all
* on macOS. * on macOS.
* *
* @remark @macos The GLFW window has no icon, as it is not a document * @remark __macOS:__ The GLFW window has no icon, as it is not a document
* window, but the dock icon will be the same as the application bundle's icon. * window, but the dock icon will be the same as the application bundle's icon.
* For more information on bundles, see the * For more information on bundles, see the
* [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
* *
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
* *
* @remark @macos On OS X 10.10 and later the window frame will not be rendered * @remark __macOS:__ The window frame will not be rendered at full resolution
* at full resolution on Retina displays unless the * on Retina displays unless the
* [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint)
* hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
* application bundle's `Info.plist`. For more information, see * application bundle's `Info.plist`. For more information, see
@ -3194,11 +3199,11 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html * [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
* *
* @remark @macos When activating frame autosaving with * @remark __macOS:__ When activating frame autosaving with
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
* window size and position may be overridden by previously saved values. * window size and position may be overridden by previously saved values.
* *
* @remark @wayland GLFW uses [libdecor][] where available to create its window * @remark __Wayland:__ GLFW uses [libdecor][] where available to create its window
* decorations. This in turn uses server-side XDG decorations where available * decorations. This in turn uses server-side XDG decorations where available
* and provides high quality client-side decorations on compositors like GNOME. * and provides high quality client-side decorations on compositors like GNOME.
* If both XDG decorations and libdecor are unavailable, GLFW falls back to * If both XDG decorations and libdecor are unavailable, GLFW falls back to
@ -3207,15 +3212,15 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor * [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor
* *
* @remark @x11 Some window managers will not respect the placement of * @remark __X11:__ Some window managers will not respect the placement of
* initially hidden windows. * initially hidden windows.
* *
* @remark @x11 Due to the asynchronous nature of X11, it may take a moment for * @remark __X11:__ Due to the asynchronous nature of X11, it may take a moment for
* a window to reach its requested state. This means you may not be able to * a window to reach its requested state. This means you may not be able to
* query the final size, position or other attributes directly after window * query the final size, position or other attributes directly after window
* creation. * creation.
* *
* @remark @x11 The class part of the `WM_CLASS` window property will by * @remark __X11:__ The class part of the `WM_CLASS` window property will by
* default be set to the window title passed to this function. The instance * default be set to the window title passed to this function. The instance
* part will use the contents of the `RESOURCE_NAME` environment variable, if * part will use the contents of the `RESOURCE_NAME` environment variable, if
* present and not empty, or fall back to the window title. Set the * present and not empty, or fall back to the window title. Set the
@ -3348,7 +3353,7 @@ GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos The window title will not be updated until the next time you * @remark __macOS:__ The window title will not be updated until the next time you
* process events. * process events.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3357,7 +3362,7 @@ GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window);
* @sa @ref glfwGetWindowTitle * @sa @ref glfwGetWindowTitle
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3391,14 +3396,14 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
* @pointer_lifetime The specified image data is copied before this function * @pointer_lifetime The specified image data is copied before this function
* returns. * returns.
* *
* @remark @macos Regular windows do not have icons on macOS. This function * @remark __macOS:__ Regular windows do not have icons on macOS. This function
* will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as * will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as
* the application bundle's icon. For more information on bundles, see the * the application bundle's icon. For more information on bundles, see the
* [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library.
* *
* [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/
* *
* @remark @wayland There is no existing protocol to change an icon, the * @remark __Wayland:__ There is no existing protocol to change an icon, the
* window will thus inherit the one defined in the application's desktop file. * window will thus inherit the one defined in the application's desktop file.
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE. * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
@ -3429,8 +3434,8 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way for an application to retrieve the global * @remark __Wayland:__ Window positions are not currently part of any common
* position of its windows. This function will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3463,8 +3468,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way for an application to set the global * @remark __Wayland:__ Window positions are not currently part of any common
* position of its windows. This function will emit @ref * Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE. * GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3473,7 +3478,7 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @sa @ref glfwGetWindowPos * @sa @ref glfwGetWindowPos
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3503,7 +3508,7 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
* @sa @ref glfwSetWindowSize * @sa @ref glfwSetWindowSize
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3538,7 +3543,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
* @remark If you set size limits and an aspect ratio that conflict, the * @remark If you set size limits and an aspect ratio that conflict, the
* results are undefined. * results are undefined.
* *
* @remark @wayland The size limits will not be applied until the window is * @remark __Wayland:__ The size limits will not be applied until the window is
* actually resized, either by the user or by the compositor. * actually resized, either by the user or by the compositor.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3581,7 +3586,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
* @remark If you set size limits and an aspect ratio that conflict, the * @remark If you set size limits and an aspect ratio that conflict, the
* results are undefined. * results are undefined.
* *
* @remark @wayland The aspect ratio will not be applied until the window is * @remark __Wayland:__ The aspect ratio will not be applied until the window is
* actually resized, either by the user or by the compositor. * actually resized, either by the user or by the compositor.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3627,7 +3632,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
* @sa @ref glfwSetWindowMonitor * @sa @ref glfwSetWindowMonitor
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3777,7 +3782,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland There is no way to set an opacity factor for a window. * @remark __Wayland:__ There is no way to set an opacity factor for a window.
* This function will emit @ref GLFW_FEATURE_UNAVAILABLE. * This function will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3806,10 +3811,6 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Once a window is iconified, @ref glfwRestoreWindow won’t
* be able to restore it. This is a design decision of the xdg-shell
* protocol.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify
@ -3817,7 +3818,7 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* @sa @ref glfwMaximizeWindow * @sa @ref glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3837,6 +3838,10 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark __Wayland:__ Restoring a window from maximization is not currently
* part of any common Wayland protocol, so this function can only restore
* windows from maximization.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify
@ -3844,7 +3849,7 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @sa @ref glfwMaximizeWindow * @sa @ref glfwMaximizeWindow
* *
* @since Added in version 2.1. * @since Added in version 2.1.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -3891,7 +3896,7 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Because Wayland wants every frame of the desktop to be * @remark __Wayland:__ Because Wayland wants every frame of the desktop to be
* complete, this function does not immediately make the window visible. * complete, this function does not immediately make the window visible.
* Instead it will become visible the next time the window framebuffer is * Instead it will become visible the next time the window framebuffer is
* updated after this call. * updated after this call.
@ -3954,7 +3959,7 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland The compositor will likely ignore focus requests unless * @remark __Wayland:__ The compositor will likely ignore focus requests unless
* another window created by the same application already has input focus. * another window created by the same application already has input focus.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -3982,7 +3987,7 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @macos Attention is requested to the application as a whole, not the * @remark __macOS:__ Attention is requested to the application as a whole, not the
* specific window. * specific window.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4057,8 +4062,8 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* affected by any resizing or mode switching, although you may need to update * affected by any resizing or mode switching, although you may need to update
* your viewport if the framebuffer size has changed. * your viewport if the framebuffer size has changed.
* *
* @remark @wayland The desired window position is ignored, as there is no way * @remark __Wayland:__ Window positions are not currently part of any common
* for an application to set this property. * Wayland protocol. The window position arguments are ignored.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4095,8 +4100,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
* errors. However, this function should not fail as long as it is passed * errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init). * valid arguments and the library has been [initialized](@ref intro_init).
* *
* @remark @wayland The Wayland protocol provides no way to check whether a * @remark __Wayland:__ Checking whether a window is iconified is not currently
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`. * part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute
* cannot be implemented and is always `GLFW_FALSE`.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4138,7 +4144,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
* @remark Calling @ref glfwGetWindowAttrib will always return the latest * @remark Calling @ref glfwGetWindowAttrib will always return the latest
* value, even if that value is ignored by the current mode of the window. * value, even if that value is ignored by the current mode of the window.
* *
* @remark @wayland The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is * @remark __Wayland:__ The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is
* not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE. * not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4218,8 +4224,8 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @wayland This callback will never be called, as there is no way for * @remark __Wayland:__ This callback will not be called. The Wayland protocol
* an application to know its global position. * provides no way to be notified of when a window is moved.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
@ -4257,7 +4263,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
* @sa @ref window_size * @sa @ref window_size
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4289,7 +4295,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark @macos Selecting Quit from the application menu will trigger the * @remark __macOS:__ Selecting Quit from the application menu will trigger the
* close callback for all windows. * close callback for all windows.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -4297,7 +4303,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind
* @sa @ref window_close * @sa @ref window_close
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4333,7 +4339,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
* @sa @ref window_refresh * @sa @ref window_refresh
* *
* @since Added in version 2.5. * @since Added in version 2.5.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup window * @ingroup window
*/ */
@ -4394,6 +4400,10 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
* *
* @remark __Wayland:__ This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is iconified, and no way to
* check whether a window is currently iconified.
*
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
* *
* @sa @ref window_iconify * @sa @ref window_iconify
@ -4514,7 +4524,8 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
* GLFW will pass those events on to the application callbacks before * GLFW will pass those events on to the application callbacks before
* returning. * returning.
* *
* Event processing is not required for joystick input to work. * Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
@ -4559,7 +4570,8 @@ GLFWAPI void glfwPollEvents(void);
* GLFW will pass those events on to the application callbacks before * GLFW will pass those events on to the application callbacks before
* returning. * returning.
* *
* Event processing is not required for joystick input to work. * Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
@ -4606,7 +4618,8 @@ GLFWAPI void glfwWaitEvents(void);
* GLFW will pass those events on to the application callbacks before * GLFW will pass those events on to the application callbacks before
* returning. * returning.
* *
* Event processing is not required for joystick input to work. * Event processing is not required to receive joystick input. Joystick state
* is polled when a joystick input or gamepad input function is called.
* *
* @param[in] timeout The maximum amount of time, in seconds, to wait. * @param[in] timeout The maximum amount of time, in seconds, to wait.
* *
@ -4676,8 +4689,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
* *
* This function sets an input mode option for the specified window. The mode * This function sets an input mode option for the specified window. The mode
* must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
* @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS
* @ref GLFW_RAW_MOUSE_MOTION. * @ref GLFW_RAW_MOUSE_MOTION, or @ref GLFW_UNLIMITED_MOUSE_BUTTONS.
* *
* If the mode is `GLFW_CURSOR`, the value must be one of the following cursor * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor
* modes: * modes:
@ -4717,6 +4730,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
* attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref
* glfwRawMouseMotionSupported to check for support. * glfwRawMouseMotionSupported to check for support.
* *
* If the mode is `GLFW_UNLIMITED_MOUSE_BUTTONS`, the value must be either
* `GLFW_TRUE` to disable the mouse button limit when calling the mouse button
* callback, or `GLFW_FALSE` to limit the mouse buttons sent to the callback
* to the mouse button token values up to `GLFW_MOUSE_BUTTON_LAST`.
*
* @param[in] window The window whose input mode to set. * @param[in] window The window whose input mode to set.
* @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
* `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
@ -4894,7 +4912,7 @@ GLFWAPI int glfwGetKeyScancode(int key);
* @sa @ref input_key * @sa @ref input_key
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -4911,8 +4929,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* returns `GLFW_PRESS` the first time you call it for a mouse button that was * returns `GLFW_PRESS` the first time you call it for a mouse button that was
* pressed, even if that mouse button has already been released. * pressed, even if that mouse button has already been released.
* *
* The @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode does not effect the
* limit on buttons which can be polled with this function.
*
* @param[in] window The desired window. * @param[in] window The desired window.
* @param[in] button The desired [mouse button](@ref buttons). * @param[in] button The desired [mouse button token](@ref buttons).
* @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.
* *
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
@ -4923,7 +4944,7 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* @sa @ref input_mouse_button * @sa @ref input_mouse_button
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup input * @ingroup input
*/ */
@ -4993,7 +5014,7 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
* *
* @remark @wayland This function will only work when the cursor mode is * @remark __Wayland:__ This function will only work when the cursor mode is
* `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE. * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@ -5191,7 +5212,7 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);
* @sa @ref input_key * @sa @ref input_key
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5234,7 +5255,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback);
* @sa @ref input_char * @sa @ref input_char
* *
* @since Added in version 2.4. * @since Added in version 2.4.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5288,10 +5309,15 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods
* is called when a mouse button is pressed or released. * is called when a mouse button is pressed or released.
* *
* When a window loses input focus, it will generate synthetic mouse button * When a window loses input focus, it will generate synthetic mouse button
* release events for all pressed mouse buttons. You can tell these events * release events for all pressed mouse buttons with associated button tokens.
* from user-generated events by the fact that the synthetic ones are generated * You can tell these events from user-generated events by the fact that the
* after the focus loss event has been processed, i.e. after the * synthetic ones are generated after the focus loss event has been processed,
* [window focus callback](@ref glfwSetWindowFocusCallback) has been called. * i.e. after the [window focus callback](@ref glfwSetWindowFocusCallback) has
* been called.
*
* The reported `button` value can be higher than `GLFW_MOUSE_BUTTON_LAST` if
* the button does not have an associated [button token](@ref buttons) and the
* @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set.
* *
* @param[in] window The window whose callback to set. * @param[in] window The window whose callback to set.
* @param[in] callback The new callback, or `NULL` to remove the currently set * @param[in] callback The new callback, or `NULL` to remove the currently set
@ -5313,7 +5339,7 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmods
* @sa @ref input_mouse_button * @sa @ref input_mouse_button
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter and return value. * __GLFW 3:__ Added window handle parameter and return value.
* *
* @ingroup input * @ingroup input
*/ */
@ -5543,7 +5569,7 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
* @sa @ref joystick_button * @sa @ref joystick_button
* *
* @since Added in version 2.2. * @since Added in version 2.2.
* @glfw3 Changed to return a dynamic array. * __GLFW 3:__ Changed to return a dynamic array.
* *
* @ingroup input * @ingroup input
*/ */
@ -5907,7 +5933,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @win32 The clipboard on Windows has a single global lock for reading and * @remark __Win32:__ The clipboard on Windows has a single global lock for reading and
* writing. GLFW tries to acquire it a few times, which is almost always enough. If it * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
* cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
* It is safe to try this multiple times. * It is safe to try this multiple times.
@ -5940,7 +5966,7 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @win32 The clipboard on Windows has a single global lock for reading and * @remark __Win32:__ The clipboard on Windows has a single global lock for reading and
* writing. GLFW tries to acquire it a few times, which is almost always enough. If it * writing. GLFW tries to acquire it a few times, which is almost always enough. If it
* cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns.
* It is safe to try this multiple times. * It is safe to try this multiple times.
@ -6148,6 +6174,10 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
* *
* @remark __Wayland:__ When the swap interval is greater than zero and the
* window is not in view, this function may take a few extra milliseconds to
* return.
*
* @remark __EGL:__ The context of the specified window must be current on the * @remark __EGL:__ The context of the specified window must be current on the
* calling thread. * calling thread.
* *
@ -6157,7 +6187,7 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @sa @ref glfwSwapInterval * @sa @ref glfwSwapInterval
* *
* @since Added in version 1.0. * @since Added in version 1.0.
* @glfw3 Added window handle parameter. * __GLFW 3:__ Added window handle parameter.
* *
* @ingroup window * @ingroup window
*/ */
@ -6424,7 +6454,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @macos This function currently always returns `GLFW_TRUE`, as the * @remark __macOS:__ This function currently always returns `GLFW_TRUE`, as the
* `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide * `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide
* a `vkGetPhysicalDevice*PresentationSupport` type function. * a `vkGetPhysicalDevice*PresentationSupport` type function.
* *
@ -6482,15 +6512,15 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys
* @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should
* eliminate almost all occurrences of these errors. * eliminate almost all occurrences of these errors.
* *
* @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the * @remark __macOS:__ GLFW prefers the `VK_EXT_metal_surface` extension, with the
* `VK_MVK_macos_surface` extension as a fallback. The name of the selected * `VK_MVK_macos_surface` extension as a fallback. The name of the selected
* extension, if any, is included in the array returned by @ref * extension, if any, is included in the array returned by @ref
* glfwGetRequiredInstanceExtensions. * glfwGetRequiredInstanceExtensions.
* *
* @remark @macos This function creates and sets a `CAMetalLayer` instance for * @remark __macOS:__ This function creates and sets a `CAMetalLayer` instance for
* the window content view, which is required for MoltenVK to function. * the window content view, which is required for MoltenVK to function.
* *
* @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, * @remark __X11:__ By default GLFW prefers the `VK_KHR_xcb_surface` extension,
* with the `VK_KHR_xlib_surface` extension as a fallback. You can make * with the `VK_KHR_xlib_surface` extension as a fallback. You can make
* `VK_KHR_xlib_surface` the preferred extension by setting the * `VK_KHR_xlib_surface` the preferred extension by setting the
* [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init

View file

@ -1,5 +1,5 @@
/************************************************************************* /*************************************************************************
* GLFW 3.4 - www.glfw.org * GLFW 3.5 - www.glfw.org
* A library for OpenGL, window and input * A library for OpenGL, window and input
*------------------------------------------------------------------------ *------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard * Copyright (c) 2002-2006 Marcus Geelnard
@ -478,6 +478,29 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
* @ingroup native * @ingroup native
*/ */
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
/*! @brief Retrieves the `GLXFBConfig` of the specified window's `GLXWindow`.
*
* @param[in] window The window whose `GLXWindow` to query.
* @param[out] config The `GLXFBConfig` of the window `GLXWindow`, if available.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_UNAVAILABLE.
*
* @remark `GLXFBConfig` is an opaque type. Unlike other GLFW functions, the
* @p config out parameter is not cleared on error, as core GLX does not define
* any invalid value.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.5
*
* @ingroup native
*/
GLFWAPI int glfwGetGLXFBConfig(GLFWwindow* window, GLXFBConfig* config);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) #if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
@ -586,6 +609,29 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
* @ingroup native * @ingroup native
*/ */
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
/*! @brief Retrieves the `EGLConfig` of the specified window's `EGLSurface`.
*
* @param[in] window The window whose `EGLSurface` to query.
* @param[out] config The `EGLConfig` of the window `EGLSurface`, if available.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_NO_WINDOW_CONTEXT.
*
* @remark `EGLConfig` is an opaque type. Unlike other GLFW functions, the @p
* config out parameter is not cleared on error, as core EGL does not define
* any invalid value.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.5.
*
* @ingroup native
*/
GLFWAPI int glfwGetEGLConfig(GLFWwindow* window, EGLConfig* config);
#endif #endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA) #if defined(GLFW_EXPOSE_NATIVE_OSMESA)

View file

@ -10,7 +10,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
# The time, thread and module code is shared between all backends on a given OS, # The time, thread and module code is shared between all backends on a given OS,
# including the null backend, which still needs those bits to be functional # including the null backend, which still needs those bits to be functional
if (APPLE) if (APPLE)
target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h target_sources(glfw PRIVATE macos_time.h macos_time.c posix_thread.h
posix_module.c posix_thread.c) posix_module.c posix_thread.c)
elseif (WIN32) elseif (WIN32)
target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c
@ -30,6 +30,7 @@ add_custom_target(update_mappings
set_target_properties(update_mappings PROPERTIES FOLDER "GLFW3") set_target_properties(update_mappings PROPERTIES FOLDER "GLFW3")
if (GLFW_BUILD_COCOA) if (GLFW_BUILD_COCOA)
enable_language(OBJC)
target_compile_definitions(glfw PRIVATE _GLFW_COCOA) target_compile_definitions(glfw PRIVATE _GLFW_COCOA)
target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h cocoa_init.m target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h cocoa_init.m
cocoa_joystick.m cocoa_monitor.m cocoa_window.m cocoa_joystick.m cocoa_monitor.m cocoa_window.m
@ -45,15 +46,15 @@ endif()
if (GLFW_BUILD_X11) if (GLFW_BUILD_X11)
target_compile_definitions(glfw PRIVATE _GLFW_X11) target_compile_definitions(glfw PRIVATE _GLFW_X11)
target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c target_sources(glfw PRIVATE x11_platform.h x11_init.c
x11_monitor.c x11_window.c xkb_unicode.c x11_monitor.c x11_window.c xkb_unicode.c
glx_context.c) glx_context.c)
endif() endif()
if (GLFW_BUILD_WAYLAND) if (GLFW_BUILD_WAYLAND)
target_compile_definitions(glfw PRIVATE _GLFW_WAYLAND) target_compile_definitions(glfw PRIVATE _GLFW_WAYLAND)
target_sources(glfw PRIVATE wl_platform.h xkb_unicode.h wl_init.c target_sources(glfw PRIVATE wl_platform.h wl_init.c
wl_monitor.c wl_window.c xkb_unicode.c) wl_monitor.c wl_window.c)
endif() endif()
if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
@ -137,13 +138,6 @@ target_include_directories(glfw PRIVATE
"${GLFW_BINARY_DIR}/src") "${GLFW_BINARY_DIR}/src")
target_link_libraries(glfw PRIVATE Threads::Threads) target_link_libraries(glfw PRIVATE Threads::Threads)
# Workaround for CMake not knowing about .m files before version 3.16
if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE)
set_source_files_properties(cocoa_init.m cocoa_joystick.m cocoa_monitor.m
cocoa_window.m nsgl_context.m PROPERTIES
LANGUAGE C)
endif()
if (GLFW_BUILD_WIN32) if (GLFW_BUILD_WIN32)
list(APPEND glfw_PKG_LIBS "-lgdi32") list(APPEND glfw_PKG_LIBS "-lgdi32")
endif() endif()
@ -151,10 +145,11 @@ endif()
if (GLFW_BUILD_COCOA) if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa" target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit" "-framework IOKit"
"-framework CoreFoundation") "-framework QuartzCore")
set(glfw_PKG_DEPS "") list(APPEND glfw_PKG_LIBS "-framework Cocoa"
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation") "-framework IOKit"
"-framework QuartzCore")
endif() endif()
if (GLFW_BUILD_WAYLAND) if (GLFW_BUILD_WAYLAND)
@ -239,6 +234,11 @@ if (UNIX AND NOT APPLE)
endif() endif()
endif() endif()
if (APPLE)
target_link_libraries(glfw PRIVATE "-framework CoreFoundation")
list(APPEND glfw_PKG_LIBS "-framework CoreFoundation")
endif()
if (WIN32) if (WIN32)
if (GLFW_USE_HYBRID_HPG) if (GLFW_USE_HYBRID_HPG)
target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG) target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG)
@ -260,24 +260,6 @@ if (GLFW_BUILD_WIN32)
target_compile_definitions(glfw PRIVATE UNICODE _UNICODE) target_compile_definitions(glfw PRIVATE UNICODE _UNICODE)
endif() endif()
# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
# the inclusion of stddef.h (by glfw3.h), which is itself included before
# win32_platform.h. We define them here until a saner solution can be found
# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
if (MINGW)
target_compile_definitions(glfw PRIVATE WINVER=0x0501)
endif()
# Workaround for legacy MinGW not providing XInput and DirectInput
if (MINGW)
include(CheckIncludeFile)
check_include_file(dinput.h DINPUT_H_FOUND)
check_include_file(xinput.h XINPUT_H_FOUND)
if (NOT DINPUT_H_FOUND OR NOT XINPUT_H_FOUND)
target_include_directories(glfw PRIVATE "${GLFW_SOURCE_DIR}/deps/mingw")
endif()
endif()
# Workaround for the MS CRT deprecating parts of the standard library # Workaround for the MS CRT deprecating parts of the standard library
if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC") if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC")
target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS) target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS)
@ -291,10 +273,6 @@ endif()
if (GLFW_BUILD_SHARED_LIBRARY) if (GLFW_BUILD_SHARED_LIBRARY)
if (WIN32) if (WIN32)
if (MINGW) if (MINGW)
# Remove the dependency on the shared version of libgcc
# NOTE: MinGW-w64 has the correct default but MinGW needs this
target_link_libraries(glfw PRIVATE "-static-libgcc")
# Remove the lib prefix on the DLL (but not the import library) # Remove the lib prefix on the DLL (but not the import library)
set_target_properties(glfw PROPERTIES PREFIX "") set_target_properties(glfw PROPERTIES PREFIX "")
@ -312,30 +290,34 @@ if (GLFW_BUILD_SHARED_LIBRARY)
if (MINGW) if (MINGW)
# Enable link-time exploit mitigation features enabled by default on MSVC # Enable link-time exploit mitigation features enabled by default on MSVC
include(CheckCCompilerFlag) include(CheckCCompilerFlag)
include(CMakePushCheckState)
# Compatibility with data execution prevention (DEP) # Compatibility with data execution prevention (DEP)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat") set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat")
check_c_compiler_flag("" _GLFW_HAS_DEP) check_c_compiler_flag("" _GLFW_HAS_DEP)
if (_GLFW_HAS_DEP) if (_GLFW_HAS_DEP)
target_link_libraries(glfw PRIVATE "-Wl,--nxcompat") target_link_libraries(glfw PRIVATE "-Wl,--nxcompat")
endif() endif()
cmake_pop_check_state()
# Compatibility with address space layout randomization (ASLR) # Compatibility with address space layout randomization (ASLR)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Wl,--dynamicbase") set(CMAKE_REQUIRED_FLAGS "-Wl,--dynamicbase")
check_c_compiler_flag("" _GLFW_HAS_ASLR) check_c_compiler_flag("" _GLFW_HAS_ASLR)
if (_GLFW_HAS_ASLR) if (_GLFW_HAS_ASLR)
target_link_libraries(glfw PRIVATE "-Wl,--dynamicbase") target_link_libraries(glfw PRIVATE "-Wl,--dynamicbase")
endif() endif()
cmake_pop_check_state()
# Compatibility with 64-bit address space layout randomization (ASLR) # Compatibility with 64-bit address space layout randomization (ASLR)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Wl,--high-entropy-va") set(CMAKE_REQUIRED_FLAGS "-Wl,--high-entropy-va")
check_c_compiler_flag("" _GLFW_HAS_64ASLR) check_c_compiler_flag("" _GLFW_HAS_64ASLR)
if (_GLFW_HAS_64ASLR) if (_GLFW_HAS_64ASLR)
target_link_libraries(glfw PRIVATE "-Wl,--high-entropy-va") target_link_libraries(glfw PRIVATE "-Wl,--high-entropy-va")
endif() endif()
cmake_pop_check_state()
# Clear flags again to avoid breaking later tests
set(CMAKE_REQUIRED_FLAGS)
endif() endif()
if (UNIX) if (UNIX)
@ -344,12 +326,8 @@ if (GLFW_BUILD_SHARED_LIBRARY)
endif() endif()
endif() endif()
foreach(arg ${glfw_PKG_DEPS}) list(JOIN glfw_PKG_DEPS " " deps)
string(APPEND deps " ${arg}") list(JOIN glfw_PKG_LIBS " " libs)
endforeach()
foreach(arg ${glfw_PKG_LIBS})
string(APPEND libs " ${arg}")
endforeach()
set(GLFW_PKG_CONFIG_REQUIRES_PRIVATE "${deps}" CACHE INTERNAL set(GLFW_PKG_CONFIG_REQUIRES_PRIVATE "${deps}" CACHE INTERNAL
"GLFW pkg-config Requires.private") "GLFW pkg-config Requires.private")

View file

@ -1,8 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -176,7 +175,7 @@ static void createMenuBar(void)
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTablesCocoa(void) static void createKeyTables(void)
{ {
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes)); memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes)); memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
@ -451,41 +450,6 @@ static GLFWbool initializeTIS(void)
@end // GLFWApplicationDelegate @end // GLFWApplicationDelegate
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwLoadLocalVulkanLoaderCocoa(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -619,7 +583,7 @@ int _glfwInitCocoa(void)
name:NSTextInputContextKeyboardSelectionDidChangeNotification name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil]; object:nil];
createKeyTablesCocoa(); createKeyTables();
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (!_glfw.ns.eventSource) if (!_glfw.ns.eventSource)
@ -689,6 +653,8 @@ void _glfwTerminateCocoa(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
memset(&_glfw.ns, 0, sizeof(_glfw.ns));
} // autoreleasepool } // autoreleasepool
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Cocoa - www.glfw.org // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Cocoa - www.glfw.org // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -33,6 +32,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <assert.h>
#include <IOKit/graphics/IOGraphicsLib.h> #include <IOKit/graphics/IOGraphicsLib.h>
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
@ -137,7 +137,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
if (flags & kDisplayModeStretchedFlag) if (flags & kDisplayModeStretchedFlag)
return GLFW_FALSE; return GLFW_FALSE;
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
@ -164,7 +164,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
if (result.refreshRate == 0) if (result.refreshRate == 0)
result.refreshRate = (int) round(fallbackRefreshRate); result.refreshRate = (int) round(fallbackRefreshRate);
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0) if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
{ {
@ -180,7 +180,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
result.blueBits = 8; result.blueBits = 8;
} }
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100 #if MAC_OS_X_VERSION_MAX_ALLOWED == 101100
CFRelease(format); CFRelease(format);
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */ #endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
return result; return result;
@ -628,7 +628,6 @@ void _glfwSetGammaRampCocoa(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle) GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay); _GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA)
@ -637,6 +636,9 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
return kCGNullDirectDisplay; return kCGNullDirectDisplay;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->ns.displayID; return monitor->ns.displayID;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS - www.glfw.org // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
@ -291,8 +291,6 @@ void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor);
float _glfwTransformYCocoa(float y); float _glfwTransformYCocoa(float y);
void* _glfwLoadLocalVulkanLoaderCocoa(void);
GLFWbool _glfwInitNSGL(void); GLFWbool _glfwInitNSGL(void);
void _glfwTerminateNSGL(void); void _glfwTerminateNSGL(void);
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS - www.glfw.org // GLFW 3.5 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
@ -28,8 +28,11 @@
#if defined(_GLFW_COCOA) #if defined(_GLFW_COCOA)
#import <QuartzCore/CAMetalLayer.h>
#include <float.h> #include <float.h>
#include <string.h> #include <string.h>
#include <assert.h>
// HACK: This enum value is missing from framework headers on OS X 10.11 despite // HACK: This enum value is missing from framework headers on OS X 10.11 despite
// having been (according to documentation) added in Mac OS X 10.7 // having been (according to documentation) added in Mac OS X 10.7
@ -111,7 +114,7 @@ static void updateCursorMode(_GLFWwindow* window)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitorCocoa(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
_glfwSetVideoModeCocoa(window->monitor, &window->videoMode); _glfwSetVideoModeCocoa(window->monitor, &window->videoMode);
const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID); const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
@ -127,7 +130,7 @@ static void acquireMonitorCocoa(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitorCocoa(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -158,7 +161,7 @@ static int translateFlags(NSUInteger flags)
// Translates a macOS keycode to a GLFW keycode // Translates a macOS keycode to a GLFW keycode
// //
static int translateKeyCocoa(unsigned int key) static int translateKey(unsigned int key)
{ {
if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0])) if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
return GLFW_KEY_UNKNOWN; return GLFW_KEY_UNKNOWN;
@ -277,7 +280,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidMiniaturize:(NSNotification *)notification - (void)windowDidMiniaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
releaseMonitorCocoa(window); releaseMonitor(window);
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
} }
@ -285,7 +288,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidDeminiaturize:(NSNotification *)notification - (void)windowDidDeminiaturize:(NSNotification *)notification
{ {
if (window->monitor) if (window->monitor)
acquireMonitorCocoa(window); acquireMonitor(window);
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
} }
@ -309,7 +312,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)windowDidChangeOcclusionState:(NSNotification* )notification - (void)windowDidChangeOcclusionState:(NSNotification* )notification
{ {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
if ([window->ns.object respondsToSelector:@selector(occlusionState)]) if ([window->ns.object respondsToSelector:@selector(occlusionState)])
{ {
if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
@ -317,7 +319,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
else else
window->ns.occluded = GLFW_TRUE; window->ns.occluded = GLFW_TRUE;
} }
#endif
} }
@end @end
@ -561,7 +562,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyDown:(NSEvent *)event - (void)keyDown:(NSEvent *)event
{ {
const int key = translateKeyCocoa([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
@ -574,7 +575,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
int action; int action;
const unsigned int modifierFlags = const unsigned int modifierFlags =
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
const int key = translateKeyCocoa([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags(modifierFlags); const int mods = translateFlags(modifierFlags);
const NSUInteger keyFlag = translateKeyToModifierFlag(key); const NSUInteger keyFlag = translateKeyToModifierFlag(key);
@ -593,11 +594,39 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)keyUp:(NSEvent *)event - (void)keyUp:(NSEvent *)event
{ {
const int key = translateKeyCocoa([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]); const int mods = translateFlags([event modifierFlags]);
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods); _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
} }
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
// HACK: Some key combinations are consumed before reaching keyDown:
// so we claim those events and emit them here
const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
if (mods & GLFW_MOD_CONTROL)
{
if (key == GLFW_KEY_TAB || key == GLFW_KEY_ESCAPE)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
if (mods & GLFW_MOD_SUPER)
{
if (key == GLFW_KEY_PERIOD)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
return [super performKeyEquivalent:event];
}
- (void)scrollWheel:(NSEvent *)event - (void)scrollWheel:(NSEvent *)event
{ {
double deltaX = [event scrollingDeltaX]; double deltaX = [event scrollingDeltaX];
@ -883,7 +912,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
[window->ns.object setContentView:window->ns.view]; [window->ns.object setContentView:window->ns.view];
[window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object makeFirstResponder:window->ns.view];
[window->ns.object setTitle:@(wndconfig->title)]; [window->ns.object setTitle:@(window->title)];
[window->ns.object setDelegate:window->ns.delegate]; [window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES]; [window->ns.object setAcceptsMouseMovedEvents:YES];
[window->ns.object setRestorable:NO]; [window->ns.object setRestorable:NO];
@ -966,7 +995,7 @@ GLFWbool _glfwCreateWindowCocoa(_GLFWwindow* window,
{ {
_glfwShowWindowCocoa(window); _glfwShowWindowCocoa(window);
_glfwFocusWindowCocoa(window); _glfwFocusWindowCocoa(window);
acquireMonitorCocoa(window); acquireMonitor(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -996,7 +1025,7 @@ void _glfwDestroyWindowCocoa(_GLFWwindow* window)
[window->ns.object orderOut:nil]; [window->ns.object orderOut:nil];
if (window->monitor) if (window->monitor)
releaseMonitorCocoa(window); releaseMonitor(window);
if (window->context.destroy) if (window->context.destroy)
window->context.destroy(window); window->context.destroy(window);
@ -1083,7 +1112,7 @@ void _glfwSetWindowSizeCocoa(_GLFWwindow* window, int width, int height)
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
acquireMonitorCocoa(window); acquireMonitor(window);
} }
else else
{ {
@ -1252,7 +1281,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
if (monitor->window == window) if (monitor->window == window)
acquireMonitorCocoa(window); acquireMonitor(window);
} }
else else
{ {
@ -1270,7 +1299,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitorCocoa(window); releaseMonitor(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -1308,7 +1337,7 @@ void _glfwSetWindowMonitorCocoa(_GLFWwindow* window,
[window->ns.object setLevel:NSMainMenuWindowLevel + 1]; [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHasShadow:NO]; [window->ns.object setHasShadow:NO];
acquireMonitorCocoa(window); acquireMonitor(window);
} }
else else
{ {
@ -1949,19 +1978,8 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
{ {
@autoreleasepool { @autoreleasepool {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
// HACK: Dynamically load Core Animation to avoid adding an extra
// dependency for the majority who don't use MoltenVK
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
if (!bundle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Failed to find QuartzCore.framework");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// NOTE: Create the layer here as makeBackingLayer should not return nil // NOTE: Create the layer here as makeBackingLayer should not return nil
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer]; window->ns.layer = [CAMetalLayer layer];
if (!window->ns.layer) if (!window->ns.layer)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -2026,9 +2044,6 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
} }
return err; return err;
#else
return VK_ERROR_EXTENSION_NOT_PRESENT;
#endif
} // autoreleasepool } // autoreleasepool
} }
@ -2040,7 +2055,6 @@ VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance,
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle) GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA)
@ -2050,12 +2064,14 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
return nil; return nil;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
return window->ns.object; return window->ns.object;
} }
GLFWAPI id glfwGetCocoaView(GLFWwindow* handle) GLFWAPI id glfwGetCocoaView(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA)
@ -2065,6 +2081,9 @@ GLFWAPI id glfwGetCocoaView(GLFWwindow* handle)
return nil; return nil;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
return window->ns.view; return window->ns.view;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
@ -195,7 +195,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
{ {
current = alternatives + i; current = alternatives + i;
if (desired->stereo > 0 && current->stereo == 0) if (desired->stereo && !current->stereo)
{ {
// Stereo is a hard constraint // Stereo is a hard constraint
continue; continue;
@ -359,7 +359,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.source = ctxconfig->source; window->context.source = ctxconfig->source;
window->context.client = GLFW_OPENGL_API; window->context.client = GLFW_OPENGL_API;
previous = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); previous = _glfwPlatformGetTls(&_glfw.contextSlot);
glfwMakeContextCurrent((GLFWwindow*) window); glfwMakeContextCurrent((GLFWwindow*) window);
if (_glfwPlatformGetTls(&_glfw.contextSlot) != window) if (_glfwPlatformGetTls(&_glfw.contextSlot) != window)
return GLFW_FALSE; return GLFW_FALSE;
@ -368,7 +368,12 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
window->context.getProcAddress("glGetIntegerv"); window->context.getProcAddress("glGetIntegerv");
window->context.GetString = (PFNGLGETSTRINGPROC) window->context.GetString = (PFNGLGETSTRINGPROC)
window->context.getProcAddress("glGetString"); window->context.getProcAddress("glGetString");
if (!window->context.GetIntegerv || !window->context.GetString) window->context.Flush = (PFNGLFLUSHPROC)
window->context.getProcAddress("glFlush");
if (!window->context.GetIntegerv ||
!window->context.GetString ||
!window->context.Flush)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken"); _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
glfwMakeContextCurrent((GLFWwindow*) previous); glfwMakeContextCurrent((GLFWwindow*) previous);
@ -615,12 +620,12 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow *) handle;
_GLFWwindow* previous;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
previous = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); _GLFWwindow* window = (_GLFWwindow*) handle;
_GLFWwindow* previous;
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
if (window && window->context.client == GLFW_NO_API) if (window && window->context.client == GLFW_NO_API)
{ {
@ -642,16 +647,16 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
GLFWAPI GLFWwindow* glfwGetCurrentContext(void) GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return (GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); return _glfwPlatformGetTls(&_glfw.contextSlot);
} }
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow *) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.client == GLFW_NO_API) if (window->context.client == GLFW_NO_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
@ -668,7 +673,7 @@ GLFWAPI void glfwSwapInterval(int interval)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
@ -686,7 +691,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
@ -752,7 +757,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); window = _glfwPlatformGetTls(&_glfw.contextSlot);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
@ -762,3 +767,4 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
return window->context.getProcAddress(procname); return window->context.getProcAddress(procname);
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 EGL - www.glfw.org // GLFW 3.5 EGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -92,7 +92,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
EGLConfig* nativeConfigs; EGLConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs; _GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest; const _GLFWfbconfig* closest;
int i, nativeCount, usableCount, apiBit; int i, nativeCount, usableCount, apiBit, surfaceTypeBit;
GLFWbool wrongApiAvailable = GLFW_FALSE; GLFWbool wrongApiAvailable = GLFW_FALSE;
if (ctxconfig->client == GLFW_OPENGL_ES_API) if (ctxconfig->client == GLFW_OPENGL_ES_API)
@ -105,6 +105,11 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
else else
apiBit = EGL_OPENGL_BIT; apiBit = EGL_OPENGL_BIT;
if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
surfaceTypeBit = EGL_PBUFFER_BIT;
else
surfaceTypeBit = EGL_WINDOW_BIT;
if (fbconfig->stereo) if (fbconfig->stereo)
{ {
_glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported"); _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
@ -118,10 +123,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
return GLFW_FALSE; return GLFW_FALSE;
} }
nativeConfigs = (EGLConfig *)_glfw_calloc(nativeCount, sizeof(EGLConfig)); nativeConfigs = _glfw_calloc(nativeCount, sizeof(EGLConfig));
eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
usableConfigs = (_GLFWfbconfig *)_glfw_calloc(nativeCount, sizeof(_GLFWfbconfig)); usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0; usableCount = 0;
for (i = 0; i < nativeCount; i++) for (i = 0; i < nativeCount; i++)
@ -133,8 +138,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue; continue;
// Only consider window EGLConfigs if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & surfaceTypeBit))
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue; continue;
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
@ -250,6 +254,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
getEGLErrorString(eglGetError())); getEGLErrorString(eglGetError()));
return; return;
} }
#if defined(_GLFW_WAYLAND)
// NOTE: Disable EGL vsync so we can substitute our own that includes a timeout
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
eglSwapInterval(_glfw.egl.display, 0);
#endif // _GLFW_WAYLAND
} }
else else
{ {
@ -283,6 +293,15 @@ static void swapBuffersEGL(_GLFWwindow* window)
// NOTE: Swapping buffers on a hidden window on Wayland makes it visible // NOTE: Swapping buffers on a hidden window on Wayland makes it visible
if (!window->wl.visible) if (!window->wl.visible)
return; return;
// NOTE: We wait for a frame manually so we can add a timeout,
// as the EGL implementation will wait indefinitely
if (window->wl.egl.interval > 0)
{
window->context.Flush();
if (!_glfwWaitForEGLFrameWayland(window))
return;
}
} }
#endif #endif
@ -291,6 +310,16 @@ static void swapBuffersEGL(_GLFWwindow* window)
static void swapIntervalEGL(int interval) static void swapIntervalEGL(int interval)
{ {
#if defined(_GLFW_WAYLAND)
if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
window->wl.egl.interval = interval;
return;
}
#endif
eglSwapInterval(_glfw.egl.display, interval); eglSwapInterval(_glfw.egl.display, interval);
} }
@ -308,18 +337,19 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname) static GLFWglproc getProcAddressEGL(const char* procname)
{ {
_GLFWwindow* window = (_GLFWwindow *)_glfwPlatformGetTls(&_glfw.contextSlot); const GLFWglproc proc = (GLFWglproc) eglGetProcAddress(procname);
assert(window != NULL);
if (window->context.egl.client)
{
GLFWglproc proc = (GLFWglproc)
_glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
if (proc) if (proc)
return proc; return proc;
if (!_glfw.egl.KHR_get_all_proc_addresses)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
return _glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
} }
return eglGetProcAddress(procname); return NULL;
} }
static void destroyContextEGL(_GLFWwindow* window) static void destroyContextEGL(_GLFWwindow* window)
@ -328,13 +358,10 @@ static void destroyContextEGL(_GLFWwindow* window)
// as it will make XCloseDisplay segfault // as it will make XCloseDisplay segfault
if (_glfw.platform.platformID != GLFW_PLATFORM_X11 || if (_glfw.platform.platformID != GLFW_PLATFORM_X11 ||
window->context.client != GLFW_OPENGL_API) window->context.client != GLFW_OPENGL_API)
{
if (window->context.egl.client)
{ {
_glfwPlatformFreeModule(window->context.egl.client); _glfwPlatformFreeModule(window->context.egl.client);
window->context.egl.client = NULL; window->context.egl.client = NULL;
} }
}
if (window->context.egl.surface) if (window->context.egl.surface)
{ {
@ -354,8 +381,6 @@ static void destroyContextEGL(_GLFWwindow* window)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize EGL
//
GLFWbool _glfwInitEGL(void) GLFWbool _glfwInitEGL(void)
{ {
int i; int i;
@ -365,10 +390,10 @@ GLFWbool _glfwInitEGL(void)
{ {
#if defined(_GLFW_EGL_LIBRARY) #if defined(_GLFW_EGL_LIBRARY)
_GLFW_EGL_LIBRARY, _GLFW_EGL_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_WIN32)
"libEGL.dll", "libEGL.dll",
"EGL.dll", "EGL.dll",
#elif defined(_GLFW_COCOA) #elif defined(__APPLE__)
"libEGL.dylib", "libEGL.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libEGL-1.so", "libEGL-1.so",
@ -420,6 +445,8 @@ GLFWbool _glfwInitEGL(void)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext"); _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface) _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface"); _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.CreatePbufferSurface = (PFN_eglCreatePbufferSurface)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglCreatePbufferSurface");
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent) _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
_glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent"); _glfwPlatformGetModuleSymbol(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers) _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
@ -442,6 +469,7 @@ GLFWbool _glfwInitEGL(void)
!_glfw.egl.DestroySurface || !_glfw.egl.DestroySurface ||
!_glfw.egl.DestroyContext || !_glfw.egl.DestroyContext ||
!_glfw.egl.CreateWindowSurface || !_glfw.egl.CreateWindowSurface ||
!_glfw.egl.CreatePbufferSurface ||
!_glfw.egl.MakeCurrent || !_glfw.egl.MakeCurrent ||
!_glfw.egl.SwapBuffers || !_glfw.egl.SwapBuffers ||
!_glfw.egl.SwapInterval || !_glfw.egl.SwapInterval ||
@ -477,6 +505,8 @@ GLFWbool _glfwInitEGL(void)
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions); _glfwStringInExtensionString("EGL_ANGLE_platform_angle_vulkan", extensions);
_glfw.egl.ANGLE_platform_angle_metal = _glfw.egl.ANGLE_platform_angle_metal =
_glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions); _glfwStringInExtensionString("EGL_ANGLE_platform_angle_metal", extensions);
_glfw.egl.MESA_platform_surfaceless =
_glfwStringInExtensionString("EGL_MESA_platform_surfaceless", extensions);
} }
if (_glfw.egl.EXT_platform_base) if (_glfw.egl.EXT_platform_base)
@ -536,8 +566,6 @@ GLFWbool _glfwInitEGL(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Terminate EGL
//
void _glfwTerminateEGL(void) void _glfwTerminateEGL(void)
{ {
if (_glfw.egl.display) if (_glfw.egl.display)
@ -546,7 +574,8 @@ void _glfwTerminateEGL(void)
_glfw.egl.display = EGL_NO_DISPLAY; _glfw.egl.display = EGL_NO_DISPLAY;
} }
if (_glfw.egl.handle) // Free modules only after all wayland termination functions are called
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
{ {
_glfwPlatformFreeModule(_glfw.egl.handle); _glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL; _glfw.egl.handle = NULL;
@ -560,8 +589,6 @@ void _glfwTerminateEGL(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
@ -648,7 +675,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->noerror) if (ctxconfig->noerror)
{ {
if (_glfw.egl.KHR_create_context_no_error) if (_glfw.egl.KHR_create_context_no_error)
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
} }
if (mask) if (mask)
@ -708,20 +735,36 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); SET_ATTRIB(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
} }
if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
{
int width, height;
_glfw.platform.getFramebufferSize(window, &width, &height);
SET_ATTRIB(EGL_WIDTH, width);
SET_ATTRIB(EGL_HEIGHT, height);
}
SET_ATTRIB(EGL_NONE, EGL_NONE); SET_ATTRIB(EGL_NONE, EGL_NONE);
native = _glfw.platform.getEGLNativeWindow(window); native = _glfw.platform.getEGLNativeWindow(window);
// HACK: ANGLE does not implement eglCreatePlatformWindowSurfaceEXT if (!_glfw.egl.platform || _glfw.egl.platform == EGL_PLATFORM_ANGLE_ANGLE)
// despite reporting EGL_EXT_platform_base
if (_glfw.egl.platform && _glfw.egl.platform != EGL_PLATFORM_ANGLE_ANGLE)
{ {
// HACK: Also use non-platform function for ANGLE, as it does not
// implement eglCreatePlatformWindowSurfaceEXT despite reporting
// support for EGL_EXT_platform_base
window->context.egl.surface = window->context.egl.surface =
eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs); eglCreateWindowSurface(_glfw.egl.display, config, native, attribs);
}
else if (_glfw.egl.platform == EGL_PLATFORM_SURFACELESS_MESA)
{
// HACK: Use a pbuffer surface as the default framebuffer
window->context.egl.surface =
eglCreatePbufferSurface(_glfw.egl.display, config, attribs);
} }
else else
{ {
window->context.egl.surface = window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display, config, native, attribs); eglCreatePlatformWindowSurfaceEXT(_glfw.egl.display, config, native, attribs);
} }
if (window->context.egl.surface == EGL_NO_SURFACE) if (window->context.egl.surface == EGL_NO_SURFACE)
@ -743,10 +786,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
#if defined(_GLFW_GLESV1_LIBRARY) #if defined(_GLFW_GLESV1_LIBRARY)
_GLFW_GLESV1_LIBRARY, _GLFW_GLESV1_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_WIN32)
"GLESv1_CM.dll", "GLESv1_CM.dll",
"libGLES_CM.dll", "libGLES_CM.dll",
#elif defined(_GLFW_COCOA) #elif defined(__APPLE__)
"libGLESv1_CM.dylib", "libGLESv1_CM.dylib",
#elif defined(__OpenBSD__) || defined(__NetBSD__) #elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGLESv1_CM.so", "libGLESv1_CM.so",
@ -760,10 +803,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
#if defined(_GLFW_GLESV2_LIBRARY) #if defined(_GLFW_GLESV2_LIBRARY)
_GLFW_GLESV2_LIBRARY, _GLFW_GLESV2_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_WIN32)
"GLESv2.dll", "GLESv2.dll",
"libGLESv2.dll", "libGLESv2.dll",
#elif defined(_GLFW_COCOA) #elif defined(__APPLE__)
"libGLESv2.dylib", "libGLESv2.dylib",
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
"libGLESv2-2.so", "libGLESv2-2.so",
@ -778,8 +821,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{ {
#if defined(_GLFW_OPENGL_LIBRARY) #if defined(_GLFW_OPENGL_LIBRARY)
_GLFW_OPENGL_LIBRARY, _GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32) #elif defined(_WIN32)
#elif defined(_GLFW_COCOA) #elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__) #elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so", "libGL.so",
#else #else
@ -883,28 +926,63 @@ GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle) GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow *) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_EGL_CONTEXT_API) if (window->context.source != GLFW_EGL_CONTEXT_API)
{
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND ||
window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
} }
}
return window->context.egl.handle; return window->context.egl.handle;
} }
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow *) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE); _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_EGL_CONTEXT_API) if (window->context.source != GLFW_EGL_CONTEXT_API)
{
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND ||
window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return EGL_NO_SURFACE; return EGL_NO_SURFACE;
} }
}
return window->context.egl.surface; return window->context.egl.surface;
} }
GLFWAPI int glfwGetEGLConfig(GLFWwindow* handle, EGLConfig* config)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(config != NULL);
if (window->context.source != GLFW_EGL_CONTEXT_API)
{
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND ||
window->context.source != GLFW_NATIVE_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
}
*config = window->context.egl.config;
return GLFW_TRUE;
}

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 GLX - www.glfw.org // GLFW 3.5 GLX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -119,9 +119,7 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE); u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS); u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
u->stereo = getGLXFBConfigAttrib(n, GLX_STEREO);
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = GLFW_TRUE;
if (_glfw.glx.ARB_multisample) if (_glfw.glx.ARB_multisample)
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES); u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
@ -253,8 +251,6 @@ static void destroyContextGLX(_GLFWwindow* window)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize GLX
//
GLFWbool _glfwInitGLX(void) GLFWbool _glfwInitGLX(void)
{ {
const char* sonames[] = const char* sonames[] =
@ -369,7 +365,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalEXT"); getProcAddressGLX("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT) if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = GLFW_TRUE; _glfw.glx.EXT_swap_control = true;
} }
if (extensionSupportedGLX("GLX_SGI_swap_control")) if (extensionSupportedGLX("GLX_SGI_swap_control"))
@ -378,7 +374,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalSGI"); getProcAddressGLX("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI) if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = GLFW_TRUE; _glfw.glx.SGI_swap_control = true;
} }
if (extensionSupportedGLX("GLX_MESA_swap_control")) if (extensionSupportedGLX("GLX_MESA_swap_control"))
@ -387,17 +383,17 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalMESA"); getProcAddressGLX("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA) if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = GLFW_TRUE; _glfw.glx.MESA_swap_control = true;
} }
if (extensionSupportedGLX("GLX_ARB_multisample")) if (extensionSupportedGLX("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = GLFW_TRUE; _glfw.glx.ARB_multisample = true;
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB")) if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.ARB_framebuffer_sRGB = true;
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB")) if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE; _glfw.glx.EXT_framebuffer_sRGB = true;
if (extensionSupportedGLX("GLX_ARB_create_context")) if (extensionSupportedGLX("GLX_ARB_create_context"))
{ {
@ -405,39 +401,34 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXCreateContextAttribsARB"); getProcAddressGLX("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB) if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = GLFW_TRUE; _glfw.glx.ARB_create_context = true;
} }
if (extensionSupportedGLX("GLX_ARB_create_context_robustness")) if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE; _glfw.glx.ARB_create_context_robustness = true;
if (extensionSupportedGLX("GLX_ARB_create_context_profile")) if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = GLFW_TRUE; _glfw.glx.ARB_create_context_profile = true;
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile")) if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; _glfw.glx.EXT_create_context_es2_profile = true;
if (extensionSupportedGLX("GLX_ARB_create_context_no_error")) if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE; _glfw.glx.ARB_create_context_no_error = true;
if (extensionSupportedGLX("GLX_ARB_context_flush_control")) if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GLFW_TRUE; _glfw.glx.ARB_context_flush_control = true;
return GLFW_TRUE; return GLFW_TRUE;
} }
// Terminate GLX
//
void _glfwTerminateGLX(void) void _glfwTerminateGLX(void)
{ {
// NOTE: This function must not call any X11 functions, as it is called // NOTE: This function must not call any X11 functions, as it is called
// after XCloseDisplay (see _glfwTerminateX11 for details) // after XCloseDisplay (see _glfwTerminateX11 for details)
if (_glfw.glx.handle)
{
_glfwPlatformFreeModule(_glfw.glx.handle); _glfwPlatformFreeModule(_glfw.glx.handle);
_glfw.glx.handle = NULL; _glfw.glx.handle = NULL;
}
} }
#define SET_ATTRIB(a, v) \ #define SET_ATTRIB(a, v) \
@ -447,8 +438,6 @@ void _glfwTerminateGLX(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window, GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
@ -626,6 +615,8 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
window->context.glx.fbconfig = native;
window->context.makeCurrent = makeContextCurrentGLX; window->context.makeCurrent = makeContextCurrentGLX;
window->context.swapBuffers = swapBuffersGLX; window->context.swapBuffers = swapBuffersGLX;
window->context.swapInterval = swapIntervalGLX; window->context.swapInterval = swapIntervalGLX;
@ -677,7 +668,6 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle) GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11) if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -686,6 +676,9 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
return NULL; return NULL;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
@ -697,7 +690,6 @@ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle) GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11) if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -706,6 +698,9 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
return None; return None;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
@ -715,5 +710,29 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
return window->context.glx.window; return window->context.glx.window;
} }
GLFWAPI int glfwGetGLXFBConfig(GLFWwindow* handle, GLXFBConfig* config)
{
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized");
return GLFW_FALSE;
}
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(config != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return GLFW_FALSE;
}
*config = window->context.glx.fbconfig;
return GLFW_TRUE;
}
#endif // _GLFW_X11 #endif // _GLFW_X11

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@ -49,18 +49,18 @@ static GLFWerrorfun _glfwErrorCallback;
static GLFWallocator _glfwInitAllocator; static GLFWallocator _glfwInitAllocator;
static _GLFWinitconfig _glfwInitHints = static _GLFWinitconfig _glfwInitHints =
{ {
.hatButtons = GLFW_TRUE, .hatButtons = true,
.angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE, .angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE,
.platformID = GLFW_ANY_PLATFORM, .platformID = GLFW_ANY_PLATFORM,
.vulkanLoader = NULL, .vulkanLoader = NULL,
.ns = .ns =
{ {
.menubar = GLFW_TRUE, .menubar = true,
.chdir = GLFW_TRUE .chdir = true
}, },
.x11 = .x11 =
{ {
.xcbVulkanSurface = GLFW_TRUE, .xcbVulkanSurface = true,
}, },
.wl = .wl =
{ {

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -333,10 +333,8 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{ {
assert(window != NULL); assert(window != NULL);
assert(xoffset > -FLT_MAX); assert(isfinite(xoffset));
assert(xoffset < FLT_MAX); assert(isfinite(yoffset));
assert(yoffset > -FLT_MAX);
assert(yoffset < FLT_MAX);
if (window->callbacks.scroll) if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
@ -348,20 +346,22 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
{ {
assert(window != NULL); assert(window != NULL);
assert(button >= 0); assert(button >= 0);
assert(button <= GLFW_MOUSE_BUTTON_LAST);
assert(action == GLFW_PRESS || action == GLFW_RELEASE); assert(action == GLFW_PRESS || action == GLFW_RELEASE);
assert(mods == (mods & GLFW_MOD_MASK)); assert(mods == (mods & GLFW_MOD_MASK));
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) if (button < 0 || (!window->disableMouseButtonLimit && button > GLFW_MOUSE_BUTTON_LAST))
return; return;
if (!window->lockKeyMods) if (!window->lockKeyMods)
mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK); mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
if (button <= GLFW_MOUSE_BUTTON_LAST)
{
if (action == GLFW_RELEASE && window->stickyMouseButtons) if (action == GLFW_RELEASE && window->stickyMouseButtons)
window->mouseButtons[button] = _GLFW_STICK; window->mouseButtons[button] = _GLFW_STICK;
else else
window->mouseButtons[button] = (char) action; window->mouseButtons[button] = (char) action;
}
if (window->callbacks.mouseButton) if (window->callbacks.mouseButton)
window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
@ -373,10 +373,8 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{ {
assert(window != NULL); assert(window != NULL);
assert(xpos > -FLT_MAX); assert(isfinite(xpos));
assert(xpos < FLT_MAX); assert(isfinite(ypos));
assert(ypos > -FLT_MAX);
assert(ypos < FLT_MAX);
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
return; return;
@ -434,6 +432,7 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
assert(js != NULL); assert(js != NULL);
assert(axis >= 0); assert(axis >= 0);
assert(axis < js->axisCount); assert(axis < js->axisCount);
assert(isfinite(value));
js->axes[axis] = value; js->axes[axis] = value;
} }
@ -559,11 +558,11 @@ void _glfwCenterCursorInContentArea(_GLFWwindow* window)
GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0);
switch (mode) switch (mode)
{ {
case GLFW_CURSOR: case GLFW_CURSOR:
@ -576,6 +575,8 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
return window->lockKeyMods; return window->lockKeyMods;
case GLFW_RAW_MOUSE_MOTION: case GLFW_RAW_MOUSE_MOTION:
return window->rawMouseMotion; return window->rawMouseMotion;
case GLFW_UNLIMITED_MOUSE_BUTTONS:
return window->disableMouseButtonLimit;
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
@ -584,11 +585,11 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
switch (mode) switch (mode)
{ {
case GLFW_CURSOR: case GLFW_CURSOR:
@ -683,6 +684,12 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
_glfw.platform.setRawMouseMotion(window, value); _glfw.platform.setRawMouseMotion(window, value);
return; return;
} }
case GLFW_UNLIMITED_MOUSE_BUTTONS:
{
window->disableMouseButtonLimit = value ? GLFW_TRUE : GLFW_FALSE;
return;
}
} }
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
@ -734,11 +741,11 @@ GLFWAPI int glfwGetKeyScancode(int key)
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
@ -757,11 +764,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST) if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
{ {
_glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button); _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
@ -780,9 +787,6 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
if (ypos) if (ypos)
@ -790,6 +794,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->cursorMode == GLFW_CURSOR_DISABLED) if (window->cursorMode == GLFW_CURSOR_DISABLED)
{ {
if (xpos) if (xpos)
@ -803,13 +810,12 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT(); if (!isfinite(xpos) || !isfinite(ypos))
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
{ {
_glfwInputError(GLFW_INVALID_VALUE, _glfwInputError(GLFW_INVALID_VALUE,
"Invalid cursor position %f %f", "Invalid cursor position %f %f",
@ -897,10 +903,10 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
GLFWAPI void glfwDestroyCursor(GLFWcursor* handle) GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
{ {
_GLFWcursor* cursor = (_GLFWcursor*) handle;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWcursor* cursor = (_GLFWcursor*) handle;
if (cursor == NULL) if (cursor == NULL)
return; return;
@ -932,12 +938,12 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle) GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) windowHandle; _GLFWwindow* window = (_GLFWwindow*) windowHandle;
_GLFWcursor* cursor = (_GLFWcursor*) cursorHandle; _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
window->cursor = cursor; window->cursor = cursor;
_glfw.platform.setCursor(window, cursor); _glfw.platform.setCursor(window, cursor);
@ -945,30 +951,33 @@ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun); _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun);
return cbfun; return cbfun;
} }
GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun); _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun);
return cbfun; return cbfun;
} }
GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun); _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun);
return cbfun; return cbfun;
} }
@ -976,10 +985,11 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmods
GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle, GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
GLFWmousebuttonfun cbfun) GLFWmousebuttonfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun); _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun);
return cbfun; return cbfun;
} }
@ -987,10 +997,11 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle, GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
GLFWcursorposfun cbfun) GLFWcursorposfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun); _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun);
return cbfun; return cbfun;
} }
@ -998,10 +1009,11 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle, GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
GLFWcursorenterfun cbfun) GLFWcursorenterfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun); _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun);
return cbfun; return cbfun;
} }
@ -1009,20 +1021,22 @@ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle, GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
GLFWscrollfun cbfun) GLFWscrollfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun); _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun);
return cbfun; return cbfun;
} }
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun); _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun);
return cbfun; return cbfun;
} }
@ -1481,7 +1495,7 @@ GLFWAPI void glfwSetTime(double time)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (time != time || time < 0.0 || time > 18446744073.0) if (!isfinite(time) || time < 0.0 || time > 18446744073.0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time); _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return; return;

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -48,6 +48,8 @@
#define GLFW_INCLUDE_NONE #define GLFW_INCLUDE_NONE
#include "../include/GLFW/glfw3.h" #include "../include/GLFW/glfw3.h"
#include <stdbool.h>
#define _GLFW_INSERT_FIRST 0 #define _GLFW_INSERT_FIRST 0
#define _GLFW_INSERT_LAST 1 #define _GLFW_INSERT_LAST 1
@ -107,6 +109,7 @@ typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum); typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*); typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
typedef void (APIENTRY * PFNGLFLUSHPROC)(void);
#define EGL_SUCCESS 0x3000 #define EGL_SUCCESS 0x3000
#define EGL_NOT_INITIALIZED 0x3001 #define EGL_NOT_INITIALIZED 0x3001
@ -150,6 +153,9 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
#define EGL_NO_DISPLAY ((EGLDisplay) 0) #define EGL_NO_DISPLAY ((EGLDisplay) 0)
#define EGL_NO_CONTEXT ((EGLContext) 0) #define EGL_NO_CONTEXT ((EGLContext) 0)
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) #define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
#define EGL_PBUFFER_BIT 0x0001
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 #define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 #define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
@ -181,6 +187,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
#define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450
#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 #define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489
#define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f #define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f
#define EGL_PLATFORM_SURFACELESS_MESA 0x31dd
typedef int EGLint; typedef int EGLint;
typedef unsigned int EGLBoolean; typedef unsigned int EGLBoolean;
@ -205,6 +212,7 @@ typedef EGLContext (APIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLCon
typedef EGLBoolean (APIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface); typedef EGLBoolean (APIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
typedef EGLBoolean (APIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext); typedef EGLBoolean (APIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
typedef EGLSurface (APIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*); typedef EGLSurface (APIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
typedef EGLSurface (APIENTRY * PFN_eglCreatePbufferSurface)(EGLDisplay,EGLContext,const EGLint*);
typedef EGLBoolean (APIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext); typedef EGLBoolean (APIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
typedef EGLBoolean (APIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface); typedef EGLBoolean (APIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint); typedef EGLBoolean (APIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
@ -221,6 +229,7 @@ typedef GLFWglproc (APIENTRY * PFN_eglGetProcAddress)(const char*);
#define eglDestroySurface _glfw.egl.DestroySurface #define eglDestroySurface _glfw.egl.DestroySurface
#define eglDestroyContext _glfw.egl.DestroyContext #define eglDestroyContext _glfw.egl.DestroyContext
#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface #define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
#define eglCreatePbufferSurface _glfw.egl.CreatePbufferSurface
#define eglMakeCurrent _glfw.egl.MakeCurrent #define eglMakeCurrent _glfw.egl.MakeCurrent
#define eglSwapBuffers _glfw.egl.SwapBuffers #define eglSwapBuffers _glfw.egl.SwapBuffers
#define eglSwapInterval _glfw.egl.SwapInterval #define eglSwapInterval _glfw.egl.SwapInterval
@ -277,6 +286,7 @@ typedef enum VkStructureType
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT = 1000256000,
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
} VkStructureType; } VkStructureType;
@ -365,16 +375,16 @@ struct _GLFWerror
// //
struct _GLFWinitconfig struct _GLFWinitconfig
{ {
GLFWbool hatButtons; bool hatButtons;
int angleType; int angleType;
int platformID; int platformID;
PFN_vkGetInstanceProcAddr vulkanLoader; PFN_vkGetInstanceProcAddr vulkanLoader;
struct { struct {
GLFWbool menubar; bool menubar;
GLFWbool chdir; bool chdir;
} ns; } ns;
struct { struct {
GLFWbool xcbVulkanSurface; bool xcbVulkanSurface;
} x11; } x11;
struct { struct {
int libdecorMode; int libdecorMode;
@ -393,19 +403,18 @@ struct _GLFWwndconfig
int ypos; int ypos;
int width; int width;
int height; int height;
const char* title; bool resizable;
GLFWbool resizable; bool visible;
GLFWbool visible; bool decorated;
GLFWbool decorated; bool focused;
GLFWbool focused; bool autoIconify;
GLFWbool autoIconify; bool floating;
GLFWbool floating; bool maximized;
GLFWbool maximized; bool centerCursor;
GLFWbool centerCursor; bool focusOnShow;
GLFWbool focusOnShow; bool mousePassthrough;
GLFWbool mousePassthrough; bool scaleToMonitor;
GLFWbool scaleToMonitor; bool scaleFramebuffer;
GLFWbool scaleFramebuffer;
struct { struct {
char frameName[256]; char frameName[256];
} ns; } ns;
@ -414,8 +423,8 @@ struct _GLFWwndconfig
char instanceName[256]; char instanceName[256];
} x11; } x11;
struct { struct {
GLFWbool keymenu; bool keymenu;
GLFWbool showDefault; bool showDefault;
} win32; } win32;
struct { struct {
char appId[256]; char appId[256];
@ -434,15 +443,15 @@ struct _GLFWctxconfig
int source; int source;
int major; int major;
int minor; int minor;
GLFWbool forward; bool forward;
GLFWbool debug; bool debug;
GLFWbool noerror; bool noerror;
int profile; int profile;
int robustness; int robustness;
int release; int release;
_GLFWwindow* share; _GLFWwindow* share;
struct { struct {
GLFWbool offline; bool offline;
} nsgl; } nsgl;
}; };
@ -467,11 +476,11 @@ struct _GLFWfbconfig
int accumBlueBits; int accumBlueBits;
int accumAlphaBits; int accumAlphaBits;
int auxBuffers; int auxBuffers;
GLFWbool stereo; bool stereo;
int samples; int samples;
GLFWbool sRGB; bool sRGB;
GLFWbool doublebuffer; bool doublebuffer;
GLFWbool transparent; bool transparent;
uintptr_t handle; uintptr_t handle;
}; };
@ -490,6 +499,7 @@ struct _GLFWcontext
PFNGLGETSTRINGIPROC GetStringi; PFNGLGETSTRINGIPROC GetStringi;
PFNGLGETINTEGERVPROC GetIntegerv; PFNGLGETINTEGERVPROC GetIntegerv;
PFNGLGETSTRINGPROC GetString; PFNGLGETSTRINGPROC GetString;
PFNGLFLUSHPROC Flush;
void (*makeCurrent)(_GLFWwindow*); void (*makeCurrent)(_GLFWwindow*);
void (*swapBuffers)(_GLFWwindow*); void (*swapBuffers)(_GLFWwindow*);
@ -544,6 +554,7 @@ struct _GLFWwindow
GLFWbool stickyKeys; GLFWbool stickyKeys;
GLFWbool stickyMouseButtons; GLFWbool stickyMouseButtons;
GLFWbool lockKeyMods; GLFWbool lockKeyMods;
GLFWbool disableMouseButtonLimit;
int cursorMode; int cursorMode;
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
char keys[GLFW_KEY_LAST + 1]; char keys[GLFW_KEY_LAST + 1];
@ -796,21 +807,22 @@ struct _GLFWlibrary
EGLint major, minor; EGLint major, minor;
GLFWbool prefix; GLFWbool prefix;
GLFWbool KHR_create_context; bool KHR_create_context;
GLFWbool KHR_create_context_no_error; bool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace; bool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses; bool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control; bool KHR_context_flush_control;
GLFWbool EXT_client_extensions; bool EXT_client_extensions;
GLFWbool EXT_platform_base; bool EXT_platform_base;
GLFWbool EXT_platform_x11; bool EXT_platform_x11;
GLFWbool EXT_platform_wayland; bool EXT_platform_wayland;
GLFWbool EXT_present_opaque; bool EXT_present_opaque;
GLFWbool ANGLE_platform_angle; bool ANGLE_platform_angle;
GLFWbool ANGLE_platform_angle_opengl; bool ANGLE_platform_angle_opengl;
GLFWbool ANGLE_platform_angle_d3d; bool ANGLE_platform_angle_d3d;
GLFWbool ANGLE_platform_angle_vulkan; bool ANGLE_platform_angle_vulkan;
GLFWbool ANGLE_platform_angle_metal; bool ANGLE_platform_angle_metal;
bool MESA_platform_surfaceless;
void* handle; void* handle;
@ -825,6 +837,7 @@ struct _GLFWlibrary
PFN_eglDestroySurface DestroySurface; PFN_eglDestroySurface DestroySurface;
PFN_eglDestroyContext DestroyContext; PFN_eglDestroyContext DestroyContext;
PFN_eglCreateWindowSurface CreateWindowSurface; PFN_eglCreateWindowSurface CreateWindowSurface;
PFN_eglCreatePbufferSurface CreatePbufferSurface;
PFN_eglMakeCurrent MakeCurrent; PFN_eglMakeCurrent MakeCurrent;
PFN_eglSwapBuffers SwapBuffers; PFN_eglSwapBuffers SwapBuffers;
PFN_eglSwapInterval SwapInterval; PFN_eglSwapInterval SwapInterval;
@ -853,13 +866,14 @@ struct _GLFWlibrary
void* handle; void* handle;
char* extensions[2]; char* extensions[2];
PFN_vkGetInstanceProcAddr GetInstanceProcAddr; PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
GLFWbool KHR_surface; bool KHR_surface;
GLFWbool KHR_win32_surface; bool KHR_win32_surface;
GLFWbool MVK_macos_surface; bool MVK_macos_surface;
GLFWbool EXT_metal_surface; bool EXT_metal_surface;
GLFWbool KHR_xlib_surface; bool KHR_xlib_surface;
GLFWbool KHR_xcb_surface; bool KHR_xcb_surface;
GLFWbool KHR_wayland_surface; bool KHR_wayland_surface;
bool EXT_headless_surface;
} vk; } vk;
struct { struct {

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Linux - www.glfw.org // GLFW 3.5 Linux - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@ -32,6 +32,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/ioctl.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Linux - www.glfw.org // GLFW 3.5 Linux - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //

View file

@ -0,0 +1,57 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(GLFW_BUILD_MACOS_TIMER)
#include <mach/mach_time.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformInitTimer(void)
{
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.timer.macos.frequency = (info.denom * 1e9) / info.numer;
}
uint64_t _glfwPlatformGetTimerValue(void)
{
return mach_absolute_time();
}
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.macos.frequency;
}
#endif // GLFW_BUILD_MACOS_TIMER

View file

@ -0,0 +1,35 @@
//========================================================================
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2021 Camilla Löwy <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#define GLFW_MACOS_LIBRARY_TIMER_STATE _GLFWtimerMacOS macos;
// macOS-specific global timer data
//
typedef struct _GLFWtimerMacOS
{
uint64_t frequency;
} _GLFWtimerMacOS;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -325,9 +325,6 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
if (ypos) if (ypos)
@ -335,6 +332,9 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_glfw.platform.getMonitorPos(monitor, xpos, ypos); _glfw.platform.getMonitorPos(monitor, xpos, ypos);
} }
@ -342,9 +342,6 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
int* xpos, int* ypos, int* xpos, int* ypos,
int* width, int* height) int* width, int* height)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
if (ypos) if (ypos)
@ -356,14 +353,14 @@ GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height); _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height);
} }
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (widthMM) if (widthMM)
*widthMM = 0; *widthMM = 0;
if (heightMM) if (heightMM)
@ -371,6 +368,9 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (widthMM) if (widthMM)
*widthMM = monitor->widthMM; *widthMM = monitor->widthMM;
if (heightMM) if (heightMM)
@ -380,42 +380,46 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int*
GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle, GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (xscale) if (xscale)
*xscale = 0.f; *xscale = 0.f;
if (yscale) if (yscale)
*yscale = 0.f; *yscale = 0.f;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
_glfw.platform.getMonitorContentScale(monitor, xscale, yscale); _glfw.platform.getMonitorContentScale(monitor, xscale, yscale);
} }
GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->name; return monitor->name;
} }
GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer) GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
{ {
_GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
_GLFW_REQUIRE_INIT();
monitor->userPointer = pointer; monitor->userPointer = pointer;
} }
GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle) GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return monitor->userPointer; return monitor->userPointer;
} }
@ -428,14 +432,15 @@ GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
assert(count != NULL); assert(count != NULL);
*count = 0; *count = 0;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (!refreshVideoModes(monitor)) if (!refreshVideoModes(monitor))
return NULL; return NULL;
@ -445,11 +450,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (!_glfw.platform.getVideoMode(monitor, &monitor->currentMode)) if (!_glfw.platform.getVideoMode(monitor, &monitor->currentMode))
return NULL; return NULL;
@ -462,13 +467,15 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
unsigned short* values; unsigned short* values;
GLFWgammaramp ramp; GLFWgammaramp ramp;
const GLFWgammaramp* original; const GLFWgammaramp* original;
assert(handle != NULL);
assert(gamma > 0.f); assert(gamma > 0.f);
assert(gamma <= FLT_MAX); assert(isfinite(gamma));
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX) assert(handle != NULL);
if (!isfinite(gamma) || gamma <= 0.f)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma); _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return; return;
@ -505,11 +512,11 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_glfwFreeGammaArrays(&monitor->currentRamp); _glfwFreeGammaArrays(&monitor->currentRamp);
if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp)) if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp))
return NULL; return NULL;
@ -519,8 +526,6 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
assert(ramp != NULL); assert(ramp != NULL);
assert(ramp->size > 0); assert(ramp->size > 0);
assert(ramp->red != NULL); assert(ramp->red != NULL);
@ -529,6 +534,9 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
if (ramp->size <= 0) if (ramp->size <= 0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, _glfwInputError(GLFW_INVALID_VALUE,

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 macOS - www.glfw.org // GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
@ -30,6 +30,7 @@
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <math.h>
#include <assert.h>
static void makeContextCurrentNSGL(_GLFWwindow* window) static void makeContextCurrentNSGL(_GLFWwindow* window)
{ {
@ -127,8 +128,6 @@ static void destroyContextNSGL(_GLFWwindow* window)
////// GLFW internal API ////// ////// GLFW internal API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Initialize OpenGL support
//
GLFWbool _glfwInitNSGL(void) GLFWbool _glfwInitNSGL(void)
{ {
if (_glfw.nsgl.framework) if (_glfw.nsgl.framework)
@ -146,14 +145,10 @@ GLFWbool _glfwInitNSGL(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Terminate OpenGL support
//
void _glfwTerminateNSGL(void) void _glfwTerminateNSGL(void)
{ {
} }
// Create the OpenGL context
//
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window, GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
@ -182,16 +177,16 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
return GLFW_FALSE; return GLFW_FALSE;
} }
// Context robustness modes (GL_KHR_robustness) are not yet supported by // Context robustness modes (GL_KHR_robustness) are not supported by
// macOS but are not a hard constraint, so ignore and continue // macOS but are not a hard constraint, so ignore and continue
// Context release behaviors (GL_KHR_context_flush_control) are not yet // Context release behaviors (GL_KHR_context_flush_control) are not
// supported by macOS but are not a hard constraint, so ignore and continue // supported by macOS but are not a hard constraint, so ignore and continue
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not // Debug contexts (GL_KHR_debug) are not supported by macOS but are not
// a hard constraint, so ignore and continue // a hard constraint, so ignore and continue
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but // No-error contexts (GL_KHR_no_error) are not supported by macOS but
// are not a hard constraint, so ignore and continue // are not a hard constraint, so ignore and continue
#define ADD_ATTRIB(a) \ #define ADD_ATTRIB(a) \
@ -217,14 +212,11 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching); ADD_ATTRIB(kCGLPFASupportsAutomaticGraphicsSwitching);
} }
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
if (ctxconfig->major >= 4) if (ctxconfig->major >= 4)
{ {
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core); SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
} }
else else if (ctxconfig->major >= 3)
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
if (ctxconfig->major >= 3)
{ {
SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); SET_ATTRIB(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
} }
@ -361,7 +353,6 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle) GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(nil); _GLFW_REQUIRE_INIT_OR_RETURN(nil);
if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA) if (_glfw.platform.platformID != GLFW_PLATFORM_COCOA)
@ -371,6 +362,9 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
return nil; return nil;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@ -260,5 +260,6 @@ void _glfwTerminateNull(void)
free(_glfw.null.clipboardString); free(_glfw.null.clipboardString);
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
_glfwTerminateEGL(); _glfwTerminateEGL();
memset(&_glfw.null, 0, sizeof(_glfw.null));
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@ -156,6 +156,17 @@
#define GLFW_NULL_SC_MENU 120 #define GLFW_NULL_SC_MENU 120
#define GLFW_NULL_SC_LAST GLFW_NULL_SC_MENU #define GLFW_NULL_SC_LAST GLFW_NULL_SC_MENU
typedef VkFlags VkHeadlessSurfaceCreateFlagsEXT;
typedef struct VkHeadlessSurfaceCreateInfoEXT
{
VkStructureType sType;
const void* pNext;
VkHeadlessSurfaceCreateFlagsEXT flags;
} VkHeadlessSurfaceCreateInfoEXT;
typedef VkResult (APIENTRY *PFN_vkCreateHeadlessSurfaceEXT)(VkInstance,const VkHeadlessSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
// Null-specific per-window data // Null-specific per-window data
// //
typedef struct _GLFWwindowNull typedef struct _GLFWwindowNull

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -29,6 +28,7 @@
#include "internal.h" #include "internal.h"
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
static void applySizeLimits(_GLFWwindow* window, int* width, int* height) static void applySizeLimits(_GLFWwindow* window, int* width, int* height)
{ {
@ -60,12 +60,12 @@ static void fitToMonitor(_GLFWwindow* window)
window->null.height = mode.height; window->null.height = mode.height;
} }
static void acquireMonitorNull(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
_glfwInputMonitorWindow(window->monitor, window); _glfwInputMonitorWindow(window->monitor, window);
} }
static void releaseMonitorNull(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -148,7 +148,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
{ {
_glfwShowWindowNull(window); _glfwShowWindowNull(window);
_glfwFocusWindowNull(window); _glfwFocusWindowNull(window);
acquireMonitorNull(window); acquireMonitor(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -169,7 +169,7 @@ GLFWbool _glfwCreateWindowNull(_GLFWwindow* window,
void _glfwDestroyWindowNull(_GLFWwindow* window) void _glfwDestroyWindowNull(_GLFWwindow* window)
{ {
if (window->monitor) if (window->monitor)
releaseMonitorNull(window); releaseMonitor(window);
if (_glfw.null.focusedWindow == window) if (_glfw.null.focusedWindow == window)
_glfw.null.focusedWindow = NULL; _glfw.null.focusedWindow = NULL;
@ -204,14 +204,14 @@ void _glfwSetWindowMonitorNull(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitorNull(window); releaseMonitor(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
if (window->monitor) if (window->monitor)
{ {
window->null.visible = GLFW_TRUE; window->null.visible = GLFW_TRUE;
acquireMonitorNull(window); acquireMonitor(window);
fitToMonitor(window); fitToMonitor(window);
} }
else else
@ -341,7 +341,7 @@ void _glfwIconifyWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_TRUE); _glfwInputWindowIconify(window, GLFW_TRUE);
if (window->monitor) if (window->monitor)
releaseMonitorNull(window); releaseMonitor(window);
} }
} }
@ -353,7 +353,7 @@ void _glfwRestoreWindowNull(_GLFWwindow* window)
_glfwInputWindowIconify(window, GLFW_FALSE); _glfwInputWindowIconify(window, GLFW_FALSE);
if (window->monitor) if (window->monitor)
acquireMonitorNull(window); acquireMonitor(window);
} }
else if (window->null.maximized) else if (window->null.maximized)
{ {
@ -553,12 +553,15 @@ const char* _glfwGetClipboardStringNull(void)
EGLenum _glfwGetEGLPlatformNull(EGLint** attribs) EGLenum _glfwGetEGLPlatformNull(EGLint** attribs)
{ {
if (_glfw.egl.EXT_platform_base && _glfw.egl.MESA_platform_surfaceless)
return EGL_PLATFORM_SURFACELESS_MESA;
else
return 0; return 0;
} }
EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void) EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void)
{ {
return 0; return EGL_DEFAULT_DISPLAY;
} }
EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window) EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window)
@ -700,13 +703,18 @@ int _glfwGetKeyScancodeNull(int key)
void _glfwGetRequiredInstanceExtensionsNull(char** extensions) void _glfwGetRequiredInstanceExtensionsNull(char** extensions)
{ {
if (!_glfw.vk.KHR_surface || !_glfw.vk.EXT_headless_surface)
return;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_EXT_headless_surface";
} }
GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
return GLFW_FALSE; return GLFW_TRUE;
} }
VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, VkResult _glfwCreateWindowSurfaceNull(VkInstance instance,
@ -714,7 +722,28 @@ VkResult _glfwCreateWindowSurfaceNull(VkInstance instance,
const VkAllocationCallbacks* allocator, const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface) VkSurfaceKHR* surface)
{ {
// This seems like the most appropriate error to return here PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT =
(PFN_vkCreateHeadlessSurfaceEXT)
vkGetInstanceProcAddr(instance, "vkCreateHeadlessSurfaceEXT");
if (!vkCreateHeadlessSurfaceEXT)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Null: Vulkan instance missing VK_EXT_headless_surface extension");
return VK_ERROR_EXTENSION_NOT_PRESENT; return VK_ERROR_EXTENSION_NOT_PRESENT;
}
VkHeadlessSurfaceCreateInfoEXT sci;
memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_HEADLESS_SURFACE_CREATE_INFO_EXT;
const VkResult err = vkCreateHeadlessSurfaceEXT(instance, &sci, allocator, surface);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Null: Failed to create Vulkan surface: %s",
_glfwGetVulkanResultString(err));
}
return err;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 OSMesa - www.glfw.org // GLFW 3.5 OSMesa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
@ -180,11 +180,8 @@ GLFWbool _glfwInitOSMesa(void)
void _glfwTerminateOSMesa(void) void _glfwTerminateOSMesa(void)
{ {
if (_glfw.osmesa.handle)
{
_glfwPlatformFreeModule(_glfw.osmesa.handle); _glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL; _glfw.osmesa.handle = NULL;
}
} }
#define SET_ATTRIB(a, v) \ #define SET_ATTRIB(a, v) \
@ -296,11 +293,12 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
{ {
void* mesaBuffer; void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaFormat; GLint mesaWidth, mesaHeight, mesaFormat;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API) if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
@ -335,11 +333,12 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
{ {
void* mesaBuffer; void* mesaBuffer;
GLint mesaWidth, mesaHeight, mesaBytes; GLint mesaWidth, mesaHeight, mesaBytes;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API) if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
@ -369,9 +368,11 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle) GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_OSMESA_CONTEXT_API) if (window->context.source != GLFW_OSMESA_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -75,6 +74,15 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
return GLFW_FALSE; return GLFW_FALSE;
} }
// Only allow the Null platform if specifically requested
if (desiredID == GLFW_PLATFORM_NULL)
return _glfwConnectNull(desiredID, platform);
else if (count == 0)
{
_glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
return GLFW_FALSE;
}
#if defined(_GLFW_WAYLAND) && defined(_GLFW_X11) #if defined(_GLFW_WAYLAND) && defined(_GLFW_X11)
if (desiredID == GLFW_ANY_PLATFORM) if (desiredID == GLFW_ANY_PLATFORM)
{ {
@ -179,8 +187,6 @@ GLFWAPI const char* glfwGetVersionString(void)
" OSMesa" " OSMesa"
#if defined(__MINGW64_VERSION_MAJOR) #if defined(__MINGW64_VERSION_MAJOR)
" MinGW-w64" " MinGW-w64"
#elif defined(__MINGW32__)
" MinGW"
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
" VisualC" " VisualC"
#endif #endif

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@ -28,7 +28,7 @@
#if defined(GLFW_BUILD_WIN32_TIMER) || \ #if defined(GLFW_BUILD_WIN32_TIMER) || \
defined(GLFW_BUILD_WIN32_MODULE) || \ defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \ defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_COCOA_TIMER) || \ defined(GLFW_BUILD_MACOS_TIMER) || \
defined(GLFW_BUILD_POSIX_TIMER) || \ defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \ defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \ defined(GLFW_BUILD_POSIX_THREAD) || \
@ -184,7 +184,7 @@
#if defined(_WIN32) #if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER #define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__) #elif defined(__APPLE__)
#define GLFW_BUILD_COCOA_TIMER #define GLFW_BUILD_MACOS_TIMER
#else #else
#define GLFW_BUILD_POSIX_TIMER #define GLFW_BUILD_POSIX_TIMER
#endif #endif
@ -192,9 +192,9 @@
#if defined(GLFW_BUILD_WIN32_TIMER) #if defined(GLFW_BUILD_WIN32_TIMER)
#include "win32_time.h" #include "win32_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_COCOA_TIMER) #elif defined(GLFW_BUILD_MACOS_TIMER)
#include "cocoa_time.h" #include "macos_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_MACOS_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_POSIX_TIMER) #elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h" #include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
@ -207,6 +207,7 @@
#endif #endif
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11) #if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
#include "posix_poll.h"
#define GLFW_BUILD_POSIX_POLL #define GLFW_BUILD_POSIX_POLL
#endif #endif

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org>
// //
@ -41,6 +41,7 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module) void _glfwPlatformFreeModule(void* module)
{ {
if (module)
dlclose(module); dlclose(module);
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2022 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 POSIX - www.glfw.org // GLFW 3.5 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
@ -34,6 +34,40 @@
#define _GLFW_FIND_LOADER 1 #define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2 #define _GLFW_REQUIRE_LOADER 2
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
static void* loadLocalVulkanLoaderMacOS(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
#endif // __APPLE__
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW internal API ////// ////// GLFW internal API //////
@ -55,12 +89,12 @@ GLFWbool _glfwInitVulkan(int mode)
{ {
#if defined(_GLFW_VULKAN_LIBRARY) #if defined(_GLFW_VULKAN_LIBRARY)
_glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
#elif defined(_GLFW_WIN32) #elif defined(_WIN32)
_glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
#elif defined(_GLFW_COCOA) #elif defined(__APPLE__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle) if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); _glfw.vk.handle = loadLocalVulkanLoaderMacOS();
#elif defined(__OpenBSD__) || defined(__NetBSD__) #elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else #else
@ -129,19 +163,21 @@ GLFWbool _glfwInitVulkan(int mode)
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0) if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = GLFW_TRUE; _glfw.vk.KHR_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = GLFW_TRUE; _glfw.vk.KHR_win32_surface = true;
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = GLFW_TRUE; _glfw.vk.MVK_macos_surface = true;
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
_glfw.vk.EXT_metal_surface = GLFW_TRUE; _glfw.vk.EXT_metal_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = GLFW_TRUE; _glfw.vk.KHR_xlib_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = GLFW_TRUE; _glfw.vk.KHR_xcb_surface = true;
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE; _glfw.vk.KHR_wayland_surface = true;
else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0)
_glfw.vk.EXT_headless_surface = true;
} }
_glfw_free(ep); _glfw_free(ep);
@ -155,8 +191,8 @@ GLFWbool _glfwInitVulkan(int mode)
void _glfwTerminateVulkan(void) void _glfwTerminateVulkan(void)
{ {
if (_glfw.vk.handle)
_glfwPlatformFreeModule(_glfw.vk.handle); _glfwPlatformFreeModule(_glfw.vk.handle);
_glfw.vk.handle = NULL;
} }
const char* _glfwGetVulkanResultString(VkResult result) const char* _glfwGetVulkanResultString(VkResult result)
@ -272,11 +308,11 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device, VkPhysicalDevice device,
uint32_t queuefamily) uint32_t queuefamily)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
assert(instance != VK_NULL_HANDLE); assert(instance != VK_NULL_HANDLE);
assert(device != VK_NULL_HANDLE); assert(device != VK_NULL_HANDLE);
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return GLFW_FALSE; return GLFW_FALSE;
@ -297,15 +333,16 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
const VkAllocationCallbacks* allocator, const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface) VkSurfaceKHR* surface)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(instance != VK_NULL_HANDLE);
assert(window != NULL);
assert(surface != NULL); assert(surface != NULL);
*surface = VK_NULL_HANDLE; *surface = VK_NULL_HANDLE;
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(instance != VK_NULL_HANDLE);
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
return VK_ERROR_INITIALIZATION_FAILED; return VK_ERROR_INITIALIZATION_FAILED;

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 WGL - www.glfw.org // GLFW 3.5 WGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -186,28 +186,22 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB); u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB); u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
u->stereo = FIND_ATTRIB_VALUE(WGL_STEREO_ARB);
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample) if (_glfw.wgl.ARB_multisample)
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB); u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API) if (ctxconfig->client == GLFW_OPENGL_API)
{ {
if (_glfw.wgl.ARB_framebuffer_sRGB || if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
_glfw.wgl.EXT_framebuffer_sRGB) u->sRGB = FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
{
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
} }
else else
{ {
if (_glfw.wgl.EXT_colorspace) if (_glfw.wgl.EXT_colorspace)
{ {
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT) if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = GLFW_TRUE; u->sRGB = true;
} }
} }
} }
@ -261,9 +255,7 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = pfd.cAccumAlphaBits; u->accumAlphaBits = pfd.cAccumAlphaBits;
u->auxBuffers = pfd.cAuxBuffers; u->auxBuffers = pfd.cAuxBuffers;
u->stereo = (pfd.dwFlags & PFD_STEREO);
if (pfd.dwFlags & PFD_STEREO)
u->stereo = GLFW_TRUE;
} }
u->handle = pixelFormat; u->handle = pixelFormat;
@ -327,8 +319,8 @@ static void swapBuffersWGL(_GLFWwindow* window)
{ {
if (!window->monitor) if (!window->monitor)
{ {
// HACK: Use DwmFlush when desktop composition is enabled on Windows Vista and 7 // HACK: Use DwmFlush when desktop composition is enabled on Windows 7
if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) if (!IsWindows8OrGreater())
{ {
BOOL enabled = FALSE; BOOL enabled = FALSE;
@ -353,9 +345,9 @@ static void swapIntervalWGL(int interval)
if (!window->monitor) if (!window->monitor)
{ {
// HACK: Disable WGL swap interval when desktop composition is enabled on Windows // HACK: Disable WGL swap interval when desktop composition is enabled on
// Vista and 7 to avoid interfering with DWM vsync // Windows 7 to avoid interfering with DWM vsync
if (!IsWindows8OrGreater() && IsWindowsVistaOrGreater()) if (!IsWindows8OrGreater())
{ {
BOOL enabled = FALSE; BOOL enabled = FALSE;
@ -401,8 +393,6 @@ static void destroyContextWGL(_GLFWwindow* window)
} }
} }
// Initialize WGL
//
GLFWbool _glfwInitWGL(void) GLFWbool _glfwInitWGL(void)
{ {
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
@ -521,12 +511,10 @@ GLFWbool _glfwInitWGL(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Terminate WGL
//
void _glfwTerminateWGL(void) void _glfwTerminateWGL(void)
{ {
if (_glfw.wgl.instance)
_glfwPlatformFreeModule(_glfw.wgl.instance); _glfwPlatformFreeModule(_glfw.wgl.instance);
_glfw.wgl.instance = NULL;
} }
#define SET_ATTRIB(a, v) \ #define SET_ATTRIB(a, v) \
@ -536,8 +524,6 @@ void _glfwTerminateWGL(void)
attribs[index++] = v; \ attribs[index++] = v; \
} }
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig) const _GLFWfbconfig* fbconfig)
@ -670,7 +656,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->noerror) if (ctxconfig->noerror)
{ {
if (_glfw.wgl.ARB_create_context_no_error) if (_glfw.wgl.ARB_create_context_no_error)
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE); SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
} }
// NOTE: Only request an explicitly versioned context when necessary, as // NOTE: Only request an explicitly versioned context when necessary, as
@ -775,7 +761,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle) GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
@ -785,6 +770,9 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
return NULL; return NULL;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (window->context.source != GLFW_NATIVE_CONTEXT_API) if (window->context.source != GLFW_NATIVE_CONTEXT_API)
{ {
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -90,10 +89,6 @@ static GLFWbool loadLibraries(void)
return GLFW_FALSE; return GLFW_FALSE;
} }
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling) _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
_glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext) _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
@ -171,32 +166,9 @@ static GLFWbool loadLibraries(void)
return GLFW_TRUE; return GLFW_TRUE;
} }
// Unload used libraries (DLLs)
//
static void freeLibraries(void)
{
if (_glfw.win32.xinput.instance)
_glfwPlatformFreeModule(_glfw.win32.xinput.instance);
if (_glfw.win32.dinput8.instance)
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
if (_glfw.win32.user32.instance)
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
if (_glfw.win32.dwmapi.instance)
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
if (_glfw.win32.shcore.instance)
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
}
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTablesWin32(void) static void createKeyTables(void)
{ {
int scancode; int scancode;
@ -533,7 +505,8 @@ void _glfwUpdateKeyNamesWin32(void)
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
{ {
const UINT vks[] = { const UINT vks[] =
{
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
@ -686,14 +659,14 @@ int _glfwInitWin32(void)
if (!loadLibraries()) if (!loadLibraries())
return GLFW_FALSE; return GLFW_FALSE;
createKeyTablesWin32(); createKeyTables();
_glfwUpdateKeyNamesWin32(); _glfwUpdateKeyNamesWin32();
if (_glfwIsWindows10Version1703OrGreaterWin32()) if (_glfwIsWindows10Version1703OrGreaterWin32())
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (IsWindows8Point1OrGreater()) else if (IsWindows8Point1OrGreater())
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
else if (IsWindowsVistaOrGreater()) else
SetProcessDPIAware(); SetProcessDPIAware();
if (!createHelperWindow()) if (!createHelperWindow())
@ -725,7 +698,14 @@ void _glfwTerminateWin32(void)
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
freeLibraries(); _glfwPlatformFreeModule(_glfw.win32.xinput.instance);
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
memset(&_glfw.win32, 0, sizeof(_glfw.win32));
} }
#endif // _GLFW_WIN32 #endif // _GLFW_WIN32

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2021 Camilla Löwy <elmindreda@glfw.org>
// //
@ -39,6 +39,7 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module) void _glfwPlatformFreeModule(void* module)
{ {
if (module)
FreeLibrary((HMODULE) module); FreeLibrary((HMODULE) module);
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -33,6 +33,7 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <wchar.h> #include <wchar.h>
#include <assert.h>
// Callback for EnumDisplayMonitors in createMonitor // Callback for EnumDisplayMonitors in createMonitor
@ -539,7 +540,6 @@ void _glfwSetGammaRampWin32(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle) GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
@ -548,12 +548,14 @@ GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
return NULL; return NULL;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->win32.publicAdapterName; return monitor->win32.publicAdapterName;
} }
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle) GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
@ -562,6 +564,9 @@ GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
return NULL; return NULL;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->win32.publicDisplayName; return monitor->win32.publicDisplayName;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -48,14 +48,14 @@
#define UNICODE #define UNICODE
#endif #endif
// GLFW requires Windows XP or later // GLFW requires Windows 7 or later
#if WINVER < 0x0501 #if WINVER < 0x0601
#undef WINVER #undef WINVER
#define WINVER 0x0501 #define WINVER 0x0601
#endif #endif
#if _WIN32_WINNT < 0x0501 #if _WIN32_WINNT < 0x0601
#undef _WIN32_WINNT #undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 #define _WIN32_WINNT 0x0601
#endif #endif
// GLFW uses DirectInput8 interfaces // GLFW uses DirectInput8 interfaces
@ -66,41 +66,21 @@
#include <wctype.h> #include <wctype.h>
#include <windows.h> #include <windows.h>
#include <dwmapi.h>
#include <dinput.h> #include <dinput.h>
#include <xinput.h> #include <xinput.h>
#include <dbt.h> #include <dbt.h>
// HACK: Define macros that some windows.h variants don't // HACK: Define macros that some windows.h variants don't
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
#ifndef WM_DWMCOMPOSITIONCHANGED
#define WM_DWMCOMPOSITIONCHANGED 0x031E
#endif
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
#endif
#ifndef WM_COPYGLOBALDATA #ifndef WM_COPYGLOBALDATA
#define WM_COPYGLOBALDATA 0x0049 #define WM_COPYGLOBALDATA 0x0049
#endif #endif
#ifndef WM_UNICHAR
#define WM_UNICHAR 0x0109
#endif
#ifndef UNICODE_NOCHAR
#define UNICODE_NOCHAR 0xFFFF
#endif
#ifndef WM_DPICHANGED #ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0 #define WM_DPICHANGED 0x02E0
#endif #endif
#ifndef GET_XBUTTON_WPARAM
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
#endif
#ifndef EDS_ROTATEDMODE #ifndef EDS_ROTATEDMODE
#define EDS_ROTATEDMODE 0x00000004 #define EDS_ROTATEDMODE 0x00000004
#endif #endif
#ifndef DISPLAY_DEVICE_ACTIVE
#define DISPLAY_DEVICE_ACTIVE 0x00000001
#endif
#ifndef _WIN32_WINNT_WINBLUE #ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0603 #define _WIN32_WINNT_WINBLUE 0x0603
#endif #endif
@ -113,34 +93,6 @@
#ifndef USER_DEFAULT_SCREEN_DPI #ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96 #define USER_DEFAULT_SCREEN_DPI 96
#endif #endif
#ifndef OCR_HAND
#define OCR_HAND 32649
#endif
#if WINVER < 0x0601
typedef struct
{
DWORD cbSize;
DWORD ExtStatus;
} CHANGEFILTERSTRUCT;
#ifndef MSGFLT_ALLOW
#define MSGFLT_ALLOW 1
#endif
#endif /*Windows 7*/
#if WINVER < 0x0600
#define DWM_BB_ENABLE 0x00000001
#define DWM_BB_BLURREGION 0x00000002
typedef struct
{
DWORD dwFlags;
BOOL fEnable;
HRGN hRgnBlur;
BOOL fTransitionOnMaximized;
} DWM_BLURBEHIND;
#else
#include <dwmapi.h>
#endif /*Windows Vista*/
#ifndef DPI_ENUMS_DECLARED #ifndef DPI_ENUMS_DECLARED
typedef enum typedef enum
@ -165,12 +117,6 @@ typedef enum
// Replacement for versionhelpers.h macros, as we cannot rely on the // Replacement for versionhelpers.h macros, as we cannot rely on the
// application having a correct embedded manifest // application having a correct embedded manifest
// //
#define IsWindowsVistaOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0)
#define IsWindows7OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
LOBYTE(_WIN32_WINNT_WIN7), 0)
#define IsWindows8OrGreater() \ #define IsWindows8OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \ _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0) LOBYTE(_WIN32_WINNT_WIN8), 0)
@ -281,15 +227,11 @@ typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*
#define DirectInput8Create _glfw.win32.dinput8.Create #define DirectInput8Create _glfw.win32.dinput8.Create
// user32.dll function pointer typedefs // user32.dll function pointer typedefs
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND); typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE); typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND); typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT); typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT); typedef int (WINAPI * PFN_GetSystemMetricsForDpi)(int,UINT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_ #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_ #define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_ #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
@ -394,18 +336,18 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT; PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB; PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool EXT_swap_control; bool EXT_swap_control;
GLFWbool EXT_colorspace; bool EXT_colorspace;
GLFWbool ARB_multisample; bool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB; bool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB; bool EXT_framebuffer_sRGB;
GLFWbool ARB_pixel_format; bool ARB_pixel_format;
GLFWbool ARB_create_context; bool ARB_create_context;
GLFWbool ARB_create_context_profile; bool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile; bool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness; bool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error; bool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control; bool ARB_context_flush_control;
} _GLFWlibraryWGL; } _GLFWlibraryWGL;
// Win32-specific per-window data // Win32-specific per-window data
@ -475,8 +417,6 @@ typedef struct _GLFWlibraryWin32
struct { struct {
HINSTANCE instance; HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware_;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_; PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_; PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_; PFN_GetDpiForWindow GetDpiForWindow_;

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 - www.glfw.org // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 Win32 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 Win32 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -33,6 +32,7 @@
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <windowsx.h> #include <windowsx.h>
#include <shellapi.h> #include <shellapi.h>
@ -374,9 +374,6 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
BOOL composition, opaque; BOOL composition, opaque;
DWORD color; DWORD color;
if (!IsWindowsVistaOrGreater())
return;
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition) if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
return; return;
@ -440,7 +437,7 @@ static void fitToMonitor(_GLFWwindow* window)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitorWin32(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
if (!_glfw.win32.acquiredMonitorCount) if (!_glfw.win32.acquiredMonitorCount)
{ {
@ -461,7 +458,7 @@ static void acquireMonitorWin32(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitorWin32(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -471,7 +468,7 @@ static void releaseMonitorWin32(_GLFWwindow* window)
{ {
SetThreadExecutionState(ES_CONTINUOUS); SetThreadExecutionState(ES_CONTINUOUS);
// HACK: Restore mouse trail length saved in acquireMonitorWin32 // HACK: Restore mouse trail length saved in acquireMonitor
SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0); SystemParametersInfoW(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
} }
@ -714,11 +711,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
const int mods = getKeyMods(); const int mods = getKeyMods();
scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff)); scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
if (!scancode) if (!(scancode & 0xff))
{ {
// NOTE: Some synthetic key messages have a scancode of zero // NOTE: Both media keys and the synthetic key messages from Windows
// HACK: Map the virtual key back to a usable scancode // Clipboard History are reported with a scancode of zero
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC); // HACK: Map the virtual key to a scancode but preserve extended bit
scancode |= MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
} }
// HACK: Alt+PrtSc has a different scancode than just PrtSc // HACK: Alt+PrtSc has a different scancode than just PrtSc
@ -983,7 +981,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
case WM_MOUSEHWHEEL: case WM_MOUSEHWHEEL:
{ {
// This message is only sent on Windows Vista and later
// NOTE: The X-axis is inverted for consistency with macOS and X11 // NOTE: The X-axis is inverted for consistency with macOS and X11
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0); _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
return 0; return 0;
@ -1051,10 +1048,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
if (window->monitor && window->win32.iconified != iconified) if (window->monitor && window->win32.iconified != iconified)
{ {
if (iconified) if (iconified)
releaseMonitorWin32(window); releaseMonitor(window);
else else
{ {
acquireMonitorWin32(window); acquireMonitor(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1381,7 +1378,7 @@ static int createNativeWindow(_GLFWwindow* window,
frameHeight = rect.bottom - rect.top; frameHeight = rect.bottom - rect.top;
} }
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); wideTitle = _glfwCreateWideStringFromUTF8Win32(window->title);
if (!wideTitle) if (!wideTitle)
return GLFW_FALSE; return GLFW_FALSE;
@ -1407,15 +1404,9 @@ static int createNativeWindow(_GLFWwindow* window,
SetPropW(window->win32.handle, L"GLFW", window); SetPropW(window->win32.handle, L"GLFW", window);
if (IsWindows7OrGreater()) ChangeWindowMessageFilterEx(window->win32.handle, WM_DROPFILES, MSGFLT_ALLOW, NULL);
{ ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYDATA, MSGFLT_ALLOW, NULL);
ChangeWindowMessageFilterEx(window->win32.handle, ChangeWindowMessageFilterEx(window->win32.handle, WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
WM_DROPFILES, MSGFLT_ALLOW, NULL);
ChangeWindowMessageFilterEx(window->win32.handle,
WM_COPYDATA, MSGFLT_ALLOW, NULL);
ChangeWindowMessageFilterEx(window->win32.handle,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
window->win32.scaleToMonitor = wndconfig->scaleToMonitor; window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
window->win32.keymenu = wndconfig->win32.keymenu; window->win32.keymenu = wndconfig->win32.keymenu;
@ -1535,7 +1526,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
{ {
_glfwShowWindowWin32(window); _glfwShowWindowWin32(window);
_glfwFocusWindowWin32(window); _glfwFocusWindowWin32(window);
acquireMonitorWin32(window); acquireMonitor(window);
fitToMonitor(window); fitToMonitor(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
@ -1557,7 +1548,7 @@ GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
void _glfwDestroyWindowWin32(_GLFWwindow* window) void _glfwDestroyWindowWin32(_GLFWwindow* window)
{ {
if (window->monitor) if (window->monitor)
releaseMonitorWin32(window); releaseMonitor(window);
if (window->context.destroy) if (window->context.destroy)
window->context.destroy(window); window->context.destroy(window);
@ -1678,7 +1669,7 @@ void _glfwSetWindowSizeWin32(_GLFWwindow* window, int width, int height)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
{ {
acquireMonitorWin32(window); acquireMonitor(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1850,7 +1841,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
{ {
if (monitor->window == window) if (monitor->window == window)
{ {
acquireMonitorWin32(window); acquireMonitor(window);
fitToMonitor(window); fitToMonitor(window);
} }
} }
@ -1880,7 +1871,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
} }
if (window->monitor) if (window->monitor)
releaseMonitorWin32(window); releaseMonitor(window);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -1898,7 +1889,7 @@ void _glfwSetWindowMonitorWin32(_GLFWwindow* window,
flags |= SWP_FRAMECHANGED; flags |= SWP_FRAMECHANGED;
} }
acquireMonitorWin32(window); acquireMonitor(window);
GetMonitorInfoW(window->monitor->win32.handle, &mi); GetMonitorInfoW(window->monitor->win32.handle, &mi);
SetWindowPos(window->win32.handle, HWND_TOPMOST, SetWindowPos(window->win32.handle, HWND_TOPMOST,
@ -1981,9 +1972,6 @@ GLFWbool _glfwFramebufferTransparentWin32(_GLFWwindow* window)
if (!window->win32.transparent) if (!window->win32.transparent)
return GLFW_FALSE; return GLFW_FALSE;
if (!IsWindowsVistaOrGreater())
return GLFW_FALSE;
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition) if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
return GLFW_FALSE; return GLFW_FALSE;
@ -2577,7 +2565,6 @@ VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance,
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle) GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32) if (_glfw.platform.platformID != GLFW_PLATFORM_WIN32)
@ -2587,6 +2574,9 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
return NULL; return NULL;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
return window->win32.handle; return window->win32.handle;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 - www.glfw.org // GLFW 3.5 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -32,7 +32,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <float.h> #include <float.h>
#include <math.h>
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW event API ////// ////// GLFW event API //////
@ -135,9 +135,9 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
{ {
assert(window != NULL); assert(window != NULL);
assert(xscale > 0.f); assert(xscale > 0.f);
assert(xscale < FLT_MAX); assert(isfinite(xscale));
assert(yscale > 0.f); assert(yscale > 0.f);
assert(yscale < FLT_MAX); assert(isfinite(yscale));
if (window->callbacks.scale) if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale); window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
@ -208,7 +208,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
wndconfig.width = width; wndconfig.width = width;
wndconfig.height = height; wndconfig.height = height;
wndconfig.title = title;
ctxconfig.share = (_GLFWwindow*) share; ctxconfig.share = (_GLFWwindow*) share;
if (!_glfwIsValidContextConfig(&ctxconfig)) if (!_glfwIsValidContextConfig(&ctxconfig))
@ -266,16 +265,16 @@ void glfwDefaultWindowHints(void)
// The default is a focused, visible, resizable window with decorations // The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window)); memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.resizable = GLFW_TRUE; _glfw.hints.window.resizable = true;
_glfw.hints.window.visible = GLFW_TRUE; _glfw.hints.window.visible = true;
_glfw.hints.window.decorated = GLFW_TRUE; _glfw.hints.window.decorated = true;
_glfw.hints.window.focused = GLFW_TRUE; _glfw.hints.window.focused = true;
_glfw.hints.window.autoIconify = GLFW_TRUE; _glfw.hints.window.autoIconify = true;
_glfw.hints.window.centerCursor = GLFW_TRUE; _glfw.hints.window.centerCursor = true;
_glfw.hints.window.focusOnShow = GLFW_TRUE; _glfw.hints.window.focusOnShow = true;
_glfw.hints.window.xpos = GLFW_ANY_POSITION; _glfw.hints.window.xpos = GLFW_ANY_POSITION;
_glfw.hints.window.ypos = GLFW_ANY_POSITION; _glfw.hints.window.ypos = GLFW_ANY_POSITION;
_glfw.hints.window.scaleFramebuffer = GLFW_TRUE; _glfw.hints.window.scaleFramebuffer = true;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered // double buffered
@ -286,7 +285,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.framebuffer.alphaBits = 8; _glfw.hints.framebuffer.alphaBits = 8;
_glfw.hints.framebuffer.depthBits = 24; _glfw.hints.framebuffer.depthBits = 24;
_glfw.hints.framebuffer.stencilBits = 8; _glfw.hints.framebuffer.stencilBits = 8;
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE; _glfw.hints.framebuffer.doublebuffer = true;
// The default is to select the highest available refresh rate // The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE; _glfw.hints.refreshRate = GLFW_DONT_CARE;
@ -332,40 +331,40 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.framebuffer.auxBuffers = value; _glfw.hints.framebuffer.auxBuffers = value;
return; return;
case GLFW_STEREO: case GLFW_STEREO:
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.stereo = value;
return; return;
case GLFW_DOUBLEBUFFER: case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.doublebuffer = value;
return; return;
case GLFW_TRANSPARENT_FRAMEBUFFER: case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.transparent = value;
return; return;
case GLFW_SAMPLES: case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = value; _glfw.hints.framebuffer.samples = value;
return; return;
case GLFW_SRGB_CAPABLE: case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.framebuffer.sRGB = value;
return; return;
case GLFW_RESIZABLE: case GLFW_RESIZABLE:
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.resizable = value;
return; return;
case GLFW_DECORATED: case GLFW_DECORATED:
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.decorated = value;
return; return;
case GLFW_FOCUSED: case GLFW_FOCUSED:
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.focused = value;
return; return;
case GLFW_AUTO_ICONIFY: case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.autoIconify = value;
return; return;
case GLFW_FLOATING: case GLFW_FLOATING:
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.floating = value;
return; return;
case GLFW_MAXIMIZED: case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.maximized = value;
return; return;
case GLFW_VISIBLE: case GLFW_VISIBLE:
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.visible = value;
return; return;
case GLFW_POSITION_X: case GLFW_POSITION_X:
_glfw.hints.window.xpos = value; _glfw.hints.window.xpos = value;
@ -374,29 +373,29 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.window.ypos = value; _glfw.hints.window.ypos = value;
return; return;
case GLFW_WIN32_KEYBOARD_MENU: case GLFW_WIN32_KEYBOARD_MENU:
_glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.win32.keymenu = value;
return; return;
case GLFW_WIN32_SHOWDEFAULT: case GLFW_WIN32_SHOWDEFAULT:
_glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.win32.showDefault = value;
return; return;
case GLFW_COCOA_GRAPHICS_SWITCHING: case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.nsgl.offline = value;
return; return;
case GLFW_SCALE_TO_MONITOR: case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.scaleToMonitor = value;
return; return;
case GLFW_SCALE_FRAMEBUFFER: case GLFW_SCALE_FRAMEBUFFER:
case GLFW_COCOA_RETINA_FRAMEBUFFER: case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.scaleFramebuffer = value;
return; return;
case GLFW_CENTER_CURSOR: case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.centerCursor = value;
return; return;
case GLFW_FOCUS_ON_SHOW: case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.focusOnShow = value;
return; return;
case GLFW_MOUSE_PASSTHROUGH: case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.window.mousePassthrough = value;
return; return;
case GLFW_CLIENT_API: case GLFW_CLIENT_API:
_glfw.hints.context.client = value; _glfw.hints.context.client = value;
@ -414,13 +413,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.context.robustness = value; _glfw.hints.context.robustness = value;
return; return;
case GLFW_OPENGL_FORWARD_COMPAT: case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.forward = value;
return; return;
case GLFW_CONTEXT_DEBUG: case GLFW_CONTEXT_DEBUG:
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.debug = value;
return; return;
case GLFW_CONTEXT_NO_ERROR: case GLFW_CONTEXT_NO_ERROR:
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE; _glfw.hints.context.noerror = value;
return; return;
case GLFW_OPENGL_PROFILE: case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = value; _glfw.hints.context.profile = value;
@ -467,10 +466,10 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value)
GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
// Allow closing of NULL (to match the behavior of free) // Allow closing of NULL (to match the behavior of free)
if (window == NULL) if (window == NULL)
return; return;
@ -501,40 +500,43 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return window->shouldClose; return window->shouldClose;
} }
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
window->shouldClose = value; window->shouldClose = value;
} }
GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle) GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->title; return window->title;
} }
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(title != NULL); assert(title != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
char* prev = window->title; char* prev = window->title;
window->title = _glfw_strdup(title); window->title = _glfw_strdup(title);
@ -546,14 +548,15 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
int count, const GLFWimage* images) int count, const GLFWimage* images)
{ {
int i; int i;
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(count >= 0); assert(count >= 0);
assert(count == 0 || images != NULL); assert(count == 0 || images != NULL);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (count < 0) if (count < 0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon"); _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");
@ -577,25 +580,26 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (xpos) if (xpos)
*xpos = 0; *xpos = 0;
if (ypos) if (ypos)
*ypos = 0; *ypos = 0;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_glfw.platform.getWindowPos(window, xpos, ypos); _glfw.platform.getWindowPos(window, xpos, ypos);
} }
GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->monitor) if (window->monitor)
return; return;
@ -604,27 +608,29 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (width) if (width)
*width = 0; *width = 0;
if (height) if (height)
*height = 0; *height = 0;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_glfw.platform.getWindowSize(window, width, height); _glfw.platform.getWindowSize(window, width, height);
} }
GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(width >= 0); assert(width >= 0);
assert(height >= 0); assert(height >= 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
window->videoMode.width = width; window->videoMode.width = width;
window->videoMode.height = height; window->videoMode.height = height;
@ -635,11 +641,11 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
int minwidth, int minheight, int minwidth, int minheight,
int maxwidth, int maxheight) int maxwidth, int maxheight)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE)
{ {
if (minwidth < 0 || minheight < 0) if (minwidth < 0 || minheight < 0)
@ -678,13 +684,14 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom) GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
assert(numer != 0); assert(numer != 0);
assert(denom != 0); assert(denom != 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE) if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
{ {
if (numer <= 0 || denom <= 0) if (numer <= 0 || denom <= 0)
@ -707,15 +714,16 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (width) if (width)
*width = 0; *width = 0;
if (height) if (height)
*height = 0; *height = 0;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_glfw.platform.getFramebufferSize(window, width, height); _glfw.platform.getFramebufferSize(window, width, height);
} }
@ -723,9 +731,6 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
int* left, int* top, int* left, int* top,
int* right, int* bottom) int* right, int* bottom)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (left) if (left)
*left = 0; *left = 0;
if (top) if (top)
@ -736,44 +741,51 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
*bottom = 0; *bottom = 0;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_glfw.platform.getWindowFrameSize(window, left, top, right, bottom); _glfw.platform.getWindowFrameSize(window, left, top, right, bottom);
} }
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (xscale) if (xscale)
*xscale = 0.f; *xscale = 0.f;
if (yscale) if (yscale)
*yscale = 0.f; *yscale = 0.f;
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
_glfw.platform.getWindowContentScale(window, xscale, yscale); _glfw.platform.getWindowContentScale(window, xscale, yscale);
} }
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle) GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0.f);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0.f);
return _glfw.platform.getWindowOpacity(window); return _glfw.platform.getWindowOpacity(window);
} }
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity) GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle; assert(isfinite(opacity));
assert(window != NULL);
assert(opacity == opacity);
assert(opacity >= 0.f); assert(opacity >= 0.f);
assert(opacity <= 1.f); assert(opacity <= 1.f);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
if (opacity != opacity || opacity < 0.f || opacity > 1.f) _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (!isfinite(opacity) || opacity < 0.f || opacity > 1.f)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity); _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
return; return;
@ -784,29 +796,31 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfw.platform.iconifyWindow(window); _glfw.platform.iconifyWindow(window);
} }
GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfw.platform.restoreWindow(window); _glfw.platform.restoreWindow(window);
} }
GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle) GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->monitor) if (window->monitor)
return; return;
@ -815,11 +829,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
GLFWAPI void glfwShowWindow(GLFWwindow* handle) GLFWAPI void glfwShowWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->monitor) if (window->monitor)
return; return;
@ -831,21 +845,21 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfw.platform.requestWindowAttention(window); _glfw.platform.requestWindowAttention(window);
} }
GLFWAPI void glfwHideWindow(GLFWwindow* handle) GLFWAPI void glfwHideWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
if (window->monitor) if (window->monitor)
return; return;
@ -854,21 +868,21 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle)
GLFWAPI void glfwFocusWindow(GLFWwindow* handle) GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
_glfw.platform.focusWindow(window); _glfw.platform.focusWindow(window);
} }
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(0);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(0);
switch (attrib) switch (attrib)
{ {
case GLFW_FOCUSED: case GLFW_FOCUSED:
@ -927,11 +941,11 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
value = value ? GLFW_TRUE : GLFW_FALSE; value = value ? GLFW_TRUE : GLFW_FALSE;
switch (attrib) switch (attrib)
@ -973,10 +987,11 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return (GLFWmonitor*) window->monitor; return (GLFWmonitor*) window->monitor;
} }
@ -986,14 +1001,15 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
int width, int height, int width, int height,
int refreshRate) int refreshRate)
{ {
_GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window != NULL);
assert(width >= 0); assert(width >= 0);
assert(height >= 0); assert(height >= 0);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window != NULL);
if (width <= 0 || height <= 0) if (width <= 0 || height <= 0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, _glfwInputError(GLFW_INVALID_VALUE,
@ -1021,29 +1037,32 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
{ {
_GLFW_REQUIRE_INIT();
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT();
window->userPointer = pointer; window->userPointer = pointer;
} }
GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->userPointer; return window->userPointer;
} }
GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle, GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
GLFWwindowposfun cbfun) GLFWwindowposfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun); _GLFW_SWAP(GLFWwindowposfun, window->callbacks.pos, cbfun);
return cbfun; return cbfun;
} }
@ -1051,10 +1070,11 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle, GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
GLFWwindowsizefun cbfun) GLFWwindowsizefun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun); _GLFW_SWAP(GLFWwindowsizefun, window->callbacks.size, cbfun);
return cbfun; return cbfun;
} }
@ -1062,10 +1082,11 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle, GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
GLFWwindowclosefun cbfun) GLFWwindowclosefun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun); _GLFW_SWAP(GLFWwindowclosefun, window->callbacks.close, cbfun);
return cbfun; return cbfun;
} }
@ -1073,10 +1094,11 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle, GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
GLFWwindowrefreshfun cbfun) GLFWwindowrefreshfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun); _GLFW_SWAP(GLFWwindowrefreshfun, window->callbacks.refresh, cbfun);
return cbfun; return cbfun;
} }
@ -1084,10 +1106,11 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
GLFWwindowfocusfun cbfun) GLFWwindowfocusfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun); _GLFW_SWAP(GLFWwindowfocusfun, window->callbacks.focus, cbfun);
return cbfun; return cbfun;
} }
@ -1095,10 +1118,11 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
GLFWwindowiconifyfun cbfun) GLFWwindowiconifyfun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun); _GLFW_SWAP(GLFWwindowiconifyfun, window->callbacks.iconify, cbfun);
return cbfun; return cbfun;
} }
@ -1106,10 +1130,11 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle, GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
GLFWwindowmaximizefun cbfun) GLFWwindowmaximizefun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun); _GLFW_SWAP(GLFWwindowmaximizefun, window->callbacks.maximize, cbfun);
return cbfun; return cbfun;
} }
@ -1117,10 +1142,11 @@ GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle, GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
GLFWframebuffersizefun cbfun) GLFWframebuffersizefun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun); _GLFW_SWAP(GLFWframebuffersizefun, window->callbacks.fbsize, cbfun);
return cbfun; return cbfun;
} }
@ -1128,10 +1154,11 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle, GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
GLFWwindowcontentscalefun cbfun) GLFWwindowcontentscalefun cbfun)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFWwindow* window = (_GLFWwindow*) handle; _GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL); assert(window != NULL);
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun); _GLFW_SWAP(GLFWwindowcontentscalefun, window->callbacks.scale, cbfun);
return cbfun; return cbfun;
} }
@ -1151,11 +1178,10 @@ GLFWAPI void glfwWaitEvents(void)
GLFWAPI void glfwWaitEventsTimeout(double timeout) GLFWAPI void glfwWaitEventsTimeout(double timeout)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
assert(timeout == timeout); assert(isfinite(timeout));
assert(timeout >= 0.0); assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX) if (!isfinite(timeout) || timeout < 0.0)
{ {
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout); _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
return; return;

View file

@ -1,8 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.4 Wayland (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 Wayland - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -136,7 +135,7 @@ static void registryHandleGlobal(void* userData,
{ {
_glfw.wl.seat = _glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface, wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(4, version)); _glfw_min(8, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat); _glfwAddSeatListenerWayland(_glfw.wl.seat);
} }
} }
@ -245,10 +244,7 @@ static void libdecorReadyCallback(void* userData,
uint32_t time) uint32_t time)
{ {
_glfw.wl.libdecor.ready = GLFW_TRUE; _glfw.wl.libdecor.ready = GLFW_TRUE;
wl_callback_destroy(callback);
assert(_glfw.wl.libdecor.callback == callback);
wl_callback_destroy(_glfw.wl.libdecor.callback);
_glfw.wl.libdecor.callback = NULL;
} }
static const struct wl_callback_listener libdecorReadyListener = static const struct wl_callback_listener libdecorReadyListener =
@ -258,7 +254,7 @@ static const struct wl_callback_listener libdecorReadyListener =
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTablesWayland(void) static void createKeyTables(void)
{ {
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes)); memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes)); memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
@ -579,6 +575,14 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_get_fd"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_get_fd");
_glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read) _glfw.wl.client.display_prepare_read = (PFN_wl_display_prepare_read)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read");
_glfw.wl.client.display_create_queue = (PFN_wl_display_create_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_create_queue");
_glfw.wl.client.display_prepare_read_queue = (PFN_wl_display_prepare_read_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_prepare_read_queue");
_glfw.wl.client.display_dispatch_queue_pending = (PFN_wl_display_dispatch_queue_pending)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_display_dispatch_queue_pending");
_glfw.wl.client.event_queue_destroy = (PFN_wl_event_queue_destroy)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_event_queue_destroy");
_glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal) _glfw.wl.client.proxy_marshal = (PFN_wl_proxy_marshal)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal");
_glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener) _glfw.wl.client.proxy_add_listener = (PFN_wl_proxy_add_listener)
@ -601,6 +605,12 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_get_version");
_glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags) _glfw.wl.client.proxy_marshal_flags = (PFN_wl_proxy_marshal_flags)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_flags"); _glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_marshal_flags");
_glfw.wl.client.proxy_create_wrapper = (PFN_wl_proxy_create_wrapper)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_create_wrapper");
_glfw.wl.client.proxy_wrapper_destroy = (PFN_wl_proxy_wrapper_destroy)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_wrapper_destroy");
_glfw.wl.client.proxy_set_queue = (PFN_wl_proxy_set_queue)
_glfwPlatformGetModuleSymbol(_glfw.wl.client.handle, "wl_proxy_set_queue");
if (!_glfw.wl.client.display_flush || if (!_glfw.wl.client.display_flush ||
!_glfw.wl.client.display_cancel_read || !_glfw.wl.client.display_cancel_read ||
@ -610,6 +620,10 @@ int _glfwInitWayland(void)
!_glfw.wl.client.display_roundtrip || !_glfw.wl.client.display_roundtrip ||
!_glfw.wl.client.display_get_fd || !_glfw.wl.client.display_get_fd ||
!_glfw.wl.client.display_prepare_read || !_glfw.wl.client.display_prepare_read ||
!_glfw.wl.client.display_create_queue ||
!_glfw.wl.client.display_prepare_read_queue ||
!_glfw.wl.client.display_dispatch_queue_pending ||
!_glfw.wl.client.event_queue_destroy ||
!_glfw.wl.client.proxy_marshal || !_glfw.wl.client.proxy_marshal ||
!_glfw.wl.client.proxy_add_listener || !_glfw.wl.client.proxy_add_listener ||
!_glfw.wl.client.proxy_destroy || !_glfw.wl.client.proxy_destroy ||
@ -618,7 +632,10 @@ int _glfwInitWayland(void)
!_glfw.wl.client.proxy_get_user_data || !_glfw.wl.client.proxy_get_user_data ||
!_glfw.wl.client.proxy_set_user_data || !_glfw.wl.client.proxy_set_user_data ||
!_glfw.wl.client.proxy_get_tag || !_glfw.wl.client.proxy_get_tag ||
!_glfw.wl.client.proxy_set_tag) !_glfw.wl.client.proxy_set_tag ||
!_glfw.wl.client.proxy_create_wrapper ||
!_glfw.wl.client.proxy_wrapper_destroy ||
!_glfw.wl.client.proxy_set_queue)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load libwayland-client entry point"); "Wayland: Failed to load libwayland-client entry point");
@ -705,6 +722,10 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
_glfw.wl.xkb.keysym_to_utf32 = (PFN_xkb_keysym_to_utf32)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keysym_to_utf32");
_glfw.wl.xkb.keysym_to_utf8 = (PFN_xkb_keysym_to_utf8)
_glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keysym_to_utf8");
if (!_glfw.wl.xkb.context_new || if (!_glfw.wl.xkb.context_new ||
!_glfw.wl.xkb.context_unref || !_glfw.wl.xkb.context_unref ||
@ -777,6 +798,8 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities"); _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility) _glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility"); _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
_glfw.wl.libdecor.libdecor_frame_is_visible_ = (PFN_libdecor_frame_is_visible)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_is_visible");
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel) _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel"); _glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size) _glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
@ -808,6 +831,7 @@ int _glfwInitWayland(void)
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ || !_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ || !_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ || !_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
!_glfw.wl.libdecor.libdecor_frame_is_visible_ ||
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ || !_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ || !_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ || !_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
@ -822,9 +846,19 @@ int _glfwInitWayland(void)
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL); wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
createKeyTablesWayland(); createKeyTables();
_glfw.wl.xkb.context = xkb_context_new(0); _glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
if (_glfw.wl.keyRepeatTimerfd == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create timerfd: %s",
strerror(errno));
return GLFW_FALSE;
}
_glfw.wl.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!_glfw.wl.xkb.context) if (!_glfw.wl.xkb.context)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -847,19 +881,11 @@ int _glfwInitWayland(void)
libdecor_dispatch(_glfw.wl.libdecor.context, 0); libdecor_dispatch(_glfw.wl.libdecor.context, 0);
// Create sync point to "know" when libdecor is ready for use // Create sync point to "know" when libdecor is ready for use
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display); struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(_glfw.wl.libdecor.callback, wl_callback_add_listener(callback, &libdecorReadyListener, NULL);
&libdecorReadyListener,
NULL);
} }
} }
if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
if (!_glfw.wl.wmBase) if (!_glfw.wl.wmBase)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@ -903,18 +929,6 @@ void _glfwTerminateWayland(void)
libdecor_unref(_glfw.wl.libdecor.context); libdecor_unref(_glfw.wl.libdecor.context);
} }
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle)
{
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
if (_glfw.wl.xkb.composeState) if (_glfw.wl.xkb.composeState)
xkb_compose_state_unref(_glfw.wl.xkb.composeState); xkb_compose_state_unref(_glfw.wl.xkb.composeState);
if (_glfw.wl.xkb.keymap) if (_glfw.wl.xkb.keymap)
@ -923,21 +937,11 @@ void _glfwTerminateWayland(void)
xkb_state_unref(_glfw.wl.xkb.state); xkb_state_unref(_glfw.wl.xkb.state);
if (_glfw.wl.xkb.context) if (_glfw.wl.xkb.context)
xkb_context_unref(_glfw.wl.xkb.context); xkb_context_unref(_glfw.wl.xkb.context);
if (_glfw.wl.xkb.handle)
{
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursorTheme) if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme); wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorThemeHiDPI) if (_glfw.wl.cursorThemeHiDPI)
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI); wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
if (_glfw.wl.cursor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
for (unsigned int i = 0; i < _glfw.wl.offerCount; i++) for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
wl_data_offer_destroy(_glfw.wl.offers[i].offer); wl_data_offer_destroy(_glfw.wl.offers[i].offer);
@ -997,7 +1001,18 @@ void _glfwTerminateWayland(void)
if (_glfw.wl.cursorTimerfd >= 0) if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd); close(_glfw.wl.cursorTimerfd);
// Free modules only after all Wayland termination functions are called
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfwPlatformFreeModule(_glfw.wl.client.handle);
_glfw_free(_glfw.wl.clipboardString); _glfw_free(_glfw.wl.clipboardString);
memset(&_glfw.wl, 0, sizeof(_glfw.wl));
} }
#endif // _GLFW_WAYLAND #endif // _GLFW_WAYLAND

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Wayland - www.glfw.org // GLFW 3.5 Wayland - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@ -33,6 +33,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <assert.h>
#include "wayland-client-protocol.h" #include "wayland-client-protocol.h"
@ -258,7 +259,6 @@ void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle) GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND) if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
@ -267,6 +267,9 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
return NULL; return NULL;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->wl.output; return monitor->wl.output;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 Wayland - www.glfw.org // GLFW 3.5 Wayland - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@ -28,8 +28,6 @@
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-compose.h> #include <xkbcommon/xkbcommon-compose.h>
#include <stdbool.h>
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
typedef struct VkWaylandSurfaceCreateInfoKHR typedef struct VkWaylandSurfaceCreateInfoKHR
@ -44,9 +42,6 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "xkb_unicode.h"
#include "posix_poll.h"
typedef int (* PFN_wl_display_flush)(struct wl_display* display); typedef int (* PFN_wl_display_flush)(struct wl_display* display);
typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display); typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display);
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display); typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display);
@ -56,6 +51,10 @@ typedef void (* PFN_wl_display_disconnect)(struct wl_display*);
typedef int (* PFN_wl_display_roundtrip)(struct wl_display*); typedef int (* PFN_wl_display_roundtrip)(struct wl_display*);
typedef int (* PFN_wl_display_get_fd)(struct wl_display*); typedef int (* PFN_wl_display_get_fd)(struct wl_display*);
typedef int (* PFN_wl_display_prepare_read)(struct wl_display*); typedef int (* PFN_wl_display_prepare_read)(struct wl_display*);
typedef struct wl_event_queue* (* PFN_wl_display_create_queue)(struct wl_display*);
typedef void (* PFN_wl_event_queue_destroy)(struct wl_event_queue*);
typedef int (* PFN_wl_display_prepare_read_queue)(struct wl_display*,struct wl_event_queue*);
typedef int (* PFN_wl_display_dispatch_queue_pending)(struct wl_display*,struct wl_event_queue*);
typedef void (* PFN_wl_proxy_marshal)(struct wl_proxy*,uint32_t,...); typedef void (* PFN_wl_proxy_marshal)(struct wl_proxy*,uint32_t,...);
typedef int (* PFN_wl_proxy_add_listener)(struct wl_proxy*,void(**)(void),void*); typedef int (* PFN_wl_proxy_add_listener)(struct wl_proxy*,void(**)(void),void*);
typedef void (* PFN_wl_proxy_destroy)(struct wl_proxy*); typedef void (* PFN_wl_proxy_destroy)(struct wl_proxy*);
@ -67,6 +66,9 @@ typedef void (* PFN_wl_proxy_set_tag)(struct wl_proxy*,const char*const*);
typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*); typedef const char* const* (* PFN_wl_proxy_get_tag)(struct wl_proxy*);
typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*); typedef uint32_t (* PFN_wl_proxy_get_version)(struct wl_proxy*);
typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...); typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_t,const struct wl_interface*,uint32_t,uint32_t,...);
typedef void* (* PFN_wl_proxy_create_wrapper)(void*);
typedef void (* PFN_wl_proxy_wrapper_destroy)(void*);
typedef void (* PFN_wl_proxy_set_queue)(struct wl_proxy*,struct wl_event_queue*);
#define wl_display_flush _glfw.wl.client.display_flush #define wl_display_flush _glfw.wl.client.display_flush
#define wl_display_cancel_read _glfw.wl.client.display_cancel_read #define wl_display_cancel_read _glfw.wl.client.display_cancel_read
#define wl_display_dispatch_pending _glfw.wl.client.display_dispatch_pending #define wl_display_dispatch_pending _glfw.wl.client.display_dispatch_pending
@ -75,6 +77,10 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_display_roundtrip _glfw.wl.client.display_roundtrip #define wl_display_roundtrip _glfw.wl.client.display_roundtrip
#define wl_display_get_fd _glfw.wl.client.display_get_fd #define wl_display_get_fd _glfw.wl.client.display_get_fd
#define wl_display_prepare_read _glfw.wl.client.display_prepare_read #define wl_display_prepare_read _glfw.wl.client.display_prepare_read
#define wl_display_create_queue _glfw.wl.client.display_create_queue
#define wl_display_prepare_read_queue _glfw.wl.client.display_prepare_read_queue
#define wl_display_dispatch_queue_pending _glfw.wl.client.display_dispatch_queue_pending
#define wl_event_queue_destroy _glfw.wl.client.event_queue_destroy
#define wl_proxy_marshal _glfw.wl.client.proxy_marshal #define wl_proxy_marshal _glfw.wl.client.proxy_marshal
#define wl_proxy_add_listener _glfw.wl.client.proxy_add_listener #define wl_proxy_add_listener _glfw.wl.client.proxy_add_listener
#define wl_proxy_destroy _glfw.wl.client.proxy_destroy #define wl_proxy_destroy _glfw.wl.client.proxy_destroy
@ -86,6 +92,9 @@ typedef struct wl_proxy* (* PFN_wl_proxy_marshal_flags)(struct wl_proxy*,uint32_
#define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag #define wl_proxy_set_tag _glfw.wl.client.proxy_set_tag
#define wl_proxy_get_version _glfw.wl.client.proxy_get_version #define wl_proxy_get_version _glfw.wl.client.proxy_get_version
#define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags #define wl_proxy_marshal_flags _glfw.wl.client.proxy_marshal_flags
#define wl_proxy_create_wrapper _glfw.wl.client.proxy_create_wrapper
#define wl_proxy_wrapper_destroy _glfw.wl.client.proxy_wrapper_destroy
#define wl_proxy_set_queue _glfw.wl.client.proxy_set_queue
struct wl_shm; struct wl_shm;
struct wl_output; struct wl_output;
@ -139,18 +148,22 @@ struct wl_output;
#define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl; #define GLFW_WAYLAND_MONITOR_STATE _GLFWmonitorWayland wl;
#define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl; #define GLFW_WAYLAND_CURSOR_STATE _GLFWcursorWayland wl;
struct wl_cursor_image { struct wl_cursor_image
{
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t hotspot_x; uint32_t hotspot_x;
uint32_t hotspot_y; uint32_t hotspot_y;
uint32_t delay; uint32_t delay;
}; };
struct wl_cursor {
struct wl_cursor
{
unsigned int image_count; unsigned int image_count;
struct wl_cursor_image** images; struct wl_cursor_image** images;
char* name; char* name;
}; };
typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*); typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*); typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*); typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
@ -180,6 +193,8 @@ typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, con
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t); typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component); typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component);
typedef uint32_t (* PFN_xkb_keysym_to_utf32)(xkb_keysym_t);
typedef int (* PFN_xkb_keysym_to_utf8)(xkb_keysym_t, char*, size_t);
#define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_new _glfw.wl.xkb.context_new
#define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_context_unref _glfw.wl.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
@ -193,6 +208,8 @@ typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_inde
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout #define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active #define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active
#define xkb_keysym_to_utf32 _glfw.wl.xkb.keysym_to_utf32
#define xkb_keysym_to_utf8 _glfw.wl.xkb.keysym_to_utf8
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
@ -294,6 +311,7 @@ typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities); typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities); typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible); typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
typedef bool (* PFN_libdecor_frame_is_visible)(struct libdecor_frame*);
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*); typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*); typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*); typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
@ -319,6 +337,7 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_ #define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_ #define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_ #define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
#define libdecor_frame_is_visible _glfw.wl.libdecor.libdecor_frame_is_visible_
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ #define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_ #define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_ #define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
@ -355,14 +374,16 @@ typedef struct _GLFWwindowWayland
GLFWbool maximized; GLFWbool maximized;
GLFWbool activated; GLFWbool activated;
GLFWbool fullscreen; GLFWbool fullscreen;
GLFWbool hovered;
GLFWbool transparent; GLFWbool transparent;
GLFWbool scaleFramebuffer; GLFWbool scaleFramebuffer;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_callback* callback;
struct { struct {
struct wl_event_queue* queue;
struct wl_egl_window* window; struct wl_egl_window* window;
struct wl_callback* callback;
struct wl_surface* wrapper;
int interval;
} egl; } egl;
struct { struct {
@ -384,7 +405,6 @@ typedef struct _GLFWwindowWayland
struct libdecor_frame* frame; struct libdecor_frame* frame;
} libdecor; } libdecor;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY; double cursorPosX, cursorPosY;
char* appId; char* appId;
@ -411,7 +431,9 @@ typedef struct _GLFWwindowWayland
GLFWbool decorations; GLFWbool decorations;
struct wl_buffer* buffer; struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom; _GLFWfallbackEdgeWayland top, left, right, bottom;
struct wl_surface* focus; double pointerX, pointerY;
uint32_t buttonPressSerial;
const char* cursorName;
} fallback; } fallback;
} _GLFWwindowWayland; } _GLFWwindowWayland;
@ -450,10 +472,10 @@ typedef struct _GLFWlibraryWayland
const char* tag; const char* tag;
struct wl_surface* pointerSurface;
struct wl_cursor_theme* cursorTheme; struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI; struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface; struct wl_surface* cursorSurface;
const char* cursorPreviousName;
int cursorTimerfd; int cursorTimerfd;
uint32_t serial; uint32_t serial;
uint32_t pointerEnterSerial; uint32_t pointerEnterSerial;
@ -468,6 +490,19 @@ typedef struct _GLFWlibraryWayland
short int scancodes[GLFW_KEY_LAST + 1]; short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5]; char keynames[GLFW_KEY_LAST + 1][5];
struct {
struct wl_surface* pointerSurface;
unsigned int events;
double pointerX;
double pointerY;
double scrollX;
double scrollY;
double discreteX;
double discreteY;
int button;
int action;
} pending;
struct { struct {
void* handle; void* handle;
struct xkb_context* context; struct xkb_context* context;
@ -497,6 +532,8 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_state_update_mask state_update_mask; PFN_xkb_state_update_mask state_update_mask;
PFN_xkb_state_key_get_layout state_key_get_layout; PFN_xkb_state_key_get_layout state_key_get_layout;
PFN_xkb_state_mod_index_is_active state_mod_index_is_active; PFN_xkb_state_mod_index_is_active state_mod_index_is_active;
PFN_xkb_keysym_to_utf32 keysym_to_utf32;
PFN_xkb_keysym_to_utf8 keysym_to_utf8;
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_table_unref compose_table_unref;
@ -507,7 +544,6 @@ typedef struct _GLFWlibraryWayland
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
} xkb; } xkb;
_GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus; _GLFWwindow* keyboardFocus;
struct { struct {
@ -520,6 +556,10 @@ typedef struct _GLFWlibraryWayland
PFN_wl_display_roundtrip display_roundtrip; PFN_wl_display_roundtrip display_roundtrip;
PFN_wl_display_get_fd display_get_fd; PFN_wl_display_get_fd display_get_fd;
PFN_wl_display_prepare_read display_prepare_read; PFN_wl_display_prepare_read display_prepare_read;
PFN_wl_display_create_queue display_create_queue;
PFN_wl_display_prepare_read_queue display_prepare_read_queue;
PFN_wl_display_dispatch_queue_pending display_dispatch_queue_pending;
PFN_wl_event_queue_destroy event_queue_destroy;
PFN_wl_proxy_marshal proxy_marshal; PFN_wl_proxy_marshal proxy_marshal;
PFN_wl_proxy_add_listener proxy_add_listener; PFN_wl_proxy_add_listener proxy_add_listener;
PFN_wl_proxy_destroy proxy_destroy; PFN_wl_proxy_destroy proxy_destroy;
@ -531,6 +571,9 @@ typedef struct _GLFWlibraryWayland
PFN_wl_proxy_set_tag proxy_set_tag; PFN_wl_proxy_set_tag proxy_set_tag;
PFN_wl_proxy_get_version proxy_get_version; PFN_wl_proxy_get_version proxy_get_version;
PFN_wl_proxy_marshal_flags proxy_marshal_flags; PFN_wl_proxy_marshal_flags proxy_marshal_flags;
PFN_wl_proxy_create_wrapper proxy_create_wrapper;
PFN_wl_proxy_wrapper_destroy proxy_wrapper_destroy;
PFN_wl_proxy_set_queue proxy_set_queue;
} client; } client;
struct { struct {
@ -553,7 +596,6 @@ typedef struct _GLFWlibraryWayland
struct { struct {
void* handle; void* handle;
struct libdecor* context; struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready; GLFWbool ready;
PFN_libdecor_new libdecor_new_; PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_; PFN_libdecor_unref libdecor_unref_;
@ -575,6 +617,7 @@ typedef struct _GLFWlibraryWayland
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_; PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_; PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_; PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
PFN_libdecor_frame_is_visible libdecor_frame_is_visible_;
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_; PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_; PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_; PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
@ -689,3 +732,5 @@ void _glfwUpdateBufferScaleFromOutputsWayland(_GLFWwindow* window);
void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddSeatListenerWayland(struct wl_seat* seat);
void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
GLFWbool _glfwWaitForEGLFrameWayland(_GLFWwindow* window);

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -211,7 +210,7 @@ static int translateKeySyms(const KeySym* keysyms, int width)
// Create key code translation tables // Create key code translation tables
// //
static void createKeyTablesX11(void) static void createKeyTables(void)
{ {
int scancodeMin, scancodeMax; int scancodeMin, scancodeMax;
@ -536,6 +535,7 @@ static void detectEWMH(void)
XA_WINDOW, XA_WINDOW,
(unsigned char**) &windowFromChild)) (unsigned char**) &windowFromChild))
{ {
_glfwReleaseErrorHandlerX11();
XFree(windowFromRoot); XFree(windowFromRoot);
return; return;
} }
@ -909,7 +909,7 @@ static GLFWbool initExtensions(void)
// Update the key code LUT // Update the key code LUT
// FIXME: We should listen to XkbMapNotify events to track changes to // FIXME: We should listen to XkbMapNotify events to track changes to
// the keyboard mapping. // the keyboard mapping.
createKeyTablesX11(); createKeyTables();
// String format atoms // String format atoms
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
@ -1592,65 +1592,29 @@ void _glfwTerminateX11(void)
_glfw.x11.display = NULL; _glfw.x11.display = NULL;
} }
if (_glfw.x11.x11xcb.handle)
{
_glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
_glfw.x11.x11xcb.handle = NULL;
}
if (_glfw.x11.xcursor.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfw.x11.xcursor.handle = NULL;
}
if (_glfw.x11.randr.handle)
{
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfw.x11.randr.handle = NULL;
}
if (_glfw.x11.xinerama.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfw.x11.xinerama.handle = NULL;
}
if (_glfw.x11.xrender.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfw.x11.xrender.handle = NULL;
}
if (_glfw.x11.vidmode.handle)
{
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfw.x11.vidmode.handle = NULL;
}
if (_glfw.x11.xi.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfw.x11.xi.handle = NULL;
}
_glfwTerminateOSMesa(); _glfwTerminateOSMesa();
// NOTE: These need to be unloaded after XCloseDisplay, as they register // NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function // cleanup callbacks that get called by that function
_glfwTerminateEGL(); _glfwTerminateEGL();
_glfwTerminateGLX(); _glfwTerminateGLX();
if (_glfw.x11.xlib.handle) _glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
{ _glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfwPlatformFreeModule(_glfw.x11.xshape.handle);
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfwPlatformFreeModule(_glfw.x11.xlib.handle); _glfwPlatformFreeModule(_glfw.x11.xlib.handle);
_glfw.x11.xlib.handle = NULL;
}
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1]) if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
{ {
close(_glfw.x11.emptyEventPipe[0]); close(_glfw.x11.emptyEventPipe[0]);
close(_glfw.x11.emptyEventPipe[1]); close(_glfw.x11.emptyEventPipe[1]);
} }
memset(&_glfw.x11, 0, sizeof(_glfw.x11));
} }
#endif // _GLFW_X11 #endif // _GLFW_X11

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 - www.glfw.org // GLFW 3.5 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -33,6 +33,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <assert.h>
// Check whether the display mode should be included in enumeration // Check whether the display mode should be included in enumeration
@ -150,6 +151,12 @@ void _glfwPollMonitorsX11(void)
} }
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
if (!ci)
{
XRRFreeOutputInfo(oi);
continue;
}
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
{ {
widthMM = oi->mm_height; widthMM = oi->mm_height;
@ -611,7 +618,6 @@ void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle) GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11) if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -620,12 +626,14 @@ GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
return None; return None;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->x11.crtc; return monitor->x11.crtc;
} }
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle) GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11) if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -634,6 +642,9 @@ GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
return None; return None;
} }
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL);
return monitor->x11.output; return monitor->x11.output;
} }

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 - www.glfw.org // GLFW 3.5 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
@ -452,9 +452,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(V
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*); typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t); typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "xkb_unicode.h"
#include "posix_poll.h"
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11; #define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11; #define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
#define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11; #define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11;
@ -463,6 +460,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx; #define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx;
#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx; #define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
#define GLFW_INVALID_CODEPOINT 0xffffffffu
// GLX-specific per-context data // GLX-specific per-context data
// //
@ -470,6 +468,7 @@ typedef struct _GLFWcontextGLX
{ {
GLXContext handle; GLXContext handle;
GLXWindow window; GLXWindow window;
GLXFBConfig fbconfig;
} _GLFWcontextGLX; } _GLFWcontextGLX;
// GLX-specific global data // GLX-specific global data
@ -504,18 +503,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
GLFWbool SGI_swap_control; bool SGI_swap_control;
GLFWbool EXT_swap_control; bool EXT_swap_control;
GLFWbool MESA_swap_control; bool MESA_swap_control;
GLFWbool ARB_multisample; bool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB; bool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB; bool EXT_framebuffer_sRGB;
GLFWbool ARB_create_context; bool ARB_create_context;
GLFWbool ARB_create_context_profile; bool ARB_create_context_profile;
GLFWbool ARB_create_context_robustness; bool ARB_create_context_robustness;
GLFWbool EXT_create_context_es2_profile; bool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error; bool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control; bool ARB_context_flush_control;
} _GLFWlibraryGLX; } _GLFWlibraryGLX;
// X11-specific per-window data // X11-specific per-window data
@ -984,6 +983,8 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
unsigned char** value); unsigned char** value);
GLFWbool _glfwIsVisualTransparentX11(Visual* visual); GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym);
void _glfwGrabErrorHandlerX11(void); void _glfwGrabErrorHandlerX11(void);
void _glfwReleaseErrorHandlerX11(void); void _glfwReleaseErrorHandlerX11(void);
void _glfwInputErrorX11(int error, const char* message); void _glfwInputErrorX11(int error, const char* message);

View file

@ -1,9 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 (modified for raylib) - www.glfw.org; www.raylib.com // GLFW 3.5 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2024 M374LX <wilsalx@gmail.com>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@ -236,9 +235,9 @@ static int translateState(int state)
// Translates an X11 key code to a GLFW key token // Translates an X11 key code to a GLFW key token
// //
static int translateKeyX11(int scancode) static int translateKey(int scancode)
{ {
// Use the pre-filled LUT (see createKeyTablesX11() in x11_init.c) // Use the pre-filled LUT (see createKeyTables() in x11_init.c)
if (scancode < 0 || scancode > 255) if (scancode < 0 || scancode > 255)
return GLFW_KEY_UNKNOWN; return GLFW_KEY_UNKNOWN;
@ -577,6 +576,10 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
height *= _glfw.x11.contentScaleY; height *= _glfw.x11.contentScaleY;
} }
// The dimensions must be nonzero, or a BadValue error results.
width = _glfw_max(1, width);
height = _glfw_max(1, height);
int xpos = 0, ypos = 0; int xpos = 0, ypos = 0;
if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION) if (wndconfig->xpos != GLFW_ANY_POSITION && wndconfig->ypos != GLFW_ANY_POSITION)
@ -755,13 +758,13 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
const char* resourceName = getenv("RESOURCE_NAME"); const char* resourceName = getenv("RESOURCE_NAME");
if (resourceName && strlen(resourceName)) if (resourceName && strlen(resourceName))
hint->res_name = (char*) resourceName; hint->res_name = (char*) resourceName;
else if (strlen(wndconfig->title)) else if (strlen(window->title))
hint->res_name = (char*) wndconfig->title; hint->res_name = (char*) window->title;
else else
hint->res_name = (char*) "glfw-application"; hint->res_name = (char*) "glfw-application";
if (strlen(wndconfig->title)) if (strlen(window->title))
hint->res_class = (char*) wndconfig->title; hint->res_class = (char*) window->title;
else else
hint->res_class = (char*) "GLFW-Application"; hint->res_class = (char*) "GLFW-Application";
} }
@ -781,7 +784,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
if (_glfw.x11.im) if (_glfw.x11.im)
_glfwCreateInputContextX11(window); _glfwCreateInputContextX11(window);
_glfwSetWindowTitleX11(window, wndconfig->title); _glfwSetWindowTitleX11(window, window->title);
_glfwGetWindowPosX11(window, &window->x11.xpos, &window->x11.ypos); _glfwGetWindowPosX11(window, &window->x11.xpos, &window->x11.ypos);
_glfwGetWindowSizeX11(window, &window->x11.width, &window->x11.height); _glfwGetWindowSizeX11(window, &window->x11.width, &window->x11.height);
@ -1082,7 +1085,7 @@ static const char* getSelectionString(Atom selection)
// Make the specified window and its video mode active on its monitor // Make the specified window and its video mode active on its monitor
// //
static void acquireMonitorX11(_GLFWwindow* window) static void acquireMonitor(_GLFWwindow* window)
{ {
if (_glfw.x11.saver.count == 0) if (_glfw.x11.saver.count == 0)
{ {
@ -1121,7 +1124,7 @@ static void acquireMonitorX11(_GLFWwindow* window)
// Remove the window and restore the original video mode // Remove the window and restore the original video mode
// //
static void releaseMonitorX11(_GLFWwindow* window) static void releaseMonitor(_GLFWwindow* window)
{ {
if (window->monitor->window != window) if (window->monitor->window != window)
return; return;
@ -1243,7 +1246,7 @@ static void processEvent(XEvent *event)
case KeyPress: case KeyPress:
{ {
const int key = translateKeyX11(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
@ -1305,7 +1308,7 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods); _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym); const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT) if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, codepoint, mods, plain); _glfwInputChar(window, codepoint, mods, plain);
} }
@ -1315,7 +1318,7 @@ static void processEvent(XEvent *event)
case KeyRelease: case KeyRelease:
{ {
const int key = translateKeyX11(keycode); const int key = translateKey(keycode);
const int mods = translateState(event->xkey.state); const int mods = translateState(event->xkey.state);
if (!_glfw.x11.xkb.detectable) if (!_glfw.x11.xkb.detectable)
@ -1807,9 +1810,9 @@ static void processEvent(XEvent *event)
if (window->monitor) if (window->monitor)
{ {
if (iconified) if (iconified)
releaseMonitorX11(window); releaseMonitor(window);
else else
acquireMonitorX11(window); acquireMonitor(window);
} }
window->x11.iconified = iconified; window->x11.iconified = iconified;
@ -2026,7 +2029,7 @@ GLFWbool _glfwCreateWindowX11(_GLFWwindow* window,
{ {
_glfwShowWindowX11(window); _glfwShowWindowX11(window);
updateWindowMode(window); updateWindowMode(window);
acquireMonitorX11(window); acquireMonitor(window);
if (wndconfig->centerCursor) if (wndconfig->centerCursor)
_glfwCenterCursorInContentArea(window); _glfwCenterCursorInContentArea(window);
@ -2051,7 +2054,7 @@ void _glfwDestroyWindowX11(_GLFWwindow* window)
enableCursor(window); enableCursor(window);
if (window->monitor) if (window->monitor)
releaseMonitorX11(window); releaseMonitor(window);
if (window->x11.ic) if (window->x11.ic)
{ {
@ -2204,10 +2207,14 @@ void _glfwGetWindowSizeX11(_GLFWwindow* window, int* width, int* height)
void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height) void _glfwSetWindowSizeX11(_GLFWwindow* window, int width, int height)
{ {
// The dimensions must be nonzero, or a BadValue error results
width = _glfw_max(1, width);
height = _glfw_max(1, height);
if (window->monitor) if (window->monitor)
{ {
if (window->monitor->window == window) if (window->monitor->window == window)
acquireMonitorX11(window); acquireMonitor(window);
} }
else else
{ {
@ -2431,6 +2438,38 @@ void _glfwShowWindowX11(_GLFWwindow* window)
if (_glfwWindowVisibleX11(window)) if (_glfwWindowVisibleX11(window))
return; return;
if (window->floating && _glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
Atom* states = NULL;
const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
XA_ATOM, (unsigned char**) &states);
// NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append)
unsigned long i;
for (i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
break;
}
if (i == count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
if (states)
XFree(states);
}
XMapWindow(_glfw.x11.display, window->x11.handle); XMapWindow(_glfw.x11.display, window->x11.handle);
waitForVisibilityNotify(window); waitForVisibilityNotify(window);
} }
@ -2478,7 +2517,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
if (monitor) if (monitor)
{ {
if (monitor->window == window) if (monitor->window == window)
acquireMonitorX11(window); acquireMonitor(window);
} }
else else
{ {
@ -2497,7 +2536,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
{ {
_glfwSetWindowDecoratedX11(window, window->decorated); _glfwSetWindowDecoratedX11(window, window->decorated);
_glfwSetWindowFloatingX11(window, window->floating); _glfwSetWindowFloatingX11(window, window->floating);
releaseMonitorX11(window); releaseMonitor(window);
} }
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@ -2512,7 +2551,7 @@ void _glfwSetWindowMonitorX11(_GLFWwindow* window,
} }
updateWindowMode(window); updateWindowMode(window);
acquireMonitorX11(window); acquireMonitor(window);
} }
else else
{ {
@ -2660,6 +2699,10 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled)
} }
else else
{ {
// NOTE: _NET_WM_STATE_ABOVE is added when the window is shown
if (enabled)
return;
Atom* states = NULL; Atom* states = NULL;
const unsigned long count = const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle, _glfwGetWindowPropertyX11(window->x11.handle,
@ -2670,8 +2713,6 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled)
// NOTE: We don't check for failure as this property may not exist yet // NOTE: We don't check for failure as this property may not exist yet
// and that's fine (and we'll create it implicitly with append) // and that's fine (and we'll create it implicitly with append)
if (enabled)
{
unsigned long i; unsigned long i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
@ -2680,28 +2721,12 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled)
break; break;
} }
if (i == count) if (i < count)
{
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeAppend,
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
1);
}
}
else if (states)
{
for (unsigned long i = 0; i < count; i++)
{
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
{ {
states[i] = states[count - 1]; states[i] = states[count - 1];
XChangeProperty(_glfw.x11.display, window->x11.handle, XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32, _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) states, count - 1); PropModeReplace, (unsigned char*) states, count - 1);
break;
}
}
} }
if (states) if (states)
@ -2919,7 +2944,7 @@ const char* _glfwGetScancodeNameX11(int scancode)
if (keysym == NoSymbol) if (keysym == NoSymbol)
return NULL; return NULL;
const uint32_t codepoint = _glfwKeySym2Unicode(keysym); const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
if (codepoint == GLFW_INVALID_CODEPOINT) if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL; return NULL;
@ -3303,7 +3328,6 @@ GLFWAPI Display* glfwGetX11Display(void)
GLFWAPI Window glfwGetX11Window(GLFWwindow* handle) GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
{ {
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(None); _GLFW_REQUIRE_INIT_OR_RETURN(None);
if (_glfw.platform.platformID != GLFW_PLATFORM_X11) if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
@ -3312,6 +3336,9 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
return None; return None;
} }
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
return window->x11.handle; return window->x11.handle;
} }
@ -3325,6 +3352,8 @@ GLFWAPI void glfwSetX11SelectionString(const char* string)
return; return;
} }
assert(string != NULL);
_glfw_free(_glfw.x11.primarySelectionString); _glfw_free(_glfw.x11.primarySelectionString);
_glfw.x11.primarySelectionString = _glfw_strdup(string); _glfw.x11.primarySelectionString = _glfw_strdup(string);

View file

@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.4 X11 - www.glfw.org // GLFW 3.5 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
@ -27,7 +27,7 @@
#include "internal.h" #include "internal.h"
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) #if defined(_GLFW_X11)
/* /*
* Marcus: This code was originally written by Markus G. Kuhn. * Marcus: This code was originally written by Markus G. Kuhn.
@ -906,7 +906,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode // Convert XKB KeySym to Unicode
// //
uint32_t _glfwKeySym2Unicode(unsigned int keysym) uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
{ {
int min = 0; int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@ -939,5 +939,5 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym)
return GLFW_INVALID_CODEPOINT; return GLFW_INVALID_CODEPOINT;
} }
#endif // _GLFW_WAYLAND or _GLFW_X11 #endif // _GLFW_X11

View file

@ -1538,10 +1538,10 @@ mulong jar_mod_load_file(jar_mod_context_t * modctx, const char* filename)
modctx->modfile = (muchar *) JARMOD_MALLOC(fsize); modctx->modfile = (muchar *) JARMOD_MALLOC(fsize);
modctx->modfilesize = fsize; modctx->modfilesize = fsize;
memset(modctx->modfile, 0, fsize); memset(modctx->modfile, 0, fsize);
fread(modctx->modfile, fsize, 1, f); if(fread(modctx->modfile, fsize, 1, f) != 1) fsize = 0;
fclose(f); fclose(f);
if(!jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0; if(fsize && !jar_mod_load(modctx, (void *)modctx->modfile, fsize)) fsize = 0;
} else fsize = 0; } else fsize = 0;
} }
return fsize; return fsize;

View file

@ -1,6 +1,6 @@
/* /*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio - v0.11.24 - 2026-01-17 miniaudio - v0.11.25 - 2026-03-04
David Reid - mackron@gmail.com David Reid - mackron@gmail.com
@ -3747,7 +3747,7 @@ extern "C" {
#define MA_VERSION_MAJOR 0 #define MA_VERSION_MAJOR 0
#define MA_VERSION_MINOR 11 #define MA_VERSION_MINOR 11
#define MA_VERSION_REVISION 24 #define MA_VERSION_REVISION 25
#define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION) #define MA_VERSION_STRING MA_XSTRINGIFY(MA_VERSION_MAJOR) "." MA_XSTRINGIFY(MA_VERSION_MINOR) "." MA_XSTRINGIFY(MA_VERSION_REVISION)
#if defined(_MSC_VER) && !defined(__clang__) #if defined(_MSC_VER) && !defined(__clang__)
@ -19358,7 +19358,7 @@ MA_API ma_handle ma_dlopen(ma_log* pLog, const char* filename)
#else #else
/* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */ /* *sigh* It appears there is no ANSI version of LoadPackagedLibrary()... */
WCHAR filenameW[4096]; WCHAR filenameW[4096];
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, sizeof(filenameW)) == 0) { if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, ma_countof(filenameW)) == 0) {
handle = NULL; handle = NULL;
} else { } else {
handle = (ma_handle)LoadPackagedLibrary(filenameW, 0); handle = (ma_handle)LoadPackagedLibrary(filenameW, 0);
@ -41495,18 +41495,37 @@ Web Audio Backend
#ifdef MA_HAS_WEBAUDIO #ifdef MA_HAS_WEBAUDIO
#include <emscripten/emscripten.h> #include <emscripten/emscripten.h>
#if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 32))) #ifndef MA_EMSCRIPTEN_MAJOR
#if defined(__EMSCRIPTEN_MAJOR__)
#define MA_EMSCRIPTEN_MAJOR __EMSCRIPTEN_MAJOR__
#else
#define MA_EMSCRIPTEN_MAJOR __EMSCRIPTEN_major__
#endif
#endif
#ifndef MA_EMSCRIPTEN_MINOR
#if defined(__EMSCRIPTEN_MINOR__)
#define MA_EMSCRIPTEN_MINOR __EMSCRIPTEN_MINOR__
#else
#define MA_EMSCRIPTEN_MINOR __EMSCRIPTEN_minor__
#endif
#endif
#ifndef MA_EMSCRIPTEN_TINY
#if defined(__EMSCRIPTEN_TINY__)
#define MA_EMSCRIPTEN_TINY __EMSCRIPTEN_TINY__
#else
#define MA_EMSCRIPTEN_TINY __EMSCRIPTEN_tiny__
#endif
#endif
#if (MA_EMSCRIPTEN_MAJOR > 3) || (MA_EMSCRIPTEN_MAJOR == 3 && (MA_EMSCRIPTEN_MINOR > 1 || (MA_EMSCRIPTEN_MINOR == 1 && MA_EMSCRIPTEN_TINY >= 32)))
#include <emscripten/webaudio.h> #include <emscripten/webaudio.h>
#define MA_SUPPORT_AUDIO_WORKLETS #define MA_SUPPORT_AUDIO_WORKLETS
#if (__EMSCRIPTEN_major__ > 3) || (__EMSCRIPTEN_major__ == 3 && (__EMSCRIPTEN_minor__ > 1 || (__EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 70))) #if (MA_EMSCRIPTEN_MAJOR > 3) || (MA_EMSCRIPTEN_MAJOR == 3 && (MA_EMSCRIPTEN_MINOR > 1 || (MA_EMSCRIPTEN_MINOR == 1 && MA_EMSCRIPTEN_TINY >= 70)))
#define MA_SUPPORT_AUDIO_WORKLETS_VARIABLE_BUFFER_SIZE #define MA_SUPPORT_AUDIO_WORKLETS_VARIABLE_BUFFER_SIZE
#endif #endif
#endif #endif
/*
TODO: Version 0.12: Swap this logic around so that AudioWorklets are used by default. Add MA_NO_AUDIO_WORKLETS.
*/
#if defined(MA_ENABLE_AUDIO_WORKLETS) && defined(MA_SUPPORT_AUDIO_WORKLETS) #if defined(MA_ENABLE_AUDIO_WORKLETS) && defined(MA_SUPPORT_AUDIO_WORKLETS)
#define MA_USE_AUDIO_WORKLETS #define MA_USE_AUDIO_WORKLETS
#endif #endif
@ -59243,6 +59262,10 @@ static ma_result ma_data_source_read_pcm_frames_within_range(ma_data_source* pDa
ma_uint64 framesRead = 0; ma_uint64 framesRead = 0;
ma_bool32 loop = ma_data_source_is_looping(pDataSource); ma_bool32 loop = ma_data_source_is_looping(pDataSource);
if (pFramesRead != NULL) {
*pFramesRead = 0;
}
if (pDataSourceBase == NULL) { if (pDataSourceBase == NULL) {
return MA_AT_END; return MA_AT_END;
} }
@ -61921,7 +61944,7 @@ extern "C" {
#define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x) #define MA_DR_WAV_XSTRINGIFY(x) MA_DR_WAV_STRINGIFY(x)
#define MA_DR_WAV_VERSION_MAJOR 0 #define MA_DR_WAV_VERSION_MAJOR 0
#define MA_DR_WAV_VERSION_MINOR 14 #define MA_DR_WAV_VERSION_MINOR 14
#define MA_DR_WAV_VERSION_REVISION 4 #define MA_DR_WAV_VERSION_REVISION 5
#define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION) #define MA_DR_WAV_VERSION_STRING MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MAJOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_MINOR) "." MA_DR_WAV_XSTRINGIFY(MA_DR_WAV_VERSION_REVISION)
#include <stddef.h> #include <stddef.h>
#define MA_DR_WAVE_FORMAT_PCM 0x1 #define MA_DR_WAVE_FORMAT_PCM 0x1
@ -80503,6 +80526,13 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa
MA_DR_WAV_ASSERT(pChunkHeader != NULL); MA_DR_WAV_ASSERT(pChunkHeader != NULL);
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) { if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
ma_uint32 iSampleLoop; ma_uint32 iSampleLoop;
ma_uint32 loopCount;
ma_uint32 calculatedLoopCount;
loopCount = ma_dr_wav_bytes_to_u32(smplHeaderData + 28);
calculatedLoopCount = (pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES;
if (loopCount != calculatedLoopCount) {
return totalBytesRead;
}
pMetadata->type = ma_dr_wav_metadata_type_smpl; pMetadata->type = ma_dr_wav_metadata_type_smpl;
pMetadata->data.smpl.manufacturerId = ma_dr_wav_bytes_to_u32(smplHeaderData + 0); pMetadata->data.smpl.manufacturerId = ma_dr_wav_bytes_to_u32(smplHeaderData + 0);
pMetadata->data.smpl.productId = ma_dr_wav_bytes_to_u32(smplHeaderData + 4); pMetadata->data.smpl.productId = ma_dr_wav_bytes_to_u32(smplHeaderData + 4);
@ -80513,7 +80543,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa
pMetadata->data.smpl.smpteOffset = ma_dr_wav_bytes_to_u32(smplHeaderData + 24); pMetadata->data.smpl.smpteOffset = ma_dr_wav_bytes_to_u32(smplHeaderData + 24);
pMetadata->data.smpl.sampleLoopCount = ma_dr_wav_bytes_to_u32(smplHeaderData + 28); pMetadata->data.smpl.sampleLoopCount = ma_dr_wav_bytes_to_u32(smplHeaderData + 28);
pMetadata->data.smpl.samplerSpecificDataSizeInBytes = ma_dr_wav_bytes_to_u32(smplHeaderData + 32); pMetadata->data.smpl.samplerSpecificDataSizeInBytes = ma_dr_wav_bytes_to_u32(smplHeaderData + 32);
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - MA_DR_WAV_SMPL_BYTES) / MA_DR_WAV_SMPL_LOOP_BYTES) { if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) {
pMetadata->data.smpl.pLoops = (ma_dr_wav_smpl_loop*)ma_dr_wav__metadata_get_memory(pParser, sizeof(ma_dr_wav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, MA_DR_WAV_METADATA_ALIGNMENT); pMetadata->data.smpl.pLoops = (ma_dr_wav_smpl_loop*)ma_dr_wav__metadata_get_memory(pParser, sizeof(ma_dr_wav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, MA_DR_WAV_METADATA_ALIGNMENT);
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) { for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
ma_uint8 smplLoopData[MA_DR_WAV_SMPL_LOOP_BYTES]; ma_uint8 smplLoopData[MA_DR_WAV_SMPL_LOOP_BYTES];
@ -80534,6 +80564,8 @@ MA_PRIVATE ma_uint64 ma_dr_wav__read_smpl_to_metadata_obj(ma_dr_wav__metadata_pa
MA_DR_WAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL); MA_DR_WAV_ASSERT(pMetadata->data.smpl.pSamplerSpecificData != NULL);
ma_dr_wav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead); ma_dr_wav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
} }
} else {
MA_DR_WAV_ZERO_OBJECT(&pMetadata->data.smpl);
} }
} }
return totalBytesRead; return totalBytesRead;
@ -83149,19 +83181,13 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 += nibble0 * pWav->msadpcm.delta[0];
newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767); newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767);
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8; pWav->msadpcm.delta[0] = (ma_int32)ma_dr_wav_clamp(((ma_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
if (pWav->msadpcm.delta[0] < 16) {
pWav->msadpcm.delta[0] = 16;
}
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
pWav->msadpcm.prevFrames[0][1] = newSample0; pWav->msadpcm.prevFrames[0][1] = newSample0;
newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample1 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
newSample1 += nibble1 * pWav->msadpcm.delta[0]; newSample1 += nibble1 * pWav->msadpcm.delta[0];
newSample1 = ma_dr_wav_clamp(newSample1, -32768, 32767); newSample1 = ma_dr_wav_clamp(newSample1, -32768, 32767);
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8; pWav->msadpcm.delta[0] = (ma_int32)ma_dr_wav_clamp(((ma_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
if (pWav->msadpcm.delta[0] < 16) {
pWav->msadpcm.delta[0] = 16;
}
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
pWav->msadpcm.prevFrames[0][1] = newSample1; pWav->msadpcm.prevFrames[0][1] = newSample1;
pWav->msadpcm.cachedFrames[2] = newSample0; pWav->msadpcm.cachedFrames[2] = newSample0;
@ -83176,10 +83202,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8; newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
newSample0 += nibble0 * pWav->msadpcm.delta[0]; newSample0 += nibble0 * pWav->msadpcm.delta[0];
newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767); newSample0 = ma_dr_wav_clamp(newSample0, -32768, 32767);
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8; pWav->msadpcm.delta[0] = (ma_int32)ma_dr_wav_clamp(((ma_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
if (pWav->msadpcm.delta[0] < 16) {
pWav->msadpcm.delta[0] = 16;
}
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1]; pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
pWav->msadpcm.prevFrames[0][1] = newSample0; pWav->msadpcm.prevFrames[0][1] = newSample0;
if (pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff2Table)) { if (pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= ma_dr_wav_countof(coeff2Table)) {
@ -83188,10 +83211,7 @@ MA_PRIVATE ma_uint64 ma_dr_wav_read_pcm_frames_s16__msadpcm(ma_dr_wav* pWav, ma_
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8; newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
newSample1 += nibble1 * pWav->msadpcm.delta[1]; newSample1 += nibble1 * pWav->msadpcm.delta[1];
newSample1 = ma_dr_wav_clamp(newSample1, -32768, 32767); newSample1 = ma_dr_wav_clamp(newSample1, -32768, 32767);
pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8; pWav->msadpcm.delta[1] = (ma_int32)ma_dr_wav_clamp(((ma_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF);
if (pWav->msadpcm.delta[1] < 16) {
pWav->msadpcm.delta[1] = 16;
}
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1]; pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
pWav->msadpcm.prevFrames[1][1] = newSample1; pWav->msadpcm.prevFrames[1][1] = newSample1;
pWav->msadpcm.cachedFrames[2] = newSample0; pWav->msadpcm.cachedFrames[2] = newSample0;
@ -95825,7 +95845,7 @@ For more information, please refer to <http://unlicense.org/>
=============================================================================== ===============================================================================
ALTERNATIVE 2 - MIT No Attribution ALTERNATIVE 2 - MIT No Attribution
=============================================================================== ===============================================================================
Copyright 2025 David Reid Copyright 2026 David Reid
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* rprand v1.0 - A simple and easy-to-use pseudo-random numbers generator (PRNG) * rprand v1.1 - A simple and easy-to-use pseudo-random numbers generator (PRNG)
* *
* FEATURES: * FEATURES:
* - Pseudo-random values generation, 32 bits: [0..4294967295] * - Pseudo-random values generation, 32 bits: [0..4294967295]
@ -118,6 +118,7 @@ extern "C" { // Prevents name mangling of functions
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
RPRANDAPI void rprand_set_seed(unsigned long long seed); // Set rprand_state for Xoshiro128**, seed is 64bit RPRANDAPI void rprand_set_seed(unsigned long long seed); // Set rprand_state for Xoshiro128**, seed is 64bit
RPRANDAPI int rprand_get_value(int min, int max); // Get random value within a range, min and max included RPRANDAPI int rprand_get_value(int min, int max); // Get random value within a range, min and max included
RPRANDAPI int rprand_get_value_raw(void); // Get random value, Xoshiro128** generator (uses global rprand_state)
RPRANDAPI int *rprand_load_sequence(unsigned int count, int min, int max); // Load pseudo-random numbers sequence with no duplicates RPRANDAPI int *rprand_load_sequence(unsigned int count, int min, int max); // Load pseudo-random numbers sequence with no duplicates
RPRANDAPI void rprand_unload_sequence(int *sequence); // Unload pseudo-random numbers sequence RPRANDAPI void rprand_unload_sequence(int *sequence); // Unload pseudo-random numbers sequence
@ -186,6 +187,13 @@ int rprand_get_value(int min, int max)
return value; return value;
} }
int rprand_get_value_raw(void)
{
int value = rprand_xoshiro();
return value;
}
// Load pseudo-random numbers sequence with no duplicates, min and max included // Load pseudo-random numbers sequence with no duplicates, min and max included
int *rprand_load_sequence(unsigned int count, int min, int max) int *rprand_load_sequence(unsigned int count, int min, int max)
{ {

View file

@ -1020,7 +1020,12 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
int triangulate) { int triangulate) {
char linebuf[4096]; char linebuf[4096];
const char *token; const char *token;
assert(p_len < 4095);
// @raysan5:
// WARNING: If -DNDEBUG is set when compiling, assertions will not
// be present in the compiled binary, replacing by a runtime check
//assert(p_len < 4095);
if (p_len > 4095) return 0;
memcpy(linebuf, p, p_len); memcpy(linebuf, p, p_len);
linebuf[p_len] = '\0'; linebuf[p_len] = '\0';
@ -1102,7 +1107,11 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
tinyobj_vertex_index_t i1; tinyobj_vertex_index_t i1;
tinyobj_vertex_index_t i2 = f[1]; tinyobj_vertex_index_t i2 = f[1];
assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE); // @raysan5:
// WARNING: If -DNDEBUG is set when compiling, assertions will not
// be present in the compiled binary, replacing by a runtime check
//assert(3 * num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
if (3*num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
for (k = 2; k < num_f; k++) { for (k = 2; k < num_f; k++) {
i1 = i2; i1 = i2;
@ -1119,7 +1128,13 @@ static int parseLine(Command *command, const char *p, unsigned int p_len,
} else { } else {
unsigned int k = 0; unsigned int k = 0;
assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
// @raysan5:
// WARNING: If -DNDEBUG is set when compiling, assertions will not
// be present in the compiled binary, replacing by a runtime check
//assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE);
if (num_f > TINYOBJ_MAX_FACES_PER_F_LINE) return 0;
for (k = 0; k < num_f; k++) { for (k = 0; k < num_f; k++) {
command->f[k] = f[k]; command->f[k] = f[k];
} }

View file

@ -4,14 +4,14 @@
#ifndef WIN32_CLIPBOARD_ #ifndef WIN32_CLIPBOARD_
#define WIN32_CLIPBOARD_ #define WIN32_CLIPBOARD_
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize); unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize);
#endif // WIN32_CLIPBOARD_ #endif // WIN32_CLIPBOARD_
#ifdef WIN32_CLIPBOARD_IMPLEMENTATION #ifdef WIN32_CLIPBOARD_IMPLEMENTATION
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <limits.h>
// NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h // NOTE: These search for architecture is taken from "windows.h", and it's necessary to avoid including windows.h
// and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined // and still make it compile on msvc, because import indirectly importing "winnt.h" (e.g. <minwindef.h>) can cause problems is these are not defined
@ -213,7 +213,7 @@ static int GetPixelDataOffset(BITMAPINFOHEADER bih); // Get pixel data offset fr
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long long int *dataSize) unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned int *dataSize)
{ {
unsigned char *bmpData = NULL; unsigned char *bmpData = NULL;
@ -228,7 +228,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
*width = bmpInfoHeader->biWidth; *width = bmpInfoHeader->biWidth;
*height = bmpInfoHeader->biHeight; *height = bmpInfoHeader->biHeight;
SIZE_T clipDataSize = GlobalSize(clipHandle); SIZE_T clipDataSize = GlobalSize(clipHandle);
if (clipDataSize >= sizeof(BITMAPINFOHEADER)) if ((clipDataSize >= sizeof(BITMAPINFOHEADER)) && (clipDataSize < INT_MAX))
{ {
int pixelOffset = GetPixelDataOffset(*bmpInfoHeader); int pixelOffset = GetPixelDataOffset(*bmpInfoHeader);
@ -236,7 +236,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
//------------------------------------------------------------------------ //------------------------------------------------------------------------
BITMAPFILEHEADER bmpFileHeader = { 0 }; BITMAPFILEHEADER bmpFileHeader = { 0 };
SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize; SIZE_T bmpFileSize = sizeof(bmpFileHeader) + clipDataSize;
*dataSize = bmpFileSize; *dataSize = (unsigned int)bmpFileSize;
bmpFileHeader.bfType = 0x4D42; // BMP fil type constant bmpFileHeader.bfType = 0x4D42; // BMP fil type constant
bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine bmpFileHeader.bfSize = (DWORD)bmpFileSize; // Up to 4GB works fine
@ -254,7 +254,7 @@ unsigned char *Win32GetClipboardImageData(int *width, int *height, unsigned long
} }
else else
{ {
TRACELOG(LOG_WARNING, "Clipboard data is malformed"); TRACELOG(LOG_WARNING, "Clipboard data is not supported (>2GB?)");
GlobalUnlock(clipHandle); GlobalUnlock(clipHandle);
CloseClipboard(); CloseClipboard();
} }

View file

@ -473,8 +473,7 @@ void SetWindowFocused(void)
// Get native window handle // Get native window handle
void *GetWindowHandle(void) void *GetWindowHandle(void)
{ {
TRACELOG(LOG_WARNING, "GetWindowHandle() not implemented on target platform"); return (void *)platform.app->window; // Type: ANativeWindow*
return NULL;
} }
// Get number of monitors // Get number of monitors
@ -616,13 +615,13 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -656,7 +655,7 @@ double GetTime(void)
double time = 0.0; double time = 0.0;
struct timespec ts = { 0 }; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
@ -664,13 +663,22 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if the provided URL is safe // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Avoid calling this function with user input non-validated strings // NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else else
{ {
JNIEnv *env = NULL; JNIEnv *env = NULL;
@ -718,7 +726,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
// Set mouse cursor // Set mouse cursor
@ -794,6 +801,7 @@ void PollInputEvents(void)
if (platform.app->destroyRequested != 0) if (platform.app->destroyRequested != 0)
{ {
CORE.Window.shouldClose = true; CORE.Window.shouldClose = true;
break;
} }
} }
} }
@ -1273,20 +1281,19 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
int32_t keycode = AKeyEvent_getKeyCode(event); int32_t keycode = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event); //int32_t AKeyEvent_getMetaState(event);
// Handle gamepad button presses and releases // Handle gamepad button presses and releases. AOSP stamps the
// NOTE: Skip gamepad handling if this is a keyboard event, as some devices // KEYBOARD source bit on every key event from a gamepad, so
// report both AINPUT_SOURCE_KEYBOARD and AINPUT_SOURCE_GAMEPAD flags // discriminate on the keycode rather than gating on source bits.
if ((FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) || if (FLAG_IS_SET(source, AINPUT_SOURCE_JOYSTICK) ||
FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD)) && FLAG_IS_SET(source, AINPUT_SOURCE_GAMEPAD))
!FLAG_IS_SET(source, AINPUT_SOURCE_KEYBOARD)) {
GamepadButton button = AndroidTranslateGamepadButton(keycode);
if (button != GAMEPAD_BUTTON_UNKNOWN)
{ {
// Assuming a single gamepad, "detected" on its input event // Assuming a single gamepad, "detected" on its input event
CORE.Input.Gamepad.ready[0] = true; CORE.Input.Gamepad.ready[0] = true;
GamepadButton button = AndroidTranslateGamepadButton(keycode);
if (button == GAMEPAD_BUTTON_UNKNOWN) return 1;
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN) if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
{ {
CORE.Input.Gamepad.currentButtonState[0][button] = 1; CORE.Input.Gamepad.currentButtonState[0][button] = 1;
@ -1295,6 +1302,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
return 1; // Handled gamepad button return 1; // Handled gamepad button
} }
// Unknown keycode: fall through to the keyboard handler below.
}
KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL; KeyboardKey key = ((keycode > 0) && (keycode < KEYCODE_MAP_SIZE))? mapKeycode[keycode] : KEY_NULL;
if (key != KEY_NULL) if (key != KEY_NULL)

View file

@ -111,6 +111,12 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef struct { typedef struct {
GLFWwindow *handle; // GLFW window handle (graphic device) GLFWwindow *handle; // GLFW window handle (graphic device)
#if defined(__linux__) && defined(_GLFW_X11)
// Local storage for the window handle returned by glfwGetX11Window
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
Window windowHandleX11; // Underlying type: unsigned long (XID, Window)
#endif
} PlatformData; } PlatformData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -145,7 +151,7 @@ static void CharCallback(GLFWwindow *window, unsigned int codepoint);
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed
static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move
static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Scrolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void CursorEnterCallback(GLFWwindow *window, int entered); // GLFW3 Cursor Enter Callback, cursor enters client area
static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback static void JoystickCallback(int jid, int event); // GLFW3 Joystick Connected/Disconnected Callback
// Memory allocator wrappers [used by glfwInitAllocator()] // Memory allocator wrappers [used by glfwInitAllocator()]
@ -281,8 +287,14 @@ void ToggleBorderlessWindowed(void)
CORE.Window.screen.height = mode->height; CORE.Window.screen.height = mode->height;
// Set screen position and size // Set screen position and size
#if defined(_WIN32)
// NOTE: To prevent the fullscreen window from always staying on top, don't pass a monitor at this point.
glfwSetWindowMonitor(platform.handle, NULL, CORE.Window.position.x, CORE.Window.position.y,
CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate);
#else
glfwSetWindowMonitor(platform.handle, monitors[monitor], CORE.Window.position.x, CORE.Window.position.y, glfwSetWindowMonitor(platform.handle, monitors[monitor], CORE.Window.position.x, CORE.Window.position.y,
CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate); CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate);
#endif
// Refocus window // Refocus window
glfwFocusWindow(platform.handle); glfwFocusWindow(platform.handle);
@ -755,18 +767,13 @@ void SetWindowFocused(void)
glfwFocusWindow(platform.handle); glfwFocusWindow(platform.handle);
} }
#if defined(__linux__) && defined(_GLFW_X11)
// Local storage for the window handle returned by glfwGetX11Window
// This is needed as X11 handles are integers and may not fit inside a pointer depending on platform
// Storing the handle locally and returning a pointer in GetWindowHandle allows the code to work regardless of pointer width
static XID X11WindowHandle;
#endif
// Get native window handle // Get native window handle
void *GetWindowHandle(void) void *GetWindowHandle(void)
{ {
void *handle = NULL;
#if defined(_WIN32) #if defined(_WIN32)
// NOTE: Returned handle is: void *HWND (windows.h) handle = glfwGetWin32Window(platform.handle); // Type: HWND
return glfwGetWin32Window(platform.handle);
#endif #endif
#if defined(__linux__) #if defined(__linux__)
#if defined(_GLFW_WAYLAND) #if defined(_GLFW_WAYLAND)
@ -774,29 +781,27 @@ void *GetWindowHandle(void)
int platformID = glfwGetPlatform(); int platformID = glfwGetPlatform();
if (platformID == GLFW_PLATFORM_WAYLAND) if (platformID == GLFW_PLATFORM_WAYLAND)
{ {
return glfwGetWaylandWindow(platform.handle); handle = (void *)glfwGetWaylandWindow(platform.handle); // Type: struct wl_surface*
} }
else else
{ {
X11WindowHandle = glfwGetX11Window(platform.handle); platform.windowHandleX11 = glfwGetX11Window(platform.handle); // Type: Window (unsigned long)
return &X11WindowHandle; handle = &platform.windowHandleX11;
} }
#else #else
return glfwGetWaylandWindow(platform.handle); handle = (void *)glfwGetWaylandWindow(platform.handle);
#endif #endif
#elif defined(_GLFW_X11) #elif defined(_GLFW_X11)
// Store the window handle localy and return a pointer to the variable instead // Store the window handle locally and return a pointer to the variable instead
// Reasoning detailed in the declaration of X11WindowHandle platform.windowHandleX11 = glfwGetX11Window(platform.handle);
X11WindowHandle = glfwGetX11Window(platform.handle); handle = &platform.windowHandleX11;
return &X11WindowHandle;
#endif #endif
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
// NOTE: Returned handle is: (objc_object *) handle = (void *)glfwGetCocoaWindow(platform.handle); // Type: NSWindow*
return (void *)glfwGetCocoaWindow(platform.handle);
#endif #endif
return NULL; return handle;
} }
// Get number of monitors // Get number of monitors
@ -840,7 +845,7 @@ int GetCurrentMonitor(void)
// this is probably an overengineered solution for a side case // this is probably an overengineered solution for a side case
// trying to match SDL behaviour // trying to match SDL behaviour
int closestDist = 0x7FFFFFFF; unsigned int closestDist = 0xFFFFFFFFu;
// Window center position // Window center position
int wcx = 0; int wcx = 0;
@ -884,7 +889,14 @@ int GetCurrentMonitor(void)
int dx = wcx - xclosest; int dx = wcx - xclosest;
int dy = wcy - yclosest; int dy = wcy - yclosest;
int dist = (dx*dx) + (dy*dy);
// Unsigned to dodge signed overflow UB; (-x)^2 == x^2 mod 2^32 so sign drops out.
// If |dx| or |dy| >= 65536, dist wraps and the wrong monitor may win.
// Not a concern for realistic monitor layouts.
unsigned int ux = (unsigned int)dx;
unsigned int uy = (unsigned int)dy;
unsigned int dist = ux*ux + uy*uy;
if (dist < closestDist) if (dist < closestDist)
{ {
index = i; index = i;
@ -1018,6 +1030,8 @@ const char *GetMonitorName(int monitor)
// Get window position XY on monitor // Get window position XY on monitor
Vector2 GetWindowPosition(void) Vector2 GetWindowPosition(void)
{ {
glfwGetWindowPos(platform.handle, &CORE.Window.position.x, &CORE.Window.position.y);
return (Vector2){ (float)CORE.Window.position.x, (float)CORE.Window.position.y }; return (Vector2){ (float)CORE.Window.position.x, (float)CORE.Window.position.y };
} }
@ -1043,11 +1057,6 @@ const char *GetClipboardText(void)
return glfwGetClipboardString(platform.handle); return glfwGetClipboardString(platform.handle);
} }
#if SUPPORT_CLIPBOARD_IMAGE && defined(__linux__) && defined(_GLFW_X11)
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#endif
// Get clipboard image // Get clipboard image
Image GetClipboardImage(void) Image GetClipboardImage(void)
{ {
@ -1055,7 +1064,8 @@ Image GetClipboardImage(void)
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES #if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
#if defined(_WIN32) #if defined(_WIN32)
unsigned long long int dataSize = 0;
unsigned int dataSize = 0;
void *bmpData = NULL; void *bmpData = NULL;
int width = 0; int width = 0;
int height = 0; int height = 0;
@ -1063,35 +1073,38 @@ Image GetClipboardImage(void)
bmpData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize); bmpData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
if (bmpData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data."); if (bmpData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
else image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize); else
{
image = LoadImageFromMemory(".bmp", (const unsigned char *)bmpData, (int)dataSize);
RL_FREE(bmpData);
}
#elif defined(__linux__) && defined(_GLFW_X11) #elif defined(__linux__) && defined(_GLFW_X11)
// REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c // REF: https://github.com/ColleagueRiley/Clipboard-Copy-Paste/blob/main/x11.c
Display *dpy = XOpenDisplay(NULL);
if (!dpy) return image;
Window root = DefaultRootWindow(dpy); static Atom clipboard = 0;
Window win = XCreateSimpleWindow( static Atom targetType = 0;
dpy, // The connection to the X Server static Atom property = 0;
root, // The 'Parent' window (usually the desktop/root)
0, 0, // X and Y position on the screen
1, 1, // Width and Height (1x1 pixel)
0, // Border width
0, // Border color
0 // Background color
);
Atom clipboard = XInternAtom(dpy, "CLIPBOARD", False); Display *display = glfwGetX11Display();
Atom targetType = XInternAtom(dpy, "image/png", False); // Ask for PNG XID window = glfwGetX11Window(platform.handle);
Atom property = XInternAtom(dpy, "RAYLIB_CLIPBOARD_MANAGER", False);
// Request the data: "Convert whatever is in CLIPBOARD to image/png and put it in RAYLIB_CLIPBOARD_MANAGER" // Lazy-load X11 atoms
XConvertSelection(dpy, clipboard, targetType, property, win, CurrentTime); if (clipboard == 0)
{
clipboard = XInternAtom(display, "CLIPBOARD", False);
targetType = XInternAtom(display, "image/png", False);
property = XInternAtom(display, "RAYLIB_CLIPBOARD_MANAGER", False);
}
XConvertSelection(display, clipboard, targetType, property, window, CurrentTime);
XSync(display, 0);
// Wait for the SelectionNotify event
XEvent ev = { 0 }; XEvent ev = { 0 };
XNextEvent(dpy, &ev);
// Keep calling until we get SelectionNotify
while (XCheckTypedEvent(display, SelectionNotify, &ev) == False);
Atom actualType = { 0 }; Atom actualType = { 0 };
int actualFormat = 0; int actualFormat = 0;
@ -1099,8 +1112,7 @@ Image GetClipboardImage(void)
unsigned long bytesAfter = 0; unsigned long bytesAfter = 0;
unsigned char *data = NULL; unsigned char *data = NULL;
// Read the data from our ghost window's property XGetWindowProperty(display, window, property, 0, ~0L, False, AnyPropertyType,
XGetWindowProperty(dpy, win, property, 0, ~0L, False, AnyPropertyType,
&actualType, &actualFormat, &nitems, &bytesAfter, &data); &actualType, &actualFormat, &nitems, &bytesAfter, &data);
if (data != NULL) if (data != NULL)
@ -1109,11 +1121,9 @@ Image GetClipboardImage(void)
XFree(data); XFree(data);
} }
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
#else #else
TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform"); TRACELOG(LOG_WARNING, "GetClipboardImage() not implemented on target platform");
#endif // defined(_WIN32) #endif // _WIN32
#else #else
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly"); TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
#endif // SUPPORT_CLIPBOARD_IMAGE #endif // SUPPORT_CLIPBOARD_IMAGE
@ -1129,7 +1139,7 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
@ -1137,7 +1147,7 @@ void HideCursor(void)
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetInputMode(platform.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
@ -1151,7 +1161,7 @@ void EnableCursor(void)
CORE.Input.Mouse.cursorLocked = false; CORE.Input.Mouse.cursorLocked = false;
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
// Reset mouse position within the window area before disabling cursor // Reset mouse position within the window area before disabling cursor
@ -1184,17 +1194,25 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if you control the URL given // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Only call this function yourself not with user input or make sure to check the string yourself // NOTE: Some safety checks have been added to mitigate security issues
// REF: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else else
{ {
char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char)); char *cmd = (char *)RL_CALLOC(strlen(url) + 16, sizeof(char));
#if defined(_WIN32) #if defined(_WIN32)
sprintf(cmd, "explorer \"%s\"", url); sprintf(cmd, "explorer \"%s\"", url);
#endif #endif
@ -1204,7 +1222,9 @@ void OpenURL(const char *url)
#if defined(__APPLE__) #if defined(__APPLE__)
sprintf(cmd, "open '%s'", url); sprintf(cmd, "open '%s'", url);
#endif #endif
// TODO: Replace system() call by custom process
int result = system(cmd); int result = system(cmd);
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created"); if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd); RL_FREE(cmd);
} }
@ -1230,7 +1250,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
// NOTE: emscripten not implemented // NOTE: emscripten not implemented
glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y); glfwSetCursorPos(platform.handle, CORE.Input.Mouse.currentPosition.x, CORE.Input.Mouse.currentPosition.y);
@ -1319,7 +1338,7 @@ void PollInputEvents(void)
// Register previous gamepad states // Register previous gamepad states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
// Get current gamepad state // Get current gamepad state using internal GLFW mapping, instead of the immediate joystick API
// NOTE: There is no callback available, getting it manually // NOTE: There is no callback available, getting it manually
GLFWgamepadstate state = { 0 }; GLFWgamepadstate state = { 0 };
int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller int result = glfwGetGamepadState(i, &state); // This remaps all gamepads so they have their buttons mapped like an xbox controller
@ -1686,6 +1705,14 @@ int InitPlatform(void)
return -1; return -1;
} }
#if defined(__APPLE__)
// AppKit can constrain the requested window size to the visible work area during creation
int windowWidth = 0;
int windowHeight = 0;
glfwGetWindowSize(platform.handle, &windowWidth, &windowHeight);
if ((windowWidth > 0) && (windowHeight > 0)) CORE.Window.screen = (Size){ windowWidth, windowHeight };
#endif
// NOTE: Not considering scale factor now, considered below // NOTE: Not considering scale factor now, considered below
CORE.Window.render.width = CORE.Window.screen.width; CORE.Window.render.width = CORE.Window.screen.width;
CORE.Window.render.height = CORE.Window.screen.height; CORE.Window.render.height = CORE.Window.screen.height;
@ -1832,7 +1859,7 @@ int InitPlatform(void)
{ {
CORE.Input.Gamepad.ready[i] = true; CORE.Input.Gamepad.ready[i] = true;
CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1; CORE.Input.Gamepad.axisCount[i] = GLFW_GAMEPAD_AXIS_LAST + 1;
strncpy(CORE.Input.Gamepad.name[i], glfwGetJoystickName(i), MAX_GAMEPAD_NAME_LENGTH - 1); snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(i));
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2047,7 +2074,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{ {
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
} }
} }
} }
@ -2170,10 +2197,18 @@ static void MouseScrollCallback(GLFWwindow *window, double xoffset, double yoffs
} }
// GLFW3: Cursor ennter callback, when cursor enters the window // GLFW3: Cursor ennter callback, when cursor enters the window
static void CursorEnterCallback(GLFWwindow *window, int enter) static void CursorEnterCallback(GLFWwindow *window, int entered)
{ {
if (enter) CORE.Input.Mouse.cursorOnScreen = true; if (entered)
else CORE.Input.Mouse.cursorOnScreen = false; {
// NOTE: Mouse position updated by MouseCursorPosCallback()
CORE.Input.Mouse.cursorOnScreen = true;
}
else
{
CORE.Input.Mouse.cursorOnScreen = false;
CORE.Input.Mouse.currentPosition = (Vector2){ 0 };
}
} }
// GLFW3: Joystick connected/disconnected callback // GLFW3: Joystick connected/disconnected callback
@ -2186,7 +2221,7 @@ static void JoystickCallback(int jid, int event)
// WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH, // WARNING: If glfwGetJoystickName() is longer than MAX_GAMEPAD_NAME_LENGTH,
// only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string // only copy up to (MAX_GAMEPAD_NAME_LENGTH -1) to destination string
memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH); memset(CORE.Input.Gamepad.name[jid], 0, MAX_GAMEPAD_NAME_LENGTH);
strncpy(CORE.Input.Gamepad.name[jid], glfwGetJoystickName(jid), MAX_GAMEPAD_NAME_LENGTH - 1); snprintf(CORE.Input.Gamepad.name[jid], MAX_GAMEPAD_NAME_LENGTH, "%s", glfwGetJoystickName(jid));
} }
else if (event == GLFW_DISCONNECTED) else if (event == GLFW_DISCONNECTED)
{ {

File diff suppressed because it is too large Load diff

View file

@ -56,6 +56,13 @@
#include "SDL3/SDL.h" #include "SDL3/SDL.h"
#elif defined(USING_SDL2_PROJECT) #elif defined(USING_SDL2_PROJECT)
#include "SDL2/SDL.h" #include "SDL2/SDL.h"
// WARNING: On Linux, this header includes Xlib.h, which defines Font
// To prevent a conflict with raylib's own Font type, we temporarily
// rename it to FontX11
#define Font FontX11
#include "SDL2/SDL_syswm.h" // Required to get window handlers
#undef Font
#else #else
#include "SDL.h" #include "SDL.h"
#endif #endif
@ -101,6 +108,13 @@ typedef struct {
SDL_GameController *gamepad[MAX_GAMEPADS]; SDL_GameController *gamepad[MAX_GAMEPADS];
SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids, they do not start from 0 SDL_JoystickID gamepadId[MAX_GAMEPADS]; // Joystick instance ids, they do not start from 0
SDL_Cursor *cursor; SDL_Cursor *cursor;
#if defined(__linux__)
// Local storage for the window handle (X11)
// NOTE: On SDL is not possible to know windowing backend at compile time, so,
// just in case, avoiding X11 specific types here
unsigned long windowHandleX11; // Underlying type for: XID, Window
#endif
} PlatformData; } PlatformData;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -456,12 +470,11 @@ bool WindowShouldClose(void)
void ToggleFullscreen(void) void ToggleFullscreen(void)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE)) if (FLAG_IS_SET(CORE.Window.flags, FLAG_FULLSCREEN_MODE))
@ -482,12 +495,11 @@ void ToggleFullscreen(void)
void ToggleBorderlessWindowed(void) void ToggleBorderlessWindowed(void)
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE)) if (FLAG_IS_SET(CORE.Window.flags, FLAG_BORDERLESS_WINDOWED_MODE))
@ -539,12 +551,11 @@ void SetWindowState(unsigned int flags)
if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE)) if (FLAG_IS_SET(flags, FLAG_FULLSCREEN_MODE))
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN); SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN);
@ -601,12 +612,11 @@ void SetWindowState(unsigned int flags)
if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE)) if (FLAG_IS_SET(flags, FLAG_BORDERLESS_WINDOWED_MODE))
{ {
const int monitor = SDL_GetWindowDisplayIndex(platform.window); const int monitor = SDL_GetWindowDisplayIndex(platform.window);
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_SetWindowFullscreen(platform.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
@ -823,11 +833,10 @@ void SetWindowPosition(int x, int y)
// Set monitor for the current window // Set monitor for the current window
void SetWindowMonitor(int monitor) void SetWindowMonitor(int monitor)
{ {
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
// NOTE 1: SDL started supporting moving exclusive fullscreen windows between displays on SDL3, // NOTE 1: SDL started supporting moving exclusive fullscreen windows between displays on SDL3,
@ -855,7 +864,7 @@ void SetWindowMonitor(int monitor)
// ending up positioned partly outside the target display // ending up positioned partly outside the target display
// NOTE 2: The workaround for that is, previously to moving the window, // NOTE 2: The workaround for that is, previously to moving the window,
// setting the window size to the target display size, so they match // setting the window size to the target display size, so they match
// NOTE 3: It wasn't done here because it can not bee assumed that changing // NOTE 3: It wasn't done here because it can not be assumed that changing
// the window size automatically is acceptable behavior by the user // the window size automatically is acceptable behavior by the user
SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y); SDL_SetWindowPosition(platform.window, usableBounds.x, usableBounds.y);
CORE.Window.position.x = usableBounds.x; CORE.Window.position.x = usableBounds.x;
@ -920,40 +929,82 @@ void SetWindowFocused(void)
} }
// Get native window handle // Get native window handle
// NOTE: Handle type depends on OS and windowing system
void *GetWindowHandle(void) void *GetWindowHandle(void)
{ {
return (void *)platform.window; void *handle = NULL;
#if defined(USING_SDL3_PROJECT)
// REF: https://github.com/libsdl-org/SDL/blob/main/include/SDL3/SDL_video.h#L1590
SDL_PropertiesID props = SDL_GetWindowProperties(platform.window);
#if defined(_WIN32)
handle = (void *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); // Type: HWND
#elif defined(__linux__)
unsigned long windowId = (unsigned long)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); // Type: unsigned long (XID, Window)
if (windowId != 0)
{
// X11 window ID
platform.windowHandleX11 = windowId;
handle = &platform.windowHandleX11;
}
else
{
// Wayland, get display surface pointer
// NOTE: Alternative SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER
handle = (void *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, NULL); // Type: struct wl_surface*
}
#elif defined(__APPLE__)
handle = (void *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); // Type: NSWindow*
#endif
#elif defined(USING_SDL2_PROJECT)
SDL_SysWMinfo wmInfo = { 0 };
SDL_VERSION(&wmInfo.version);
if (SDL_GetWindowWMInfo(platform.window, &wmInfo))
{
#if defined(_WIN32)
handle = (void *)wmInfo.info.win.window; // Type: HWND
#elif defined(__linux__)
if (wmInfo.subsystem == SDL_SYSWM_X11)
{
// X11, get window ID (unsigned long)
platform.windowHandleX11 = (unsigned long)wmInfo.info.x11.window;
handle = &platform.windowHandleX11;
}
else if (wmInfo.subsystem == SDL_SYSWM_WAYLAND)
{
// Wayland, get display surface pointer
// NOTE: Alternative: wmInfo.info.wl.display
handle = (void *)wmInfo.info.wl.surface; // Type: struct wl_surface*
}
#elif defined(__APPLE__)
handle = (void *)wmInfo.info.cocoa.window; // Type: NSWindow*
#endif
}
#endif
return handle;
} }
// Get number of monitors // Get number of monitors
int GetMonitorCount(void) int GetMonitorCount(void)
{ {
int monitorCount = 0; return SDL_GetNumVideoDisplays();
monitorCount = SDL_GetNumVideoDisplays();
return monitorCount;
} }
// Get current monitor where window is placed // Get current monitor where window is placed
int GetCurrentMonitor(void) int GetCurrentMonitor(void)
{ {
int currentMonitor = 0;
// Be aware that this returns an ID in SDL3 and a Index in SDL2 // Be aware that this returns an ID in SDL3 and a Index in SDL2
currentMonitor = SDL_GetWindowDisplayIndex(platform.window); return SDL_GetWindowDisplayIndex(platform.window);
return currentMonitor;
} }
// Get selected monitor position // Get selected monitor position
Vector2 GetMonitorPosition(int monitor) Vector2 GetMonitorPosition(int monitor)
{ {
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_Rect displayBounds; SDL_Rect displayBounds;
@ -977,11 +1028,10 @@ int GetMonitorWidth(int monitor)
{ {
int width = 0; int width = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_DisplayMode mode; SDL_DisplayMode mode;
@ -998,11 +1048,10 @@ int GetMonitorHeight(int monitor)
{ {
int height = 0; int height = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_DisplayMode mode; SDL_DisplayMode mode;
@ -1019,11 +1068,10 @@ int GetMonitorPhysicalWidth(int monitor)
{ {
int width = 0; int width = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
float ddpi = 0.0f; float ddpi = 0.0f;
@ -1043,11 +1091,10 @@ int GetMonitorPhysicalHeight(int monitor)
{ {
int height = 0; int height = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
float ddpi = 0.0f; float ddpi = 0.0f;
@ -1067,11 +1114,10 @@ int GetMonitorRefreshRate(int monitor)
{ {
int refresh = 0; int refresh = 0;
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
SDL_DisplayMode mode; SDL_DisplayMode mode;
@ -1086,12 +1132,10 @@ int GetMonitorRefreshRate(int monitor)
// Get the human-readable, UTF-8 encoded name of the selected monitor // Get the human-readable, UTF-8 encoded name of the selected monitor
const char *GetMonitorName(int monitor) const char *GetMonitorName(int monitor)
{ {
const int monitorCount = SDL_GetNumVideoDisplays();
#if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure #if defined(USING_VERSION_SDL3) // SDL3 Migration: Monitor is an id instead of index now, returns 0 on failure
if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid if (SDL_GetDisplayProperties(monitor) != 0) // Returns 0 on failure, so a value other than zero indicates that the monitor id is valid
#else #else
if ((monitor >= 0) && (monitor < monitorCount)) if ((monitor >= 0) && (monitor < SDL_GetNumVideoDisplays()))
#endif #endif
{ {
return SDL_GetDisplayName(monitor); return SDL_GetDisplayName(monitor);
@ -1144,7 +1188,7 @@ const char *GetClipboardText(void)
char *clipboard = SDL_GetClipboardText(); char *clipboard = SDL_GetClipboardText();
int clipboardSize = snprintf(buffer, sizeof(buffer), "%s", clipboard); int clipboardSize = snprintf(buffer, MAX_CLIPBOARD_BUFFER_LENGTH, "%s", clipboard);
if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH) if (clipboardSize >= MAX_CLIPBOARD_BUFFER_LENGTH)
{ {
char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4; char *truncate = buffer + MAX_CLIPBOARD_BUFFER_LENGTH - 4;
@ -1196,12 +1240,14 @@ Image GetClipboardImage(void)
for (int i = 0; i < SDL_arraysize(imageFormats); i++) for (int i = 0; i < SDL_arraysize(imageFormats); i++)
{ {
// NOTE: This pointer should be free with SDL_free() at some point
fileData = SDL_GetClipboardData(imageFormats[i], &dataSize); fileData = SDL_GetClipboardData(imageFormats[i], &dataSize);
if (fileData) if (fileData)
{ {
image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize); image = LoadImageFromMemory(imageExtensions[i], fileData, (int)dataSize);
SDL_free(fileData);
if (IsImageValid(image)) if (IsImageValid(image))
{ {
TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]); TRACELOG(LOG_INFO, "Clipboard: Got image from clipboard successfully: %s", imageExtensions[i]);
@ -1227,7 +1273,7 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
@ -1238,7 +1284,7 @@ void HideCursor(void)
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
SDL_SetRelativeMouseMode(SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE);
@ -1247,7 +1293,7 @@ void EnableCursor(void)
CORE.Input.Mouse.cursorLocked = false; CORE.Input.Mouse.cursorLocked = false;
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
SDL_SetRelativeMouseMode(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE);
@ -1282,14 +1328,22 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if the provided URL is safe // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Avoid calling this function with user input non-validated strings // NOTE: Some safety checks have been added to mitigate security issues
// REF: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else SDL_OpenURL(url); else SDL_OpenURL(url);
} }
@ -1342,7 +1396,6 @@ void SetMousePosition(int x, int y)
SDL_WarpMouseInWindow(platform.window, x, y); SDL_WarpMouseInWindow(platform.window, x, y);
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
// Set mouse cursor // Set mouse cursor
@ -1453,9 +1506,9 @@ void PollInputEvents(void)
// Event memory is now managed by SDL, so it should not be freed in SDL_EVENT_DROP_FILE, // Event memory is now managed by SDL, so it should not be freed in SDL_EVENT_DROP_FILE,
// in case data needs to be hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events, // in case data needs to be hold onto the text in SDL_EVENT_TEXT_EDITING and SDL_EVENT_TEXT_INPUT events,
// a copy is required, SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed // a copy is required, SDL_TEXTINPUTEVENT_TEXT_SIZE is no longer necessary and has been removed
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data);
#else #else
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file);
SDL_free(event.drop.file); SDL_free(event.drop.file);
#endif #endif
@ -1466,9 +1519,9 @@ void PollInputEvents(void)
CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[CORE.Window.dropFileCount] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.data, MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.data);
#else #else
strncpy(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], event.drop.file, MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[CORE.Window.dropFileCount], MAX_FILEPATH_LENGTH, "%s", event.drop.file);
SDL_free(event.drop.file); SDL_free(event.drop.file);
#endif #endif
@ -1584,7 +1637,7 @@ void PollInputEvents(void)
} break; } break;
#endif #endif
// Keyboard events // Check keyboard events
case SDL_KEYDOWN: case SDL_KEYDOWN:
{ {
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
@ -1612,10 +1665,8 @@ void PollInputEvents(void)
if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true; if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey]) CORE.Window.shouldClose = true;
} break; } break;
case SDL_KEYUP: case SDL_KEYUP:
{ {
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
KeyboardKey key = ConvertScancodeToKey(event.key.scancode); KeyboardKey key = ConvertScancodeToKey(event.key.scancode);
#else #else
@ -1623,7 +1674,6 @@ void PollInputEvents(void)
#endif #endif
if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0; if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break; } break;
case SDL_TEXTINPUT: case SDL_TEXTINPUT:
{ {
// NOTE: event.text.text data comes an UTF-8 text sequence but register codepoints (int) // NOTE: event.text.text data comes an UTF-8 text sequence but register codepoints (int)
@ -1632,7 +1682,6 @@ void PollInputEvents(void)
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE) if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{ {
// Add character (codepoint) to the queue // Add character (codepoint) to the queue
#if defined(USING_VERSION_SDL3) #if defined(USING_VERSION_SDL3)
size_t textLen = strlen(event.text.text); size_t textLen = strlen(event.text.text);
unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, &textLen); unsigned int codepoint = (unsigned int)SDL_StepUTF8(&event.text.text, &textLen);
@ -1675,8 +1724,13 @@ void PollInputEvents(void)
} break; } break;
case SDL_MOUSEWHEEL: case SDL_MOUSEWHEEL:
{ {
CORE.Input.Mouse.currentWheelMove.x = (float)event.wheel.x; #if defined(USING_VERSION_SDL3)
CORE.Input.Mouse.currentWheelMove.y = (float)event.wheel.y; CORE.Input.Mouse.currentWheelMove.x = event.wheel.x;
CORE.Input.Mouse.currentWheelMove.y = event.wheel.y;
#else
CORE.Input.Mouse.currentWheelMove.x = event.wheel.preciseX;
CORE.Input.Mouse.currentWheelMove.y = event.wheel.preciseY;
#endif
} break; } break;
case SDL_MOUSEMOTION: case SDL_MOUSEMOTION:
{ {
@ -1696,6 +1750,7 @@ void PollInputEvents(void)
touchAction = 2; touchAction = 2;
} break; } break;
// Check Touch events
case SDL_FINGERDOWN: case SDL_FINGERDOWN:
{ {
UpdateTouchPointsSDL(event.tfinger); UpdateTouchPointsSDL(event.tfinger);
@ -1715,24 +1770,21 @@ void PollInputEvents(void)
realTouch = true; realTouch = true;
} break; } break;
// Check gamepad events // Check Gamepad events
case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEADDED:
{ {
int jid = event.jdevice.which; // Joystick device index int jid = event.jdevice.which; // Joystick device index
// check if already added at InitPlatform // Check if already added at InitPlatform
for (int i = 0; i < MAX_GAMEPADS; i++) for (int i = 0; i < MAX_GAMEPADS; i++)
{ {
if (jid == platform.gamepadId[i]) if (jid == platform.gamepadId[i]) return;
{
return;
}
} }
int nextAvailableSlot = 0; int nextAvailableSlot = 0;
while (nextAvailableSlot < MAX_GAMEPADS && CORE.Input.Gamepad.ready[nextAvailableSlot]) while (nextAvailableSlot < MAX_GAMEPADS && CORE.Input.Gamepad.ready[nextAvailableSlot])
{ {
++nextAvailableSlot; nextAvailableSlot++;
} }
if ((nextAvailableSlot < MAX_GAMEPADS) && !CORE.Input.Gamepad.ready[nextAvailableSlot]) if ((nextAvailableSlot < MAX_GAMEPADS) && !CORE.Input.Gamepad.ready[nextAvailableSlot])
@ -1748,8 +1800,8 @@ void PollInputEvents(void)
CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[nextAvailableSlot][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH); memset(CORE.Input.Gamepad.name[nextAvailableSlot], 0, MAX_GAMEPAD_NAME_LENGTH);
const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot); const char *controllerName = SDL_GameControllerNameForIndex(nextAvailableSlot);
if (controllerName != NULL) strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], controllerName, MAX_GAMEPAD_NAME_LENGTH - 1); if (controllerName != NULL) snprintf(CORE.Input.Gamepad.name[nextAvailableSlot], MAX_GAMEPAD_NAME_LENGTH, "%s", controllerName);
else strncpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6); else memcpy(CORE.Input.Gamepad.name[nextAvailableSlot], "noname", 6);
} }
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());
} }
@ -2100,11 +2152,20 @@ int InitPlatform(void)
platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero platform.gamepadId[i] = -1; // Set all gamepad initial instance ids as invalid to not conflict with instance id zero
} }
#if defined(USING_VERSION_SDL3)
int numJoysticks;
SDL_JoystickID *joysticks = SDL_GetJoysticks(&numJoysticks);
#else
int numJoysticks = SDL_NumJoysticks(); int numJoysticks = SDL_NumJoysticks();
#endif
for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++) for (int i = 0; (i < numJoysticks) && (i < MAX_GAMEPADS); i++)
{ {
#if defined(USING_VERSION_SDL3)
platform.gamepad[i] = SDL_OpenGamepad(joysticks[i]);
#else
platform.gamepad[i] = SDL_GameControllerOpen(i); platform.gamepad[i] = SDL_GameControllerOpen(i);
#endif
platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i])); platform.gamepadId[i] = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(platform.gamepad[i]));
if (platform.gamepad[i]) if (platform.gamepad[i])
@ -2113,7 +2174,12 @@ int InitPlatform(void)
CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i])); CORE.Input.Gamepad.axisCount[i] = SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(platform.gamepad[i]));
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] = -1.0f;
CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f; CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] = -1.0f;
strncpy(CORE.Input.Gamepad.name[i], SDL_GameControllerNameForIndex(i), MAX_GAMEPAD_NAME_LENGTH - 1); #if defined(USING_VERSION_SDL3)
const char *joystickName = SDL_GetJoystickNameForID(joysticks[i]);
#else
const char *joystickName = SDL_GameControllerNameForIndex(i);
#endif
snprintf(CORE.Input.Gamepad.name[i], MAX_GAMEPAD_NAME_LENGTH, "%s", joystickName);
CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0'; CORE.Input.Gamepad.name[i][MAX_GAMEPAD_NAME_LENGTH - 1] = '\0';
} }
else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError()); else TRACELOG(LOG_WARNING, "PLATFORM: Unable to open game controller [ERROR: %s]", SDL_GetError());

View file

@ -566,100 +566,100 @@ static KeyboardKey GetKeyFromWparam(WPARAM wparam)
case 'X': return KEY_X; case 'X': return KEY_X;
case 'Y': return KEY_Y; case 'Y': return KEY_Y;
case 'Z': return KEY_Z; case 'Z': return KEY_Z;
/* case VK_LWIN: return KEY_; */ //case VK_LWIN: return KEY_;
/* case VK_RWIN: return KEY_; */ //case VK_RWIN: return KEY_;
/* case VK_APPS: return KEY_; */ //case VK_APPS: return KEY_;
/* case VK_SLEEP: return KEY_; */ //case VK_SLEEP: return KEY_;
/* case VK_NUMPAD0: return KEY_; */ //case VK_NUMPAD0: return KEY_;
/* case VK_NUMPAD1: return KEY_; */ //case VK_NUMPAD1: return KEY_;
/* case VK_NUMPAD2: return KEY_; */ //case VK_NUMPAD2: return KEY_;
/* case VK_NUMPAD3: return KEY_; */ //case VK_NUMPAD3: return KEY_;
/* case VK_NUMPAD4: return KEY_; */ //case VK_NUMPAD4: return KEY_;
/* case VK_NUMPAD5: return KEY_; */ //case VK_NUMPAD5: return KEY_;
/* case VK_NUMPAD6: return KEY_; */ //case VK_NUMPAD6: return KEY_;
/* case VK_NUMPAD7: return KEY_; */ //case VK_NUMPAD7: return KEY_;
/* case VK_NUMPAD8: return KEY_; */ //case VK_NUMPAD8: return KEY_;
/* case VK_NUMPAD9: return KEY_; */ //case VK_NUMPAD9: return KEY_;
/* case VK_MULTIPLY: return KEY_; */ //case VK_MULTIPLY: return KEY_;
/* case VK_ADD: return KEY_; */ //case VK_ADD: return KEY_;
/* case VK_SEPARATOR: return KEY_; */ //case VK_SEPARATOR: return KEY_;
/* case VK_SUBTRACT: return KEY_; */ //case VK_SUBTRACT: return KEY_;
/* case VK_DECIMAL: return KEY_; */ //case VK_DECIMAL: return KEY_;
/* case VK_DIVIDE: return KEY_; */ //case VK_DIVIDE: return KEY_;
/* case VK_F1: return KEY_; */ //case VK_F1: return KEY_;
/* case VK_F2: return KEY_; */ //case VK_F2: return KEY_;
/* case VK_F3: return KEY_; */ //case VK_F3: return KEY_;
/* case VK_F4: return KEY_; */ //case VK_F4: return KEY_;
/* case VK_F5: return KEY_; */ //case VK_F5: return KEY_;
/* case VK_F6: return KEY_; */ //case VK_F6: return KEY_;
/* case VK_F7: return KEY_; */ //case VK_F7: return KEY_;
/* case VK_F8: return KEY_; */ //case VK_F8: return KEY_;
/* case VK_F9: return KEY_; */ //case VK_F9: return KEY_;
/* case VK_F10: return KEY_; */ //case VK_F10: return KEY_;
/* case VK_F11: return KEY_; */ //case VK_F11: return KEY_;
/* case VK_F12: return KEY_; */ //case VK_F12: return KEY_;
/* case VK_F13: return KEY_; */ //case VK_F13: return KEY_;
/* case VK_F14: return KEY_; */ //case VK_F14: return KEY_;
/* case VK_F15: return KEY_; */ //case VK_F15: return KEY_;
/* case VK_F16: return KEY_; */ //case VK_F16: return KEY_;
/* case VK_F17: return KEY_; */ //case VK_F17: return KEY_;
/* case VK_F18: return KEY_; */ //case VK_F18: return KEY_;
/* case VK_F19: return KEY_; */ //case VK_F19: return KEY_;
/* case VK_F20: return KEY_; */ //case VK_F20: return KEY_;
/* case VK_F21: return KEY_; */ //case VK_F21: return KEY_;
/* case VK_F22: return KEY_; */ //case VK_F22: return KEY_;
/* case VK_F23: return KEY_; */ //case VK_F23: return KEY_;
/* case VK_F24: return KEY_; */ //case VK_F24: return KEY_;
/* case VK_NUMLOCK: return KEY_; */ //case VK_NUMLOCK: return KEY_;
/* case VK_SCROLL: return KEY_; */ //case VK_SCROLL: return KEY_;
/* case VK_LSHIFT: return KEY_; */ //case VK_LSHIFT: return KEY_;
/* case VK_RSHIFT: return KEY_; */ //case VK_RSHIFT: return KEY_;
/* case VK_LCONTROL: return KEY_; */ //case VK_LCONTROL: return KEY_;
/* case VK_RCONTROL: return KEY_; */ //case VK_RCONTROL: return KEY_;
/* case VK_LMENU: return KEY_; */ //case VK_LMENU: return KEY_;
/* case VK_RMENU: return KEY_; */ //case VK_RMENU: return KEY_;
/* case VK_BROWSER_BACK: return KEY_; */ //case VK_BROWSER_BACK: return KEY_;
/* case VK_BROWSER_FORWARD: return KEY_; */ //case VK_BROWSER_FORWARD: return KEY_;
/* case VK_BROWSER_REFRESH: return KEY_; */ //case VK_BROWSER_REFRESH: return KEY_;
/* case VK_BROWSER_STOP: return KEY_; */ //case VK_BROWSER_STOP: return KEY_;
/* case VK_BROWSER_SEARCH: return KEY_; */ //case VK_BROWSER_SEARCH: return KEY_;
/* case VK_BROWSER_FAVORITES: return KEY_; */ //case VK_BROWSER_FAVORITES: return KEY_;
/* case VK_BROWSER_HOME: return KEY_; */ //case VK_BROWSER_HOME: return KEY_;
/* case VK_VOLUME_MUTE: return KEY_; */ //case VK_VOLUME_MUTE: return KEY_;
/* case VK_VOLUME_DOWN: return KEY_; */ //case VK_VOLUME_DOWN: return KEY_;
/* case VK_VOLUME_UP: return KEY_; */ //case VK_VOLUME_UP: return KEY_;
/* case VK_MEDIA_NEXT_TRACK: return KEY_; */ //case VK_MEDIA_NEXT_TRACK: return KEY_;
/* case VK_MEDIA_PREV_TRACK: return KEY_; */ //case VK_MEDIA_PREV_TRACK: return KEY_;
/* case VK_MEDIA_STOP: return KEY_; */ //case VK_MEDIA_STOP: return KEY_;
/* case VK_MEDIA_PLAY_PAUSE: return KEY_; */ //case VK_MEDIA_PLAY_PAUSE: return KEY_;
/* case VK_LAUNCH_MAIL: return KEY_; */ //case VK_LAUNCH_MAIL: return KEY_;
/* case VK_LAUNCH_MEDIA_SELECT: return KEY_; */ //case VK_LAUNCH_MEDIA_SELECT: return KEY_;
/* case VK_LAUNCH_APP1: return KEY_; */ //case VK_LAUNCH_APP1: return KEY_;
/* case VK_LAUNCH_APP2: return KEY_; */ //case VK_LAUNCH_APP2: return KEY_;
/* case VK_OEM_1: return KEY_; */ //case VK_OEM_1: return KEY_;
/* case VK_OEM_PLUS: return KEY_; */ //case VK_OEM_PLUS: return KEY_;
/* case VK_OEM_COMMA: return KEY_; */ //case VK_OEM_COMMA: return KEY_;
/* case VK_OEM_MINUS: return KEY_; */ //case VK_OEM_MINUS: return KEY_;
/* case VK_OEM_PERIOD: return KEY_; */ //case VK_OEM_PERIOD: return KEY_;
/* case VK_OEM_2: return KEY_; */ //case VK_OEM_2: return KEY_;
/* case VK_OEM_3: return KEY_; */ //case VK_OEM_3: return KEY_;
/* case VK_OEM_4: return KEY_; */ //case VK_OEM_4: return KEY_;
/* case VK_OEM_5: return KEY_; */ //case VK_OEM_5: return KEY_;
/* case VK_OEM_6: return KEY_; */ //case VK_OEM_6: return KEY_;
/* case VK_OEM_7: return KEY_; */ //case VK_OEM_7: return KEY_;
/* case VK_OEM_8: return KEY_; */ //case VK_OEM_8: return KEY_;
/* case VK_OEM_102: return KEY_; */ //case VK_OEM_102: return KEY_;
/* case VK_PROCESSKEY: return KEY_; */ //case VK_PROCESSKEY: return KEY_;
/* case VK_PACKET: return KEY_; */ //case VK_PACKET: return KEY_;
/* case VK_ATTN: return KEY_; */ //case VK_ATTN: return KEY_;
/* case VK_CRSEL: return KEY_; */ //case VK_CRSEL: return KEY_;
/* case VK_EXSEL: return KEY_; */ //case VK_EXSEL: return KEY_;
/* case VK_EREOF: return KEY_; */ //case VK_EREOF: return KEY_;
/* case VK_PLAY: return KEY_; */ //case VK_PLAY: return KEY_;
/* case VK_ZOOM: return KEY_; */ //case VK_ZOOM: return KEY_;
/* case VK_NONAME: return KEY_; */ //case VK_NONAME: return KEY_;
/* case VK_PA1: return KEY_; */ //case VK_PA1: return KEY_;
/* case VK_OEM_CLEAR: return KEY_; */ //case VK_OEM_CLEAR: return KEY_;
default: return KEY_NULL; default: return KEY_NULL;
} }
} }
@ -1023,7 +1023,7 @@ void SetWindowFocused(void)
// Get native window handle // Get native window handle
void *GetWindowHandle(void) void *GetWindowHandle(void)
{ {
return platform.hwnd; return (void *)platform.hwnd;
} }
int GetMonitorCount(void) int GetMonitorCount(void)
@ -1129,12 +1129,37 @@ const char *GetClipboardText(void)
return NULL; return NULL;
} }
#if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
#define WIN32_CLIPBOARD_IMPLEMENTATION
#define WINUSER_ALREADY_INCLUDED
#define WINBASE_ALREADY_INCLUDED
#define WINGDI_ALREADY_INCLUDED
#include "../external/win32_clipboard.h"
#endif
// Get clipboard image // Get clipboard image
Image GetClipboardImage(void) Image GetClipboardImage(void)
{ {
Image image = { 0 }; Image image = { 0 };
TRACELOG(LOG_WARNING, "GetClipboardText not implemented"); #if SUPPORT_CLIPBOARD_IMAGE && SUPPORT_MODULE_RTEXTURES
unsigned int dataSize = 0;
void *fileData = NULL;
int width = 0;
int height = 0;
fileData = (void *)Win32GetClipboardImageData(&width, &height, &dataSize);
if (fileData == NULL) TRACELOG(LOG_WARNING, "Clipboard image: Couldn't get clipboard data.");
else
{
image = LoadImageFromMemory(".bmp", (const unsigned char*)fileData, (int)dataSize);
RL_FREE(fileData);
}
#else
TRACELOG(LOG_WARNING, "Clipboard image: SUPPORT_CLIPBOARD_IMAGE requires SUPPORT_MODULE_RTEXTURES to work properly");
#endif // SUPPORT_CLIPBOARD_IMAGE
return image; return image;
} }
@ -1146,7 +1171,7 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
// NOTE: Using SetCursor() instead of ShowCursor() because // NOTE: Using SetCursor() instead of ShowCursor() because
@ -1155,7 +1180,7 @@ void HideCursor(void)
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
if (CORE.Input.Mouse.cursorLocked) if (CORE.Input.Mouse.cursorLocked)
@ -1247,18 +1272,28 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if the provided URL is safe // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Avoid calling this function with user input non-validated strings // NOTE: Some safety checks have been added to mitigate security issues
// REF: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code on target platform // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else else
{ {
char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char)); int len = strlen(url) + 16;
sprintf(cmd, "explorer \"%s\"", url); char *cmd = (char *)RL_CALLOC(len, sizeof(char));
snprintf(cmd, len, "explorer \"%s\"", url);
int result = system(cmd); int result = system(cmd);
if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created"); if (result == -1) TRACELOG(LOG_WARNING, "OpenURL() child process could not be created");
RL_FREE(cmd); RL_FREE(cmd);
@ -1289,8 +1324,8 @@ void SetMousePosition(int x, int y)
if (!CORE.Input.Mouse.cursorLocked) if (!CORE.Input.Mouse.cursorLocked)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
TRACELOG(LOG_WARNING, "SetMousePosition not implemented"); TRACELOG(LOG_WARNING, "SetMousePosition not implemented at platform level");
} }
else TRACELOG(LOG_WARNING, "INPUT: MOUSE: Cursor not enabled"); else TRACELOG(LOG_WARNING, "INPUT: MOUSE: Cursor not enabled");
} }
@ -1526,7 +1561,6 @@ int InitPlatform(void)
if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr); if (hr < 0) TRACELOG(LOG_ERROR, "%s failed, hresult=0x%lx", "SetProcessDpiAwareness", (DWORD)hr);
} }
*/ */
HINSTANCE hInstance = GetModuleHandleW(0); HINSTANCE hInstance = GetModuleHandleW(0);
// Define window class // Define window class
@ -2034,7 +2068,7 @@ static void HandleKey(WPARAM wparam, LPARAM lparam, char state)
{ {
CORE.Input.Keyboard.currentKeyState[key] = state; CORE.Input.Keyboard.currentKeyState[key] = state;
if ((key == KEY_ESCAPE) && (state == 1)) CORE.Window.shouldClose = true; if ((key == CORE.Input.Keyboard.exitKey) && (state == 1)) CORE.Window.shouldClose = true;
} }
else TRACELOG(LOG_WARNING, "INPUT: Unknown (or currently unhandled) virtual keycode %d (0x%x)", wparam, wparam); else TRACELOG(LOG_WARNING, "INPUT: Unknown (or currently unhandled) virtual keycode %d (0x%x)", wparam, wparam);
@ -2053,8 +2087,11 @@ static void HandleMouseButton(int button, char state)
static void HandleRawInput(LPARAM lparam) static void HandleRawInput(LPARAM lparam)
{ {
RAWINPUT input = { 0 }; RAWINPUT input = { 0 };
UINT inputSize = 0;
if (GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &inputSize, sizeof(RAWINPUTHEADER)) != 0) return;
if (inputSize > sizeof(input)) return;
UINT inputSize = sizeof(input);
UINT size = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &input, &inputSize, sizeof(RAWINPUTHEADER)); UINT size = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &input, &inputSize, sizeof(RAWINPUTHEADER));
if (size == (UINT)-1) TRACELOG(LOG_ERROR, "WIN32: Failed to get raw input data [ERROR: %lu]", GetLastError()); if (size == (UINT)-1) TRACELOG(LOG_ERROR, "WIN32: Failed to get raw input data [ERROR: %lu]", GetLastError());
@ -2210,7 +2247,7 @@ static unsigned SanitizeFlags(int mode, unsigned flags)
// //
// This design takes care of many odd corner cases. For example, in case of restoring // This design takes care of many odd corner cases. For example, in case of restoring
// a window that was previously maximized AND minimized and those two flags need to be removed, // a window that was previously maximized AND minimized and those two flags need to be removed,
// ShowWindow with SW_RESTORE twice need to bee actually calleed. Another example is // ShowWindow with SW_RESTORE twice need to be actually calleed. Another example is
// wheen having a maximized window, if the undecorated flag is modified then the window style // wheen having a maximized window, if the undecorated flag is modified then the window style
// needs to be updated, but updating the style would mean the window size would change // needs to be updated, but updating the style would mean the window size would change
// causing the window to lose its Maximized state which would mean the window size // causing the window to lose its Maximized state which would mean the window size

View file

@ -79,7 +79,11 @@
#include <poll.h> // Required for: drmHandleEvent() poll #include <poll.h> // Required for: drmHandleEvent() poll
#include <errno.h> // Required for: EBUSY, EAGAIN #include <errno.h> // Required for: EBUSY, EAGAIN
#define MAX_DRM_CACHED_BUFFERS 3 // NOTE: Some drivers rotate more buffers than others, mesa uses 3 but the
// ARM Mali blob on RK3326 uses 4. A buffer beyond this count can not get a
// framebuffer and the display stops updating for good, so this must not be
// lower than any driver in use
#define MAX_DRM_CACHED_BUFFERS 4
#endif #endif
#ifndef EGL_OPENGL_ES3_BIT #ifndef EGL_OPENGL_ES3_BIT
@ -110,6 +114,9 @@ typedef struct {
drmModeCrtc *crtc; // CRT Controller drmModeCrtc *crtc; // CRT Controller
int modeIndex; // Index of the used mode of connector->modes int modeIndex; // Index of the used mode of connector->modes
uint32_t prevFB; // Previous DRM framebufer (during frame swapping) uint32_t prevFB; // Previous DRM framebufer (during frame swapping)
#if defined(SUPPORT_DRM_CACHE)
bool fbCacheFullReported; // Framebuffer cache exhaustion already reported
#endif
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE) #if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
struct gbm_device *gbmDevice; // GBM device struct gbm_device *gbmDevice; // GBM device
@ -266,9 +273,12 @@ static void PollKeyboardEvents(void); // Process evdev keyboard events
static void PollGamepadEvents(void); // Process evdev gamepad events static void PollGamepadEvents(void); // Process evdev gamepad events
static void PollMouseEvents(void); // Process evdev mouse events static void PollMouseEvents(void); // Process evdev mouse events
// Not used by software rendering.
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list
static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list
static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list static int FindNearestConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search the nearest matching DRM connector mode in connector's list
#endif
static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform()) static void SetupFramebuffer(int width, int height); // Setup main framebuffer (required by InitPlatform())
@ -561,13 +571,13 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -577,7 +587,7 @@ void EnableCursor(void)
CORE.Input.Mouse.cursorLocked = false; CORE.Input.Mouse.cursorLocked = false;
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -621,7 +631,18 @@ static uint32_t GetOrCreateFbForBo(struct gbm_bo *bo)
} }
// Create new entry if cache not full // Create new entry if cache not full
if (fbCacheCount >= MAX_DRM_CACHED_BUFFERS) return 0; // FB cache full if (fbCacheCount >= MAX_DRM_CACHED_BUFFERS)
{
// NOTE: Once this happens no page flip is ever scheduled again and the
// screen freezes while the game keeps running, so say it out loud once
if (!platform.fbCacheFullReported)
{
platform.fbCacheFullReported = true;
TRACELOG(LOG_WARNING, "DISPLAY: DRM: Framebuffer cache full (%i buffers), display will stop updating", MAX_DRM_CACHED_BUFFERS);
}
return 0; // FB cache full
}
uint32_t handle = gbm_bo_get_handle(bo).u32; uint32_t handle = gbm_bo_get_handle(bo).u32;
uint32_t stride = gbm_bo_get_stride(bo); uint32_t stride = gbm_bo_get_stride(bo);
@ -1003,7 +1024,7 @@ double GetTime(void)
double time = 0.0; double time = 0.0;
struct timespec ts = { 0 }; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
@ -1011,9 +1032,8 @@ double GetTime(void)
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if the provided URL is safe // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Avoid calling this function with user input non-validated strings
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform"); TRACELOG(LOG_WARNING, "OpenURL() not implemented on target platform");
@ -1040,7 +1060,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
// Set mouse cursor // Set mouse cursor
@ -1117,7 +1136,7 @@ void PollInputEvents(void)
// NOTE: For DRM touchscreen devices, this mapping is disabled to avoid false touch detection // NOTE: For DRM touchscreen devices, this mapping is disabled to avoid false touch detection
// CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; // CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
// Handle the mouse/touch/gestures events: // Handle the mouse/touch/gestures events
PollMouseEvents(); PollMouseEvents();
} }
@ -1443,7 +1462,9 @@ int InitPlatform(void)
return -1; return -1;
} }
if (!eglChooseConfig(platform.device, NULL, NULL, 0, &numConfigs)) // WARNING: Providing framebufferAttribs is not logically necessary,
// but it may prevent segfaults on some nvidia drivers
if (!eglChooseConfig(platform.device, framebufferAttribs, NULL, 0, &numConfigs))
{ {
TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError()); TRACELOG(LOG_WARNING, "DISPLAY: Failed to get EGL config count: 0x%x", eglGetError());
return -1; return -1;
@ -1935,6 +1956,7 @@ static void InitEvdevInput(void)
(strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*" (strncmp("mouse", entity->d_name, strlen("mouse")) == 0)) // Search for devices named "mouse*"
{ {
snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name); snprintf(path, MAX_FILEPATH_LENGTH, "%s%s", DEFAULT_EVDEV_PATH, entity->d_name);
ConfigureEvdevDevice(path); // Configure the device if appropriate ConfigureEvdevDevice(path); // Configure the device if appropriate
} }
} }
@ -2560,6 +2582,7 @@ static void PollMouseEvents(void)
} }
} }
#if !defined(GRAPHICS_API_OPENGL_SOFTWARE)
// Search matching DRM mode in connector's mode list // Search matching DRM mode in connector's mode list
static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode) static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode)
{ {
@ -2648,6 +2671,7 @@ static int FindNearestConnectorMode(const drmModeConnector *connector, uint widt
return nearestIndex; return nearestIndex;
} }
#endif
// Compute framebuffer size relative to screen size and display size // Compute framebuffer size relative to screen size and display size
// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified // NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified

View file

@ -91,7 +91,7 @@ bool InitGraphicsDevice(void); // Initialize graphics device
// Module Internal Functions Declaration // Module Internal Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if !defined(_WIN32) #if !defined(_WIN32)
static int kbhit(void); // Check if a key has been pressed static int kbhit(void); // Check if key has been pressed
static char getch(void) { return getchar(); } // Get pressed character static char getch(void) { return getchar(); } // Get pressed character
#endif #endif
@ -324,13 +324,13 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -339,7 +339,7 @@ void EnableCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -364,14 +364,18 @@ double GetTime(void)
{ {
double time = 0.0; double time = 0.0;
#if defined(_WIN32) #if defined(_WIN32)
LARGE_INTEGER now = { 0 }; LARGE_INTEGER currentTicks = { 0 };
QueryPerformanceCounter(&now); QueryPerformanceCounter(&currentTicks);
return (double)(now.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
time = (double)(currentTicks.QuadPart - CORE.Time.base)/(double)platform.timerFrequency.QuadPart;
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__)
struct timespec ts = { 0 }; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
#elif defined(PICO_RP2350)
time = (double)to_ms_since_boot(get_absolute_time())/1000.0;
#endif #endif
return time; return time;
} }
@ -416,7 +420,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
// Set mouse cursor // Set mouse cursor
@ -474,7 +477,7 @@ void PollInputEvents(void)
if (kbhit()) if (kbhit())
{ {
int key = getch(); int key = getch();
if (key == 27) CORE.Window.shouldClose = true; // KEY_SCAPE if (key == 27) CORE.Window.shouldClose = true; // KEY_ESCAPE
} }
} }
@ -558,7 +561,7 @@ void ClosePlatform(void)
// Module Internal Functions Definition // Module Internal Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if !defined(_WIN32) #if !defined(_WIN32)
// Check if a key has been pressed // Check if key has been pressed
static int kbhit(void) static int kbhit(void)
{ {
struct termios oldt = { 0 }; struct termios oldt = { 0 };

View file

@ -303,13 +303,13 @@ void ShowCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
CORE.Input.Mouse.cursorHidden = true; CORE.Input.Mouse.cursorHidden = true;
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -318,7 +318,7 @@ void EnableCursor(void)
CORE.Input.Mouse.cursorHidden = false; CORE.Input.Mouse.cursorHidden = false;
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
// Set cursor position in the middle // Set cursor position in the middle
@ -341,23 +341,33 @@ void SwapScreenBuffer(void)
double GetTime(void) double GetTime(void)
{ {
double time = 0.0; double time = 0.0;
struct timespec ts = { 0 }; struct timespec ts = { 0 };
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
unsigned long long int nanoSeconds = (unsigned long long int)ts.tv_sec*1000000000LLU + (unsigned long long int)ts.tv_nsec; unsigned long long nanoSeconds = (unsigned long long)ts.tv_sec*1000000000LLU + (unsigned long long)ts.tv_nsec;
time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer() time = (double)(nanoSeconds - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
return time; return time;
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if you control the URL given. // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action. // a user could craft a malicious string to perform and undesired action
// Only call this function yourself not with user input or make sure to check the string yourself. // NOTE: Some safety checks have been added to mitigate security issues
// Ref: https://github.com/raysan5/raylib/issues/686
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code on target platform // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else else
{ {
// TODO: Load url using default browser // TODO: Load url using default browser
@ -385,7 +395,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
} }
// Set mouse cursor // Set mouse cursor

View file

@ -76,7 +76,6 @@ typedef struct {
char canvasId[64]; // Keep current canvas id where wasm app is running char canvasId[64]; // Keep current canvas id where wasm app is running
// NOTE: Useful when trying to run multiple wasms in different canvases in same webpage // NOTE: Useful when trying to run multiple wasms in different canvases in same webpage
#if defined(GRAPHICS_API_OPENGL_SOFTWARE) #if defined(GRAPHICS_API_OPENGL_SOFTWARE)
unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format) unsigned int *pixels; // Pointer to pixel data buffer (RGBA 32bit format)
#endif #endif
@ -913,7 +912,7 @@ void ShowCursor(void)
} }
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
if (!CORE.Input.Mouse.cursorHidden) if (!CORE.Input.Mouse.cursorHidden)
@ -924,7 +923,7 @@ void HideCursor(void)
} }
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
emscripten_exit_pointerlock(); emscripten_exit_pointerlock();
@ -935,7 +934,7 @@ void EnableCursor(void)
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback() // NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
emscripten_request_pointerlock(platform.canvasId, 1); emscripten_request_pointerlock(platform.canvasId, 1);
@ -1048,7 +1047,6 @@ void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float d
void SetMousePosition(int x, int y) void SetMousePosition(int x, int y)
{ {
CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y }; CORE.Input.Mouse.currentPosition = (Vector2){ (float)x, (float)y };
CORE.Input.Mouse.previousPosition = CORE.Input.Mouse.currentPosition;
if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.lockedPosition = CORE.Input.Mouse.currentPosition; if (CORE.Input.Mouse.cursorLocked) CORE.Input.Mouse.lockedPosition = CORE.Input.Mouse.currentPosition;
@ -1130,7 +1128,7 @@ void PollInputEvents(void)
// Register previous gamepad button states // Register previous gamepad button states
for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k]; for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousButtonState[i][k] = CORE.Input.Gamepad.currentButtonState[i][k];
EmscriptenGamepadEvent gamepadState; EmscriptenGamepadEvent gamepadState = { 0 };
int result = emscripten_get_gamepad_status(i, &gamepadState); int result = emscripten_get_gamepad_status(i, &gamepadState);
@ -1580,7 +1578,7 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{ {
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
} }
} }
} }

View file

@ -42,6 +42,7 @@
**********************************************************************************************/ **********************************************************************************************/
#include <emscripten/emscripten.h> // Emscripten functionality for C #include <emscripten/emscripten.h> // Emscripten functionality for C
#include <emscripten/dom_pk_codes.h> // Emscripten physical keyboard codes
#include <emscripten/html5.h> // Emscripten HTML5 library #include <emscripten/html5.h> // Emscripten HTML5 library
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX #include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
@ -54,6 +55,9 @@
#define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext. #define _POSIX_C_SOURCE 199309L // Required for: CLOCK_MONOTONIC if compiled with c99 without gnu ext.
#endif #endif
#define DOM_PK_CODE_MAPPED_NUM 128
#define DOM_PK_CODE_EXTENDED_OFFSET 0xE000
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -70,9 +74,121 @@ extern CoreData CORE; // Global CORE state context
static PlatformData platform = { 0 }; // Platform specific data static PlatformData platform = { 0 }; // Platform specific data
//---------------------------------------------------------------------------------- static const KeyboardKey mapDomCodeToKey[DOM_PK_CODE_MAPPED_NUM] = {
// Global Variables Definition [DOM_PK_ESCAPE] = KEY_ESCAPE,
//---------------------------------------------------------------------------------- [DOM_PK_0] = KEY_ZERO,
[DOM_PK_1] = KEY_ONE,
[DOM_PK_2] = KEY_TWO,
[DOM_PK_3] = KEY_THREE,
[DOM_PK_4] = KEY_FOUR,
[DOM_PK_5] = KEY_FIVE,
[DOM_PK_6] = KEY_SIX,
[DOM_PK_7] = KEY_SEVEN,
[DOM_PK_8] = KEY_EIGHT,
[DOM_PK_9] = KEY_NINE,
[DOM_PK_MINUS] = KEY_MINUS,
[DOM_PK_EQUAL] = KEY_EQUAL,
[DOM_PK_BACKSPACE] = KEY_BACKSPACE,
[DOM_PK_TAB] = KEY_TAB,
[DOM_PK_Q] = KEY_Q,
[DOM_PK_W] = KEY_W,
[DOM_PK_E] = KEY_E,
[DOM_PK_R] = KEY_R,
[DOM_PK_T] = KEY_T,
[DOM_PK_Y] = KEY_Y,
[DOM_PK_U] = KEY_U,
[DOM_PK_I] = KEY_I,
[DOM_PK_O] = KEY_O,
[DOM_PK_P] = KEY_P,
[DOM_PK_BRACKET_LEFT] = KEY_LEFT_BRACKET,
[DOM_PK_BRACKET_RIGHT] = KEY_RIGHT_BRACKET,
[DOM_PK_ENTER] = KEY_ENTER,
[DOM_PK_CONTROL_LEFT] = KEY_LEFT_CONTROL,
[DOM_PK_A] = KEY_A,
[DOM_PK_S] = KEY_S,
[DOM_PK_D] = KEY_D,
[DOM_PK_F] = KEY_F,
[DOM_PK_G] = KEY_G,
[DOM_PK_H] = KEY_H,
[DOM_PK_J] = KEY_J,
[DOM_PK_K] = KEY_K,
[DOM_PK_L] = KEY_L,
[DOM_PK_SEMICOLON] = KEY_SEMICOLON,
[DOM_PK_QUOTE] = KEY_APOSTROPHE,
[DOM_PK_BACKQUOTE] = KEY_GRAVE,
[DOM_PK_SHIFT_LEFT] = KEY_LEFT_SHIFT,
[DOM_PK_BACKSLASH] = KEY_BACKSLASH,
[DOM_PK_Z] = KEY_Z,
[DOM_PK_X] = KEY_X,
[DOM_PK_C] = KEY_C,
[DOM_PK_V] = KEY_V,
[DOM_PK_B] = KEY_B,
[DOM_PK_N] = KEY_N,
[DOM_PK_M] = KEY_M,
[DOM_PK_COMMA] = KEY_COMMA,
[DOM_PK_PERIOD] = KEY_PERIOD,
[DOM_PK_SLASH] = KEY_SLASH,
[DOM_PK_SHIFT_RIGHT] = KEY_RIGHT_SHIFT,
[DOM_PK_NUMPAD_MULTIPLY] = KEY_KP_MULTIPLY,
[DOM_PK_ALT_LEFT] = KEY_LEFT_ALT,
[DOM_PK_SPACE] = KEY_SPACE,
[DOM_PK_CAPS_LOCK] = KEY_CAPS_LOCK,
[DOM_PK_F1] = KEY_F1,
[DOM_PK_F2] = KEY_F2,
[DOM_PK_F3] = KEY_F3,
[DOM_PK_F4] = KEY_F4,
[DOM_PK_F5] = KEY_F5,
[DOM_PK_F6] = KEY_F6,
[DOM_PK_F7] = KEY_F7,
[DOM_PK_F8] = KEY_F8,
[DOM_PK_F9] = KEY_F9,
[DOM_PK_F10] = KEY_F10,
[DOM_PK_PAUSE] = KEY_PAUSE,
[DOM_PK_SCROLL_LOCK] = KEY_SCROLL_LOCK,
[DOM_PK_NUMPAD_7] = KEY_KP_7,
[DOM_PK_NUMPAD_8] = KEY_KP_8,
[DOM_PK_NUMPAD_9] = KEY_KP_9,
[DOM_PK_NUMPAD_SUBTRACT] = KEY_KP_SUBTRACT,
[DOM_PK_NUMPAD_4] = KEY_KP_4,
[DOM_PK_NUMPAD_5] = KEY_KP_5,
[DOM_PK_NUMPAD_6] = KEY_KP_6,
[DOM_PK_NUMPAD_ADD] = KEY_KP_ADD,
[DOM_PK_NUMPAD_1] = KEY_KP_1,
[DOM_PK_NUMPAD_2] = KEY_KP_2,
[DOM_PK_NUMPAD_3] = KEY_KP_3,
[DOM_PK_NUMPAD_0] = KEY_KP_0,
[DOM_PK_NUMPAD_DECIMAL] = KEY_KP_DECIMAL,
[DOM_PK_PRINT_SCREEN] = KEY_PRINT_SCREEN,
[DOM_PK_F11] = KEY_F11,
[DOM_PK_F12] = KEY_F12,
[DOM_PK_NUMPAD_EQUAL] = KEY_KP_EQUAL,
[DOM_PK_NUMPAD_COMMA] = KEY_KP_DECIMAL
};
// Emscripten places keys with extended scan codes (right-side modifiers, navigation and some keypad keys) in the 0xE0xx range
static const KeyboardKey mapDomCodeToKeyExtended[DOM_PK_CODE_MAPPED_NUM] = {
[DOM_PK_NUMPAD_ENTER - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_KP_ENTER,
[DOM_PK_CONTROL_RIGHT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_RIGHT_CONTROL,
[DOM_PK_AUDIO_VOLUME_DOWN - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_VOLUME_DOWN,
[DOM_PK_AUDIO_VOLUME_UP - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_VOLUME_UP,
[DOM_PK_NUMPAD_DIVIDE - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_KP_DIVIDE,
[DOM_PK_ALT_RIGHT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_RIGHT_ALT,
[DOM_PK_NUM_LOCK - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_NUM_LOCK,
[DOM_PK_HOME - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_HOME,
[DOM_PK_ARROW_UP - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_UP,
[DOM_PK_PAGE_UP - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_PAGE_UP,
[DOM_PK_ARROW_LEFT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_LEFT,
[DOM_PK_ARROW_RIGHT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_RIGHT,
[DOM_PK_END - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_END,
[DOM_PK_ARROW_DOWN - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_DOWN,
[DOM_PK_PAGE_DOWN - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_PAGE_DOWN,
[DOM_PK_INSERT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_INSERT,
[DOM_PK_DELETE - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_DELETE,
[DOM_PK_META_LEFT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_LEFT_SUPER,
[DOM_PK_META_RIGHT - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_RIGHT_SUPER,
[DOM_PK_CONTEXT_MENU - DOM_PK_CODE_EXTENDED_OFFSET] = KEY_KB_MENU
};
static const char cursorLUT[11][12] = { static const char cursorLUT[11][12] = {
"default", // 0 MOUSE_CURSOR_DEFAULT "default", // 0 MOUSE_CURSOR_DEFAULT
"default", // 1 MOUSE_CURSOR_ARROW "default", // 1 MOUSE_CURSOR_ARROW
@ -110,6 +226,8 @@ static EM_BOOL EmscriptenPointerlockCallback(int eventType, const EmscriptenPoin
static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData);
static KeyboardKey ConvertKeyboardEventToKey(const EmscriptenKeyboardEvent *keyboardEvent);
// JS: Set the canvas id provided by the module configuration // JS: Set the canvas id provided by the module configuration
EM_JS(void, SetCanvasIdJs, (char *out, int outSize), { EM_JS(void, SetCanvasIdJs, (char *out, int outSize), {
var canvasId = "#" + Module.canvas.id; var canvasId = "#" + Module.canvas.id;
@ -633,7 +751,7 @@ void SetWindowSize(int width, int height)
// When resizing the canvas, several elements must be considered: // When resizing the canvas, several elements must be considered:
// - CSS canvas size: Web layout size, logical pixels // - CSS canvas size: Web layout size, logical pixels
// - Canvas contained framebuffer resolution // - Canvas contained framebuffer resolution
// * Browser monitor, device pixel ratio (HighDPI) // - Browser monitor, device pixel ratio (HighDPI)
double canvasCssWidth = 0.0; double canvasCssWidth = 0.0;
double canvasCssHeight = 0.0; double canvasCssHeight = 0.0;
@ -891,7 +1009,7 @@ void ShowCursor(void)
} }
} }
// Hides mouse cursor // Hide mouse cursor
void HideCursor(void) void HideCursor(void)
{ {
if (!CORE.Input.Mouse.cursorHidden) if (!CORE.Input.Mouse.cursorHidden)
@ -902,7 +1020,7 @@ void HideCursor(void)
} }
} }
// Enables cursor (unlock cursor) // Enable cursor (unlock cursor)
void EnableCursor(void) void EnableCursor(void)
{ {
emscripten_exit_pointerlock(); emscripten_exit_pointerlock();
@ -913,7 +1031,7 @@ void EnableCursor(void)
// NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback() // NOTE: CORE.Input.Mouse.cursorLocked handled by EmscriptenPointerlockCallback()
} }
// Disables cursor (lock cursor) // Disable cursor (lock cursor)
void DisableCursor(void) void DisableCursor(void)
{ {
emscripten_request_pointerlock(platform.canvasId, 1); emscripten_request_pointerlock(platform.canvasId, 1);
@ -962,19 +1080,28 @@ void SwapScreenBuffer(void)
// Get elapsed time measure in seconds since InitTimer() // Get elapsed time measure in seconds since InitTimer()
double GetTime(void) double GetTime(void)
{ {
double time = emscripten_get_now()*1000.0; double time = emscripten_get_now()/1000.0;
return time; return time;
} }
// Open URL with default system browser (if available) // Open URL with default system browser (if available)
// NOTE: This function is only safe to use if the provided URL is safe // WARNING: This function is only safe to use if you control the URL given,
// A user could craft a malicious string performing another action // a user could craft a malicious string to perform and undesired action
// Avoid calling this function with user input non-validated strings // NOTE: Some safety checks have been added to mitigate security issues
void OpenURL(const char *url) void OpenURL(const char *url)
{ {
// Security check to (partially) avoid malicious code on target platform // Security check to (partially) avoid malicious code
if (strchr(url, '\'') != NULL) TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'] character"); if ((strchr(url, '\'') != NULL) || (strchr(url, '\"') != NULL))
{
// Filter characters: ' and "
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL could be potentially malicious, avoid [\'\"] characters");
}
else if ((strncmp(url, "http://", 7) != 0) && (strncmp(url, "https://", 8) != 0))
{
// Only allow URL starting with "http://" or "https://" protocols
TRACELOG(LOG_WARNING, "SYSTEM: Provided URL must start with 'http://' or 'https://' protocols");
}
else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url)); else emscripten_run_script(TextFormat("window.open('%s', '_blank')", url));
} }
@ -1382,7 +1509,11 @@ static EM_BOOL EmscriptenFocusCallback(int eventType, const EmscriptenFocusEvent
switch (eventType) switch (eventType)
{ {
case EMSCRIPTEN_EVENT_BLUR: FLAG_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); break; case EMSCRIPTEN_EVENT_BLUR:
{
FLAG_SET(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED);
memset(CORE.Input.Keyboard.currentKeyState, 0, sizeof(CORE.Input.Keyboard.currentKeyState));
} break;
case EMSCRIPTEN_EVENT_FOCUS: FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); break; case EMSCRIPTEN_EVENT_FOCUS: FLAG_CLEAR(CORE.Window.flags, FLAG_WINDOW_UNFOCUSED); break;
default: consumed = 0; break; default: consumed = 0; break;
} }
@ -1439,58 +1570,81 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++) for (unsigned int i = 0; i < CORE.Window.dropFileCount; i++)
{ {
CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char)); CORE.Window.dropFilepaths[i] = (char *)RL_CALLOC(MAX_FILEPATH_LENGTH, sizeof(char));
strncpy(CORE.Window.dropFilepaths[i], paths[i], MAX_FILEPATH_LENGTH - 1); snprintf(CORE.Window.dropFilepaths[i], MAX_FILEPATH_LENGTH, "%s", paths[i]);
} }
} }
} }
*/ */
// Emscripten keyboard event to raylib key mapping
static KeyboardKey ConvertKeyboardEventToKey(const EmscriptenKeyboardEvent *keyboardEvent)
{
DOM_PK_CODE_TYPE code = emscripten_compute_dom_pk_code(keyboardEvent->code);
KeyboardKey key = KEY_NULL;
if ((code > DOM_PK_UNKNOWN) && (code < DOM_PK_CODE_MAPPED_NUM)) key = mapDomCodeToKey[code];
else if ((code >= DOM_PK_CODE_EXTENDED_OFFSET) && (code < (DOM_PK_CODE_EXTENDED_OFFSET + DOM_PK_CODE_MAPPED_NUM)))
{
key = mapDomCodeToKeyExtended[code - DOM_PK_CODE_EXTENDED_OFFSET];
}
return key;
}
// Emscripten: Called on key events // Emscripten: Called on key events
// TODO: keyCodes should be mapped to raylib/GLFW3 Key values
static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyboardEvent, void *userData) static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyboardEvent, void *userData)
{ {
KeyboardKey key = ConvertKeyboardEventToKey(keyboardEvent);
EM_BOOL preventDefault = 1;
switch (eventType) switch (eventType)
{ {
case EMSCRIPTEN_EVENT_KEYPRESS:
{
if (keyboardEvent->repeat) CORE.Input.Keyboard.keyRepeatInFrame[keyboardEvent->keyCode] = 1;
} break;
case EMSCRIPTEN_EVENT_KEYDOWN: case EMSCRIPTEN_EVENT_KEYDOWN:
{ {
CORE.Input.Keyboard.currentKeyState[keyboardEvent->keyCode] = 1; if (key != KEY_NULL)
{
// Check if there is space available in the key queue
if ((!keyboardEvent->repeat) && (CORE.Input.Keyboard.currentKeyState[key] == 0) &&
(CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE))
{
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
CORE.Input.Keyboard.keyPressedQueueCount++;
}
CORE.Input.Keyboard.currentKeyState[key] = 1;
if (keyboardEvent->repeat) CORE.Input.Keyboard.keyRepeatInFrame[key] = 1;
// Check the exit key to set close window
if ((key == CORE.Input.Keyboard.exitKey) && !keyboardEvent->repeat) CORE.Window.shouldClose = true;
}
// Allow printable keydown events so the browser can emit the keypress event used to collect characters
preventDefault = ((key == KEY_BACKSPACE) || (key == KEY_TAB) ||
(key == KEY_INSERT) || (key == KEY_DELETE) ||
(key == KEY_HOME) || (key == KEY_END) ||
(key == KEY_PAGE_UP) || (key == KEY_PAGE_DOWN) ||
(key == KEY_LEFT) || (key == KEY_RIGHT) ||
(key == KEY_UP) || (key == KEY_DOWN) ||
((key >= KEY_F1) && (key <= KEY_F12)) || keyboardEvent->ctrlKey);
} break; } break;
case EMSCRIPTEN_EVENT_KEYUP: case EMSCRIPTEN_EVENT_KEYUP:
{ {
CORE.Input.Keyboard.currentKeyState[keyboardEvent->keyCode] = 0; if (key != KEY_NULL) CORE.Input.Keyboard.currentKeyState[key] = 0;
} break;
case EMSCRIPTEN_EVENT_KEYPRESS:
{
// Check if there is space available in the queue for characters to be added
if ((keyboardEvent->charCode > 0) && (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE))
{
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = keyboardEvent->charCode;
CORE.Input.Keyboard.charPressedQueueCount++;
}
} break; } break;
default: break; default: break;
} }
// TODO: Add char codes return preventDefault;
//unsigned int charCode
// Check if there is space available in the queue for characters to be added
/*
if (CORE.Input.Keyboard.charPressedQueueCount < MAX_CHAR_PRESSED_QUEUE)
{
// Add character to the queue
CORE.Input.Keyboard.charPressedQueue[CORE.Input.Keyboard.charPressedQueueCount] = keyboardEvent->charCode;
CORE.Input.Keyboard.charPressedQueueCount++;
}
*/
/*
// Check if there is space available in the key queue
if ((CORE.Input.Keyboard.keyPressedQueueCount < MAX_KEY_PRESSED_QUEUE) && (eventType == EMSCRIPTEN_EVENT_KEYPRESS))
{
// Add character to the queue
CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keyboardEvent->keyCode;
CORE.Input.Keyboard.keyPressedQueueCount++;
}
// Check the exit key to set close window
//if ((keyboardEvent->keyCode == CORE.Input.Keyboard.exitKey) && (eventType == EMSCRIPTEN_EVENT_KEYPRESS)) CORE.Window.shouldClose = true;
*/
return 1; // The event was consumed by the callback handler
} }
// Emscripten: Called on mouse input events // Emscripten: Called on mouse input events
@ -1498,8 +1652,16 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
{ {
switch (eventType) switch (eventType)
{ {
case EMSCRIPTEN_EVENT_MOUSEENTER: CORE.Input.Mouse.cursorOnScreen = true; break; case EMSCRIPTEN_EVENT_MOUSEENTER: {
case EMSCRIPTEN_EVENT_MOUSELEAVE: CORE.Input.Mouse.cursorOnScreen = false; break; // NOTE: Mouse position updated by EmscriptenMouseMoveCallback(),
// EmscriptenPointerlockCallback(), and EmscriptenTouchCallback()
CORE.Input.Mouse.cursorOnScreen = true;
} break;
case EMSCRIPTEN_EVENT_MOUSELEAVE:
{
CORE.Input.Mouse.cursorOnScreen = false;
CORE.Input.Mouse.currentPosition = (Vector2){ 0 };
} break;
case EMSCRIPTEN_EVENT_MOUSEDOWN: case EMSCRIPTEN_EVENT_MOUSEDOWN:
{ {
// NOTE: Emscripten and raylib buttons indices are not aligned // NOTE: Emscripten and raylib buttons indices are not aligned
@ -1546,7 +1708,8 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
if (GetMouseX() != 0 || GetMouseY() != 0) ProcessGestureEvent(gestureEvent); if (GetMouseX() != 0 || GetMouseY() != 0) ProcessGestureEvent(gestureEvent);
#endif #endif
return 1; // The event was consumed by the callback handler // Don't prevent default to allow focusing on canvas
return 0;
} }
// Emscripten: Called on mouse move events // Emscripten: Called on mouse move events
@ -1560,32 +1723,18 @@ static EM_BOOL EmscriptenMouseMoveCallback(int eventType, const EmscriptenMouseE
else else
{ {
// Get mouse position in canvas CSS pixels // Get mouse position in canvas CSS pixels
float mouseCssX = (float)mouseEvent->canvasX; float mouseCssX = (float)mouseEvent->targetX;
float mouseCssY = (float)mouseEvent->canvasY; float mouseCssY = (float)mouseEvent->targetY;
// Get canvas sizes // Get canvas sizes
double cssWidth = 0.0; double cssWidth = 0.0;
double cssHeight = 0.0; double cssHeight = 0.0;
emscripten_get_element_css_size(platform.canvasId, &cssWidth, &cssHeight); emscripten_get_element_css_size(platform.canvasId, &cssWidth, &cssHeight);
int fbWidth = 0; float normalizedX = mouseCssX/(float)cssWidth;
int fbHeight = 0; float normalizedY = mouseCssY/(float)cssHeight;
emscripten_get_canvas_element_size(platform.canvasId, &fbWidth, &fbHeight); CORE.Input.Mouse.currentPosition.x = normalizedX*(float)CORE.Window.screen.width;
CORE.Input.Mouse.currentPosition.y = normalizedY*(float)CORE.Window.screen.height;
// Convert CSS to framebuffer coordinates
float scaleX = (float)fbWidth/(float)cssWidth;
float scaleY = (float)fbHeight/(float)cssHeight;
int mouseX = (int)(mouseCssX*scaleX);
int mouseY = (int)(mouseCssY*scaleY);
CORE.Input.Mouse.currentPosition.x = mouseX;//(float)mouseEvent->canvasX;
CORE.Input.Mouse.currentPosition.y = mouseY;//(float)mouseEvent->canvasY;
// Shorter alternative:
//double dpr = emscripten_get_device_pixel_ratio();
//int mouseX = (int)(e->canvasX*dpr);
//int mouseY = (int)(e->canvasY*dpr);
CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition; CORE.Input.Touch.position[0] = CORE.Input.Mouse.currentPosition;
} }
@ -1622,7 +1771,7 @@ static EM_BOOL EmscriptenMouseWheelCallback(int eventType, const EmscriptenWheel
if (eventType == EMSCRIPTEN_EVENT_WHEEL) if (eventType == EMSCRIPTEN_EVENT_WHEEL)
{ {
CORE.Input.Mouse.currentWheelMove.x = (float)wheelEvent->deltaX; CORE.Input.Mouse.currentWheelMove.x = (float)wheelEvent->deltaX;
CORE.Input.Mouse.currentWheelMove.y = (float)wheelEvent->deltaY; CORE.Input.Mouse.currentWheelMove.y = -(float)wheelEvent->deltaY;
} }
return 1; // The event was consumed by the callback handler return 1; // The event was consumed by the callback handler

View file

@ -344,7 +344,7 @@ typedef enum {
// Audio buffer struct // Audio buffer struct
struct rAudioBuffer { struct rAudioBuffer {
ma_data_converter converter; // Audio data converter ma_data_converter converter; // Audio data converter
unsigned char* converterResidual; // Cached residual input frames for use by the converter unsigned char *converterResidual; // Cached residual input frames for use by the converter
unsigned int converterResidualCount; // The number of valid frames sitting in converterResidual unsigned int converterResidualCount; // The number of valid frames sitting in converterResidual
AudioCallback callback; // Audio buffer callback for buffer filling on audio threads AudioCallback callback; // Audio buffer callback for buffer filling on audio threads
@ -378,7 +378,7 @@ struct rAudioProcessor {
rAudioProcessor *prev; // Previous audio processor on the list rAudioProcessor *prev; // Previous audio processor on the list
}; };
#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision #define AudioBuffer rAudioBuffer // WARNING: Renamed to avoid symbol collision with CoreAudio (macOS) AudioBuffer type
// Audio data context // Audio data context
typedef struct AudioData { typedef struct AudioData {
@ -434,6 +434,7 @@ static const char *GetFileName(const char *filePath); // Get point
static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) static const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) static unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
static void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write) static bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write)
static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated static bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated
#endif #endif
@ -532,8 +533,9 @@ void CloseAudioDevice(void)
{ {
if (AUDIO.System.isReady) if (AUDIO.System.isReady)
{ {
ma_mutex_uninit(&AUDIO.System.lock); // Stop the device first (joins the callback thread) before destroying the mutex it locks
ma_device_uninit(&AUDIO.System.device); ma_device_uninit(&AUDIO.System.device);
ma_mutex_uninit(&AUDIO.System.lock);
ma_context_uninit(&AUDIO.System.context); ma_context_uninit(&AUDIO.System.context);
AUDIO.System.isReady = false; AUDIO.System.isReady = false;
@ -821,7 +823,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
wave.sampleRate = wav.sampleRate; wave.sampleRate = wav.sampleRate;
wave.sampleSize = 16; wave.sampleSize = 16;
wave.channels = wav.channels; wave.channels = wav.channels;
wave.data = (short *)RL_MALLOC((size_t)wave.frameCount*wave.channels*sizeof(short)); wave.data = (short *)RL_CALLOC((size_t)wave.frameCount*wave.channels, sizeof(short));
// NOTE: Forcing conversion to 16bit sample size on reading // NOTE: Forcing conversion to 16bit sample size on reading
drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data); drwav_read_pcm_frames_s16(&wav, wave.frameCount, (drwav_int16 *)wave.data);
@ -844,7 +846,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short) wave.sampleSize = 16; // By default, ogg data is 16 bit per sample (short)
wave.channels = info.channels; wave.channels = info.channels;
wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames! wave.frameCount = (unsigned int)stb_vorbis_stream_length_in_samples(oggData); // NOTE: It returns frames!
wave.data = (short *)RL_MALLOC(wave.frameCount*wave.channels*sizeof(short)); wave.data = (short *)RL_CALLOC(wave.frameCount*wave.channels, sizeof(short));
// NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!) // NOTE: Get the number of samples to process (be careful! asking for number of shorts, not bytes!)
stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels); stb_vorbis_get_samples_short_interleaved(oggData, info.channels, (short *)wave.data, wave.frameCount*wave.channels);
@ -857,7 +859,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0)) else if ((strcmp(fileType, ".mp3") == 0) || (strcmp(fileType, ".MP3") == 0))
{ {
drmp3_config config = { 0 }; drmp3_config config = { 0 };
unsigned long long int totalFrameCount = 0; unsigned long long totalFrameCount = 0;
// NOTE: Forcing conversion to 32bit float sample size on reading // NOTE: Forcing conversion to 32bit float sample size on reading
wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL); wave.data = drmp3_open_memory_and_read_pcm_frames_f32(fileData, dataSize, &config, &totalFrameCount, NULL);
@ -867,7 +869,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
{ {
wave.channels = config.channels; wave.channels = config.channels;
wave.sampleRate = config.sampleRate; wave.sampleRate = config.sampleRate;
wave.frameCount = (int)totalFrameCount; wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
} }
else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data"); else TRACELOG(LOG_WARNING, "WAVE: Failed to load MP3 data");
@ -895,13 +897,13 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
#if SUPPORT_FILEFORMAT_FLAC #if SUPPORT_FILEFORMAT_FLAC
else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0)) else if ((strcmp(fileType, ".flac") == 0) || (strcmp(fileType, ".FLAC") == 0))
{ {
unsigned long long int totalFrameCount = 0; unsigned long long totalFrameCount = 0;
// NOTE: Forcing conversion to 16bit sample size on reading // NOTE: Forcing conversion to 16bit sample size on reading
wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL); wave.data = drflac_open_memory_and_read_pcm_frames_s16(fileData, dataSize, &wave.channels, &wave.sampleRate, &totalFrameCount, NULL);
wave.sampleSize = 16; wave.sampleSize = 16;
if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; if (wave.data != NULL) wave.frameCount = (unsigned int)totalFrameCount; // WARNING: Potential loss of data
else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data"); else TRACELOG(LOG_WARNING, "WAVE: Failed to load FLAC data");
} }
#endif #endif
@ -912,7 +914,7 @@ Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int
return wave; return wave;
} }
// Checks if wave data is valid (data loaded and parameters) // Check if wave data is valid (data loaded and parameters)
bool IsWaveValid(Wave wave) bool IsWaveValid(Wave wave)
{ {
bool result = false; bool result = false;
@ -980,7 +982,7 @@ Sound LoadSoundFromWave(Wave wave)
return sound; return sound;
} }
// Clone sound from existing sound data, clone does not own wave data // Load sound alias, clone sound from existing sound data, clone does not own wave data
// NOTE: Wave data must be unallocated manually and will be shared across all clones // NOTE: Wave data must be unallocated manually and will be shared across all clones
Sound LoadSoundAlias(Sound source) Sound LoadSoundAlias(Sound source)
{ {
@ -1012,7 +1014,7 @@ Sound LoadSoundAlias(Sound source)
return sound; return sound;
} }
// Checks if a sound is valid (data loaded and buffers initialized) // Check if sound is valid (data loaded and buffers initialized)
bool IsSoundValid(Sound sound) bool IsSoundValid(Sound sound)
{ {
bool result = false; bool result = false;
@ -1047,6 +1049,7 @@ void UnloadSoundAlias(Sound alias)
{ {
UntrackAudioBuffer(alias.stream.buffer); UntrackAudioBuffer(alias.stream.buffer);
ma_data_converter_uninit(&alias.stream.buffer->converter, NULL); ma_data_converter_uninit(&alias.stream.buffer->converter, NULL);
RL_FREE(alias.stream.buffer->converterResidual);
RL_FREE(alias.stream.buffer); RL_FREE(alias.stream.buffer);
} }
} }
@ -1152,7 +1155,7 @@ bool ExportWaveAsCode(Wave wave, const char *fileName)
// Get file name from path and convert variable name to uppercase // Get file name from path and convert variable name to uppercase
char varFileName[256] = { 0 }; char varFileName[256] = { 0 };
strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName)); // NOTE: Using function provided by [rcore] module
for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; } for (int i = 0; varFileName[i] != '\0'; i++) if (varFileName[i] >= 'a' && varFileName[i] <= 'z') { varFileName[i] = varFileName[i] - 32; }
// Add wave information // Add wave information
@ -1213,7 +1216,7 @@ void StopSound(Sound sound)
StopAudioBuffer(sound.stream.buffer); StopAudioBuffer(sound.stream.buffer);
} }
// Check if a sound is playing // Check if sound is playing
bool IsSoundPlaying(Sound sound) bool IsSoundPlaying(Sound sound)
{ {
bool result = false; bool result = false;
@ -1256,7 +1259,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels)
return; return;
} }
void *data = RL_MALLOC(frameCount*channels*(sampleSize/8)); void *data = RL_CALLOC(frameCount*channels*(sampleSize/8), 1);
frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate); frameCount = (ma_uint32)ma_convert_frames(data, frameCount, formatOut, channels, sampleRate, wave->data, frameCountIn, formatIn, wave->channels, wave->sampleRate);
if (frameCount == 0) if (frameCount == 0)
@ -1749,7 +1752,7 @@ Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data,
return music; return music;
} }
// Checks if a music stream is valid (context and buffers initialized) // Check if music stream is valid (context and buffers initialized)
bool IsMusicValid(Music music) bool IsMusicValid(Music music)
{ {
return ((music.ctxData != NULL) && // Validate context loaded return ((music.ctxData != NULL) && // Validate context loaded
@ -1770,7 +1773,7 @@ void UnloadMusicStream(Music music)
{ {
if (false) { } if (false) { }
#if SUPPORT_FILEFORMAT_WAV #if SUPPORT_FILEFORMAT_WAV
else if (music.ctxType == MUSIC_AUDIO_WAV) drwav_uninit((drwav *)music.ctxData); else if (music.ctxType == MUSIC_AUDIO_WAV) { drwav_uninit((drwav *)music.ctxData); RL_FREE(music.ctxData); }
#endif #endif
#if SUPPORT_FILEFORMAT_OGG #if SUPPORT_FILEFORMAT_OGG
else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData); else if (music.ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close((stb_vorbis *)music.ctxData);
@ -1782,7 +1785,7 @@ void UnloadMusicStream(Music music)
else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData); else if (music.ctxType == MUSIC_AUDIO_QOA) qoaplay_close((qoaplay_desc *)music.ctxData);
#endif #endif
#if SUPPORT_FILEFORMAT_FLAC #if SUPPORT_FILEFORMAT_FLAC
else if (music.ctxType == MUSIC_AUDIO_FLAC) { drflac_close((drflac *)music.ctxData); drflac_free((drflac *)music.ctxData, NULL); } else if (music.ctxType == MUSIC_AUDIO_FLAC) drflac_close((drflac *)music.ctxData);
#endif #endif
#if SUPPORT_FILEFORMAT_XM #if SUPPORT_FILEFORMAT_XM
else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData); else if (music.ctxType == MUSIC_MODULE_XM) jar_xm_free_context((jar_xm_context_t *)music.ctxData);
@ -2066,7 +2069,7 @@ void SetMusicPitch(Music music, float pitch)
SetAudioBufferPitch(music.stream.buffer, pitch); SetAudioBufferPitch(music.stream.buffer, pitch);
} }
// Set pan for a music // Set pan for music
void SetMusicPan(Music music, float pan) void SetMusicPan(Music music, float pan)
{ {
SetAudioBufferPan(music.stream.buffer, pan); SetAudioBufferPan(music.stream.buffer, pan);
@ -2154,7 +2157,7 @@ AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
return stream; return stream;
} }
// Checks if an audio stream is valid (buffers initialized) // Check if an audio stream is valid (buffers initialized)
bool IsAudioStreamValid(AudioStream stream) bool IsAudioStreamValid(AudioStream stream)
{ {
return ((stream.buffer != NULL) && // Validate stream buffer return ((stream.buffer != NULL) && // Validate stream buffer
@ -2825,7 +2828,7 @@ static const char *GetFileNameWithoutExt(const char *filePath)
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 }; static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH] = { 0 };
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH); memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
if (filePath != NULL) strncpy(fileName, GetFileName(filePath), MAX_FILENAMEWITHOUTEXT_LENGTH - 1); // Get filename with extension if (filePath != NULL) snprintf(fileName, MAX_FILENAMEWITHOUTEXT_LENGTH, "%s", GetFileName(filePath));
int fileNameLength = (int)strlen(fileName); // Get size in bytes int fileNameLength = (int)strlen(fileName); // Get size in bytes
@ -2882,6 +2885,12 @@ static unsigned char *LoadFileData(const char *fileName, int *dataSize)
return data; return data;
} }
// Unload file data allocated by LoadFileData()
static void UnloadFileData(unsigned char *data)
{
RL_FREE(data);
}
// Save data to file from buffer // Save data to file from buffer
static bool SaveFileData(const char *fileName, void *data, int dataSize) static bool SaveFileData(const char *fileName, void *data, int dataSize)
{ {

View file

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raylib v6.0 - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com) * raylib v6.1-dev - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
* *
* FEATURES: * FEATURES:
* - NO external dependencies, all required libraries included with raylib * - NO external dependencies, all required libraries included with raylib
@ -87,9 +87,9 @@
#include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback #include <stdarg.h> // Required for: va_list - Only used by TraceLogCallback
#define RAYLIB_VERSION_MAJOR 6 #define RAYLIB_VERSION_MAJOR 6
#define RAYLIB_VERSION_MINOR 0 #define RAYLIB_VERSION_MINOR 1
#define RAYLIB_VERSION_PATCH 0 #define RAYLIB_VERSION_PATCH 0
#define RAYLIB_VERSION "6.0" #define RAYLIB_VERSION "6.1-dev"
// Function specifiers in case library is build/used as a shared library // Function specifiers in case library is build/used as a shared library
// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll // NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll
@ -203,12 +203,14 @@
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Boolean type // Boolean type
#if !defined(__cplusplus)
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) #elif !defined(bool)
typedef enum bool { false = 0, true = !false } bool; typedef enum bool { false = 0, true = !false } bool;
#define RL_BOOL_TYPE #define RL_BOOL_TYPE
#endif #endif
#endif
// Vector2, 2 components // Vector2, 2 components
typedef struct Vector2 { typedef struct Vector2 {
@ -407,7 +409,7 @@ typedef struct BoneInfo {
// Skeleton, animation bones hierarchy // Skeleton, animation bones hierarchy
typedef struct ModelSkeleton { typedef struct ModelSkeleton {
int boneCount; // Number of bones unsigned int boneCount; // Number of bones
BoneInfo *bones; // Bones information (skeleton) BoneInfo *bones; // Bones information (skeleton)
ModelAnimPose bindPose; // Bones base transformation (Transform[]) ModelAnimPose bindPose; // Bones base transformation (Transform[])
} ModelSkeleton; } ModelSkeleton;
@ -434,7 +436,7 @@ typedef struct Model {
typedef struct ModelAnimation { typedef struct ModelAnimation {
char name[32]; // Animation name char name[32]; // Animation name
int boneCount; // Number of bones (per pose) unsigned int boneCount; // Number of bones (per pose)
int keyframeCount; // Number of animation key frames int keyframeCount; // Number of animation key frames
ModelAnimPose *keyframePoses; // Animation sequence keyframe poses [keyframe][pose] ModelAnimPose *keyframePoses; // Animation sequence keyframe poses [keyframe][pose]
} ModelAnimation; } ModelAnimation;
@ -965,7 +967,7 @@ typedef enum {
// WARNING: These callbacks are intended for advanced users // WARNING: These callbacks are intended for advanced users
typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages typedef void (*TraceLogCallback)(int logLevel, const char *text, va_list args); // Logging: Redirect trace log messages
typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data typedef unsigned char *(*LoadFileDataCallback)(const char *fileName, int *dataSize); // FileIO: Load binary data
typedef bool (*SaveFileDataCallback)(const char *fileName, void *data, int dataSize); // FileIO: Save binary data typedef bool (*SaveFileDataCallback)(const char *fileName, const void *data, int dataSize); // FileIO: Save binary data
typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data typedef char *(*LoadFileTextCallback)(const char *fileName); // FileIO: Load text data
typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data typedef bool (*SaveFileTextCallback)(const char *fileName, const char *text); // FileIO: Save text data
@ -1034,23 +1036,23 @@ RLAPI void EnableEventWaiting(void); // Enable wait
RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling RLAPI void DisableEventWaiting(void); // Disable waiting for events on EndDrawing(), automatic events polling
// Cursor-related functions // Cursor-related functions
RLAPI void ShowCursor(void); // Shows cursor RLAPI void ShowCursor(void); // Show cursor
RLAPI void HideCursor(void); // Hides cursor RLAPI void HideCursor(void); // Hide cursor
RLAPI bool IsCursorHidden(void); // Check if cursor is not visible RLAPI bool IsCursorHidden(void); // Check if cursor is not visible
RLAPI void EnableCursor(void); // Enables cursor (unlock cursor) RLAPI void EnableCursor(void); // Enable cursor (unlock cursor)
RLAPI void DisableCursor(void); // Disables cursor (lock cursor) RLAPI void DisableCursor(void); // Disable cursor (lock cursor)
RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen RLAPI bool IsCursorOnScreen(void); // Check if cursor is on the screen
// Drawing-related functions // Drawing-related functions
RLAPI void ClearBackground(Color color); // Set background color (framebuffer clear color) RLAPI void ClearBackground(Color color); // Clear background (framebuffer) to color
RLAPI void BeginDrawing(void); // Setup canvas (framebuffer) to start drawing RLAPI void BeginDrawing(void); // Begin canvas (framebuffer) drawing
RLAPI void EndDrawing(void); // End canvas drawing and swap buffers (double buffering) RLAPI void EndDrawing(void); // End canvas (framebuffer) drawing and swap buffers (double buffering)
RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D) RLAPI void BeginMode2D(Camera2D camera); // Begin 2D mode with custom camera (2D)
RLAPI void EndMode2D(void); // Ends 2D mode with custom camera RLAPI void EndMode2D(void); // End 2D mode with custom camera
RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D) RLAPI void BeginMode3D(Camera3D camera); // Begin 3D mode with custom camera (3D)
RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode RLAPI void EndMode3D(void); // End 3D mode and returns to default 2D orthographic mode
RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture RLAPI void BeginTextureMode(RenderTexture2D target); // Begin drawing to render texture
RLAPI void EndTextureMode(void); // Ends drawing to render texture RLAPI void EndTextureMode(void); // End drawing to render texture
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader) RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom) RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied, subtract, custom)
@ -1068,7 +1070,7 @@ RLAPI void UnloadVrStereoConfig(VrStereoConfig config); // Unload VR s
// NOTE: Shader functionality is not available on OpenGL 1.1 // NOTE: Shader functionality is not available on OpenGL 1.1
RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations RLAPI Shader LoadShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations RLAPI Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
RLAPI bool IsShaderValid(Shader shader); // Check if a shader is valid (loaded on GPU) RLAPI bool IsShaderValid(Shader shader); // Check if shader is valid (loaded on GPU)
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location RLAPI int GetShaderLocationAttrib(Shader shader, const char *attribName); // Get shader attribute location
RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value RLAPI void SetShaderValue(Shader shader, int locIndex, const void *value, int uniformType); // Set shader uniform value
@ -1078,13 +1080,12 @@ RLAPI void SetShaderValueTexture(Shader shader, int locIndex, Texture2D texture)
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
// Screen-space-related functions // Screen-space-related functions
#define GetMouseRay GetScreenToWorldRay // Compatibility hack for previous raylib versions
RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse) RLAPI Ray GetScreenToWorldRay(Vector2 position, Camera camera); // Get a ray trace from screen position (i.e mouse)
RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport RLAPI Ray GetScreenToWorldRayEx(Vector2 position, Camera camera, int width, int height); // Get a ray trace from screen position (i.e mouse) in a viewport
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get the screen space position for a 3d world space position RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Get screen space position for a 3d world space position
RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get size position for a 3d world space position RLAPI Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height); // Get sized screen space position for a 3d world space position
RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get the screen space position for a 2d camera world space position RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Get screen space position for a 2d camera world space position
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get the world space position for a 2d camera screen space position RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Get world space position for a 2d camera screen space position
RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix) RLAPI Matrix GetCameraMatrix(Camera camera); // Get camera transform matrix (view matrix)
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Get camera 2d transform matrix
@ -1110,7 +1111,7 @@ RLAPI void UnloadRandomSequence(int *sequence); // Unload random values
// Misc. functions // Misc. functions
RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format) RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (filename extension defines format)
RLAPI void SetConfigFlags(unsigned int flags); // Setup init configuration flags (view FLAGS) RLAPI void SetConfigFlags(unsigned int flags); // Set up init configuration flags (view FLAGS)
RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available) RLAPI void OpenURL(const char *url); // Open URL with default system browser (if available)
// Logging system // Logging system
@ -1126,7 +1127,7 @@ RLAPI void MemFree(void *ptr); // Internal memo
// File system management functions // File system management functions
RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read) RLAPI unsigned char *LoadFileData(const char *fileName, int *dataSize); // Load file data as byte array (read)
RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData()
RLAPI bool SaveFileData(const char *fileName, void *data, int dataSize); // Save data to file from byte array (write), returns true on success RLAPI bool SaveFileData(const char *fileName, const void *data, int dataSize); // Save data to file from byte array (write), returns true on success
RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success RLAPI bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileName); // Export data to code (.h), returns true on success
RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string
RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText()
@ -1139,32 +1140,34 @@ RLAPI void SetSaveFileDataCallback(SaveFileDataCallback callback); // Set custo
RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader RLAPI void SetLoadFileTextCallback(LoadFileTextCallback callback); // Set custom file text data loader
RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver RLAPI void SetSaveFileTextCallback(SaveFileTextCallback callback); // Set custom file text data saver
RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists) RLAPI int FileRename(const char *fileName, const char *fileRename); // Rename file (if exists), returns 0 on success
RLAPI int FileRemove(const char *fileName); // Remove file (if exists) RLAPI int FileRemove(const char *fileName); // Remove file (if exists), returns 0 on success
RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist RLAPI int FileCopy(const char *srcPath, const char *dstPath); // Copy file from one path to another, dstPath created if it doesn't exist, returns 0 on success
RLAPI int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist RLAPI int FileMove(const char *srcPath, const char *dstPath); // Move file from one directory to another, dstPath created if it doesn't exist, returns 0 on success
RLAPI int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file RLAPI int FileTextReplace(const char *fileName, const char *search, const char *replacement); // Replace text in an existing file, returns 0 on success
RLAPI int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file RLAPI int FileTextFindIndex(const char *fileName, const char *search); // Find text in existing file, returns -1 if index not found or index otherwise
RLAPI bool FileExists(const char *fileName); // Check if file exists RLAPI bool FileExists(const char *fileName); // Check if file exists
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists RLAPI bool DirectoryExists(const char *dirPath); // Check if directory path exists
RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (recommended include point: .png, .wav) RLAPI bool IsFileExtension(const char *fileName, const char *ext); // Check file extension (recommended include point: .png, .wav)
RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h) RLAPI int GetFileLength(const char *fileName); // Get file length in bytes (NOTE: GetFileSize() conflicts with windows.h)
RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time) RLAPI long GetFileModTime(const char *fileName); // Get file modification time (last write time)
RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png') RLAPI const char *GetFileExtension(const char *fileName); // Get pointer to extension for a filename string (includes dot: '.png')
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string) RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string) RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a provided fileName with path (uses static string)
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string) RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a provided path (uses static string)
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string) RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string) RLAPI const char *GetApplicationDirectory(void); // Get the directory of the running application (uses static string)
RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success RLAPI int MakeDirectory(const char *dirPath); // Create directories (including full path requested), returns 0 on success
RLAPI bool ChangeDirectory(const char *dirPath); // Change working directory, return true on success RLAPI int ChangeDirectory(const char *dirPath); // Change working directory, returns 0 on success
RLAPI bool IsPathFile(const char *path); // Check if a given path is a file or a directory RLAPI bool IsPathFile(const char *path); // Check if provided path points to a file
RLAPI bool IsPathDirectory(const char *path); // Check if provided path points to a directory
RLAPI bool IsPathAbsolute(const char *path); // Check if provided path is an absolute path
RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS RLAPI bool IsFileNameValid(const char *fileName); // Check if fileName is valid for the platform/OS
RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan RLAPI FilePathList LoadDirectoryFiles(const char *dirPath); // Load directory filepaths, files and directories, no subdirs scan
RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: "*.*", "FILES*", "DIRS*" RLAPI FilePathList LoadDirectoryFilesEx(const char *basePath, const char *filter, bool scanSubdirs); // Load directory filepaths with extension filtering and subdir scan; some filters available: '*.*','FILES*','DIRS*'
RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths RLAPI void UnloadDirectoryFiles(FilePathList files); // Unload filepaths
RLAPI bool IsFileDropped(void); // Check if a file has been dropped into window RLAPI bool IsFileDropped(void); // Check if file has been dropped into window
RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths RLAPI FilePathList LoadDroppedFiles(void); // Load dropped filepaths
RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths RLAPI void UnloadDroppedFiles(FilePathList files); // Unload dropped filepaths
RLAPI unsigned int GetDirectoryFileCount(const char *dirPath); // Get the file count in a directory RLAPI unsigned int GetDirectoryFileCount(const char *dirPath); // Get the file count in a directory
@ -1175,10 +1178,10 @@ RLAPI unsigned char *CompressData(const unsigned char *data, int dataSize, int *
RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree() RLAPI unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // Decompress data (DEFLATE algorithm), memory must be MemFree()
RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree() RLAPI char *EncodeDataBase64(const unsigned char *data, int dataSize, int *outputSize); // Encode data to Base64 string (includes NULL terminator), memory must be MemFree()
RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree() RLAPI unsigned char *DecodeDataBase64(const char *text, int *outputSize); // Decode Base64 string (expected NULL terminated), memory must be MemFree()
RLAPI unsigned int ComputeCRC32(unsigned char *data, int dataSize); // Compute CRC32 hash code RLAPI unsigned int ComputeCRC32(const unsigned char *data, int dataSize); // Compute CRC32 hash code
RLAPI unsigned int *ComputeMD5(unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes) RLAPI unsigned int *ComputeMD5(const unsigned char *data, int dataSize); // Compute MD5 hash code, returns static int[4] (16 bytes)
RLAPI unsigned int *ComputeSHA1(unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes) RLAPI unsigned int *ComputeSHA1(const unsigned char *data, int dataSize); // Compute SHA1 hash code, returns static int[5] (20 bytes)
RLAPI unsigned int *ComputeSHA256(unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes) RLAPI unsigned int *ComputeSHA256(const unsigned char *data, int dataSize); // Compute SHA256 hash code, returns static int[8] (32 bytes)
// Automation events functionality // Automation events functionality
RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS RLAPI AutomationEventList LoadAutomationEventList(const char *fileName); // Load automation events list from file, NULL for empty list, capacity = MAX_AUTOMATION_EVENTS
@ -1195,23 +1198,23 @@ RLAPI void PlayAutomationEvent(AutomationEvent event); // Play a reco
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Input-related functions: keyboard // Input-related functions: keyboard
RLAPI bool IsKeyPressed(int key); // Check if a key has been pressed once RLAPI bool IsKeyPressed(int key); // Check if key has been pressed once
RLAPI bool IsKeyPressedRepeat(int key); // Check if a key has been pressed again RLAPI bool IsKeyPressedRepeat(int key); // Check if key has been pressed again
RLAPI bool IsKeyDown(int key); // Check if a key is being pressed RLAPI bool IsKeyDown(int key); // Check if key is being pressed
RLAPI bool IsKeyReleased(int key); // Check if a key has been released once RLAPI bool IsKeyReleased(int key); // Check if key has been released once
RLAPI bool IsKeyUp(int key); // Check if a key is NOT being pressed RLAPI bool IsKeyUp(int key); // Check if key is NOT being pressed
RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty RLAPI int GetKeyPressed(void); // Get key pressed (keycode), call it multiple times for keys queued, returns 0 when the queue is empty
RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty RLAPI int GetCharPressed(void); // Get char pressed (unicode), call it multiple times for chars queued, returns 0 when the queue is empty
RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard) RLAPI const char *GetKeyName(int key); // Get name of a QWERTY key on the current keyboard layout (eg returns string 'q' for KEY_A on an AZERTY keyboard)
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC) RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
// Input-related functions: gamepads // Input-related functions: gamepads
RLAPI bool IsGamepadAvailable(int gamepad); // Check if a gamepad is available RLAPI bool IsGamepadAvailable(int gamepad); // Check if gamepad is available
RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id RLAPI const char *GetGamepadName(int gamepad); // Get gamepad internal name id
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if a gamepad button has been pressed once RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Check if gamepad button has been pressed once
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if a gamepad button is being pressed RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Check if gamepad button is being pressed
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if a gamepad button has been released once RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Check if gamepad button has been released once
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if a gamepad button is NOT being pressed RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Check if gamepad button is NOT being pressed
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad RLAPI int GetGamepadAxisCount(int gamepad); // Get axis count for a gamepad
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get movement value for a gamepad axis RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Get movement value for a gamepad axis
@ -1219,10 +1222,10 @@ RLAPI int SetGamepadMappings(const char *mappings); // Set internal ga
RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds) RLAPI void SetGamepadVibration(int gamepad, float leftMotor, float rightMotor, float duration); // Set gamepad vibration for both motors (duration in seconds)
// Input-related functions: mouse // Input-related functions: mouse
RLAPI bool IsMouseButtonPressed(int button); // Check if a mouse button has been pressed once RLAPI bool IsMouseButtonPressed(int button); // Check if mouse button has been pressed once
RLAPI bool IsMouseButtonDown(int button); // Check if a mouse button is being pressed RLAPI bool IsMouseButtonDown(int button); // Check if mouse button is being pressed
RLAPI bool IsMouseButtonReleased(int button); // Check if a mouse button has been released once RLAPI bool IsMouseButtonReleased(int button); // Check if mouse button has been released once
RLAPI bool IsMouseButtonUp(int button); // Check if a mouse button is NOT being pressed RLAPI bool IsMouseButtonUp(int button); // Check if mouse button is NOT being pressed
RLAPI int GetMouseX(void); // Get mouse position X RLAPI int GetMouseX(void); // Get mouse position X
RLAPI int GetMouseY(void); // Get mouse position Y RLAPI int GetMouseY(void); // Get mouse position Y
RLAPI Vector2 GetMousePosition(void); // Get mouse position XY RLAPI Vector2 GetMousePosition(void); // Get mouse position XY
@ -1238,14 +1241,14 @@ RLAPI void SetMouseCursor(int cursor); // Set mouse curso
RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size) RLAPI int GetTouchX(void); // Get touch position X for touch point 0 (relative to screen size)
RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size) RLAPI int GetTouchY(void); // Get touch position Y for touch point 0 (relative to screen size)
RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size) RLAPI Vector2 GetTouchPosition(int index); // Get touch position XY for a touch point index (relative to screen size)
RLAPI int GetTouchPointId(int index); // Get touch point identifier for given index RLAPI int GetTouchPointId(int index); // Get touch point identifier for provided index
RLAPI int GetTouchPointCount(void); // Get number of touch points RLAPI int GetTouchPointCount(void); // Get number of touch points
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Gestures and Touch Handling Functions (Module: rgestures) // Gestures and Touch Handling Functions (Module: rgestures)
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags RLAPI void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
RLAPI bool IsGestureDetected(unsigned int gesture); // Check if a gesture have been detected RLAPI bool IsGestureDetected(unsigned int gesture); // Check if gesture has been detected
RLAPI int GetGestureDetected(void); // Get latest detected gesture RLAPI int GetGestureDetected(void); // Get latest detected gesture
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in seconds
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
@ -1265,7 +1268,7 @@ RLAPI void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, f
// Set texture and rectangle to be used on shapes drawing // Set texture and rectangle to be used on shapes drawing
// NOTE: It can be useful when using basic shapes and one single font, // NOTE: It can be useful when using basic shapes and one single font,
// defining a font char white rectangle would allow drawing everything in a single draw call // defining a font char white rectangle would allow drawing everything in a single draw call
RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Set texture and rectangle to be used on shapes drawing RLAPI void SetShapesTexture(Texture2D texture, Rectangle rec); // Set texture and rectangle to be used on shapes drawing
RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing RLAPI Texture2D GetShapesTexture(void); // Get texture that is used for shapes drawing
RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing RLAPI Rectangle GetShapesTextureRectangle(void); // Get texture source rectangle that is used for shapes drawing
@ -1278,38 +1281,44 @@ RLAPI void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color
RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines) RLAPI void DrawLineStrip(const Vector2 *points, int pointCount, Color color); // Draw lines sequence (using gl lines)
RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation RLAPI void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color); // Draw line segment cubic-bezier in-out interpolation
RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line RLAPI void DrawLineDashed(Vector2 startPos, Vector2 endPos, int dashSize, int spaceSize, Color color); // Draw a dashed line
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle, counter-clockwise vertex order
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version) RLAPI void DrawTriangleGradient(Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors, counter-clockwise vertex/color order
RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline, counter-clockwise vertex order
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle RLAPI void DrawTriangleLinesEx(Vector2 v1, Vector2 v2, Vector2 v3, float thick, Color color); // Draw triangle outline with line thickness, counter-clockwise vertex order
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version)
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version)
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters
RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle RLAPI void DrawRectangleGradientV(int posX, int posY, int width, int height, Color top, Color bottom); // Draw a vertical-gradient-filled rectangle
RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle RLAPI void DrawRectangleGradientH(int posX, int posY, int width, int height, Color left, Color right); // Draw a horizontal-gradient-filled rectangle
RLAPI void DrawRectangleGradientEx(Rectangle rec, Color topLeft, Color bottomLeft, Color bottomRight, Color topRight); // Draw a gradient-filled rectangle with custom vertex colors RLAPI void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw a gradient-filled rectangle with custom vertex colors, counter-clockwise color order
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
RLAPI void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); // Draw rectangle outline with extended parameters RLAPI void DrawRectangleLinesEx(Rectangle rec, float thick, Color color); // Draw rectangle outline with line thickness
RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges RLAPI void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle with rounded edges
RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges RLAPI void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, Color color); // Draw rectangle lines with rounded edges
RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float lineThick, Color color); // Draw rectangle with rounded edges outline RLAPI void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, int segments, float thick, Color color); // Draw rectangle lines with rounded edges outline and line thickness
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon of n sides
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline (vertex in counter-clockwise order!)
RLAPI void DrawTriangleFan(const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points (first vertex is the center)
RLAPI void DrawTriangleStrip(const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color); // Draw a polygon outline of n sides with extended parameters RLAPI void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float thick, Color color); // Draw a polygon outline of n sides with line thickness
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
RLAPI void DrawCircleGradient(Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle
RLAPI void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw a piece of a circle
RLAPI void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color); // Draw circle sector outline
RLAPI void DrawCircleSectorLinesEx(Vector2 center, float radius, float startAngle, float endAngle, int segments, float thick, Color color); // Draw circle sector outline with thickness
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
RLAPI void DrawCircleLinesV(Vector2 center, float radius, Color color); // Draw circle outline (Vector version)
RLAPI void DrawCircleLinesEx(Vector2 center, float radius, float thick, Color color); // Draw circle outline with line thickness
RLAPI void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse
RLAPI void DrawEllipseV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse (Vector version)
RLAPI void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color); // Draw ellipse outline
RLAPI void DrawEllipseLinesV(Vector2 center, float radiusH, float radiusV, Color color); // Draw ellipse outline (Vector version)
RLAPI void DrawEllipseLinesEx(Vector2 center, float radiusH, float radiusV, float thick, Color color); // Draw ellipse outline with line thickness
RLAPI void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring
RLAPI void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color); // Draw ring outline
RLAPI void DrawRingLinesEx(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, float thick, Color color); // Draw ring outline with line thickness
// Splines drawing functions // Splines drawing functions
RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points RLAPI void DrawSplineLinear(const Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points
@ -1323,18 +1332,18 @@ RLAPI void DrawSplineSegmentCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vecto
RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point RLAPI void DrawSplineSegmentBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float thick, Color color); // Draw spline segment: Quadratic Bezier, 2 points, 1 control point
RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points RLAPI void DrawSplineSegmentBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float thick, Color color); // Draw spline segment: Cubic Bezier, 2 points, 2 control points
// Spline segment point evaluation functions, for a given t [0.0f .. 1.0f] // Spline segment point evaluation functions, for a provided t [0.0f .. 1.0f]
RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear RLAPI Vector2 GetSplinePointLinear(Vector2 startPos, Vector2 endPos, float t); // Get (evaluate) spline point: Linear
RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline RLAPI Vector2 GetSplinePointBasis(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: B-Spline
RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom RLAPI Vector2 GetSplinePointCatmullRom(Vector2 p1, Vector2 p2, Vector2 p3, Vector2 p4, float t); // Get (evaluate) spline point: Catmull-Rom
RLAPI Vector2 GetSplinePointBezierQuad(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier RLAPI Vector2 GetSplinePointBezierQuadratic(Vector2 p1, Vector2 c2, Vector2 p3, float t); // Get (evaluate) spline point: Quadratic Bezier
RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier RLAPI Vector2 GetSplinePointBezierCubic(Vector2 p1, Vector2 c2, Vector2 c3, Vector2 p4, float t); // Get (evaluate) spline point: Cubic Bezier
// Basic shapes collision detection functions // Basic shapes collision detection functions
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created betweeen two points [p1] and [p2] RLAPI bool CheckCollisionCircleLine(Vector2 center, float radius, Vector2 p1, Vector2 p2); // Check if circle collides with a line created between two points [p1] and [p2]
RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
@ -1355,7 +1364,7 @@ RLAPI Image LoadImageAnim(const char *fileName, int *frames);
RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer RLAPI Image LoadImageAnimFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int *frames); // Load image sequence from memory buffer
RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png' RLAPI Image LoadImageFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load image from memory buffer, fileType refers to extension: i.e. '.png'
RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data RLAPI Image LoadImageFromTexture(Texture2D texture); // Load image from GPU texture data
RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer and (screenshot) RLAPI Image LoadImageFromScreen(void); // Load image from screen buffer (screenshot)
RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters) RLAPI bool IsImageValid(Image image); // Check if an image is valid (data and parameters)
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success RLAPI bool ExportImage(Image image, const char *fileName); // Export image data to file, returns true on success
@ -1401,7 +1410,7 @@ RLAPI void ImageRotateCCW(Image *image);
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
RLAPI void ImageColorInvert(Image *image); // Modify image color: invert RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) RLAPI void ImageColorContrast(Image *image, int contrast); // Modify image color: contrast (-100 to 100)
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color RLAPI void ImageColorReplace(Image *image, Color color, Color replace); // Modify image color: replace color
RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit) RLAPI Color *LoadImageColors(Image image); // Load color data from image as a Color array (RGBA - 32bit)
@ -1413,28 +1422,38 @@ RLAPI Color GetImageColor(Image image, int x, int y);
// Image drawing functions // Image drawing functions
// NOTE: Image software-rendering functions (CPU) // NOTE: Image software-rendering functions (CPU)
RLAPI void ImageClearBackground(Image *dst, Color color); // Clear image background with given color RLAPI void ImageClearBackground(Image *dst, Color color); // Clear image background with provided color
RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); // Draw pixel within an image RLAPI void ImageDrawPixel(Image *dst, int posX, int posY, Color color); // Draw pixel within an image
RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version) RLAPI void ImageDrawPixelV(Image *dst, Vector2 position, Color color); // Draw pixel within an image (Vector version)
RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image RLAPI void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw line within an image
RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version) RLAPI void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color); // Draw line within an image (Vector version)
RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image RLAPI void ImageDrawLineEx(Image *dst, Vector2 start, Vector2 end, int thick, Color color); // Draw a line defining thickness within an image
RLAPI void ImageDrawLineStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a lines sequence within an image
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image
RLAPI void ImageDrawTriangleGradient(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image
RLAPI void ImageDrawRectanglePro(Image *dst, Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters within and image
RLAPI void ImageDrawRectangleLines(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle lines within an image
RLAPI void ImageDrawRectangleLinesEx(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image with line thickness
RLAPI void ImageDrawRectangleGradientEx(Image *dst, Rectangle rec, Color col1, Color col2, Color col3, Color col4); // Draw rectangle with gradient colors within an image, counter-clockwise color order
RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image RLAPI void ImageDrawCircle(Image *dst, int centerX, int centerY, int radius, Color color); // Draw a filled circle within an image
RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version) RLAPI void ImageDrawCircleV(Image *dst, Vector2 center, int radius, Color color); // Draw a filled circle within an image (Vector version)
RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image RLAPI void ImageDrawCircleLines(Image *dst, int centerX, int centerY, int radius, Color color); // Draw circle outline within an image
RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version) RLAPI void ImageDrawCircleLinesV(Image *dst, Vector2 center, int radius, Color color); // Draw circle outline within an image (Vector version)
RLAPI void ImageDrawRectangle(Image *dst, int posX, int posY, int width, int height, Color color); // Draw rectangle within an image RLAPI void ImageDrawCircleGradient(Image *dst, Vector2 center, float radius, Color inner, Color outer); // Draw a gradient-filled circle within an image
RLAPI void ImageDrawRectangleV(Image *dst, Vector2 position, Vector2 size, Color color); // Draw rectangle within an image (Vector version)
RLAPI void ImageDrawRectangleRec(Image *dst, Rectangle rec, Color color); // Draw rectangle within an image RLAPI void ImageDrawImage(Image *dst, Image src, int posX, int posY, Color tint); // Draw an image within an image
RLAPI void ImageDrawRectangleLines(Image *dst, Rectangle rec, int thick, Color color); // Draw rectangle lines within an image RLAPI void ImageDrawImageEx(Image *dst, Image src, Vector2 position, float rotation, float scale, Color tint); // Draw an image with scaling and rotation within an image
RLAPI void ImageDrawTriangle(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle within an image RLAPI void ImageDrawImageRec(Image *dst, Image src, Rectangle srcRec, Vector2 position, Color tint); // Draw a part of an image defined by a rectangle within an image
RLAPI void ImageDrawTriangleEx(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color c1, Color c2, Color c3); // Draw triangle with interpolated colors within an image RLAPI void ImageDrawImagePro(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Vector2 origin, float rotation, Color tint); // Draw a part of an image defined by a rectangle into destination rectangle, with scaling and rotation, within an image
RLAPI void ImageDrawTriangleLines(Image *dst, Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline within an image
RLAPI void ImageDrawTriangleFan(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle fan defined by points within an image (first vertex is the center)
RLAPI void ImageDrawTriangleStrip(Image *dst, const Vector2 *points, int pointCount, Color color); // Draw a triangle strip defined by points within an image
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec, Color tint); // Draw a source image within a destination image (tint applied to source)
RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination) RLAPI void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) within an image (destination)
RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination) RLAPI void ImageDrawTextEx(Image *dst, Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text (custom sprite font) within an image (destination)
RLAPI void ImageDrawTextPro(Image *dst, Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
// Texture loading functions // Texture loading functions
// NOTE: These functions require GPU access // NOTE: These functions require GPU access
@ -1442,9 +1461,9 @@ RLAPI Texture2D LoadTexture(const char *fileName);
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported RLAPI TextureCubemap LoadTextureCubemap(Image image, int layout); // Load cubemap from image, multiple image cubemap layouts supported
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer) RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
RLAPI bool IsTextureValid(Texture2D texture); // Check if a texture is valid (loaded in GPU) RLAPI bool IsTextureValid(Texture2D texture); // Check if texture is valid (loaded in GPU)
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM) RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if a render texture is valid (loaded in GPU) RLAPI bool IsRenderTextureValid(RenderTexture2D target); // Check if render texture is valid (loaded in GPU)
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM) RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data (pixels should be able to fill texture) RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data (pixels should be able to fill texture)
RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data (pixels and rec should fit in texture) RLAPI void UpdateTextureRec(Texture2D texture, Rectangle rec, const void *pixels); // Update GPU texture rectangle with new data (pixels and rec should fit in texture)
@ -1457,10 +1476,10 @@ RLAPI void SetTextureWrap(Texture2D texture, int wrap);
// Texture drawing functions // Texture drawing functions
RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with rotation and scale
RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle RLAPI void DrawTextureRec(Texture2D texture, Rectangle rec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters RLAPI void DrawTexturePro(Texture2D texture, Rectangle srcrec, Rectangle dstrec, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a source rectangle to destination rectangle, with scaling and rotation
RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dstrec, Vector2 origin, float rotation, Color tint); // Draw a texture (or part of it) that stretches or shrinks nicely
// Color/pixel related functions // Color/pixel related functions
RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal RLAPI bool ColorIsEqual(Color col1, Color col2); // Check if two colors are equal
@ -1477,7 +1496,7 @@ RLAPI Color ColorAlpha(Color color, float alpha); // G
RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint RLAPI Color ColorAlphaBlend(Color dst, Color src, Color tint); // Get src alpha-blended into dst color with tint
RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f] RLAPI Color ColorLerp(Color color1, Color color2, float factor); // Get color lerp interpolation between two colors, factor [0.0f..1.0f]
RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value RLAPI Color GetColor(unsigned int hexValue); // Get Color structure from hexadecimal value
RLAPI Color GetPixelColor(void *srcPtr, int format); // Get Color from a source pixel pointer of certain format RLAPI Color GetPixelColor(const void *srcPtr, int format); // Get Color from a source pixel pointer of certain format
RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer RLAPI void SetPixelColor(void *dstPtr, Color color, int format); // Set color formatted into destination pixel pointer
RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format RLAPI int GetPixelDataSize(int width, int height, int format); // Get pixel data size in bytes for certain format
@ -1488,10 +1507,10 @@ RLAPI int GetPixelDataSize(int width, int height, int format); // G
// Font loading/unloading functions // Font loading/unloading functions
RLAPI Font GetFontDefault(void); // Get the default Font RLAPI Font GetFontDefault(void); // Get the default Font
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM) RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with extended parameters, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height RLAPI Font LoadFontEx(const char *fileName, int fontSize, const int *codepoints, int codepointCount); // Load font from file with defined codepoints and generation size, use NULL for codepoints and 0 for codepointCount to load the default character set, font size is provided in pixels height
RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style) RLAPI Font LoadFontFromImage(Image image, Color key, int firstChar); // Load font from Image (XNA style)
RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf' RLAPI Font LoadFontFromMemory(const char *fileType, const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount); // Load font from memory buffer, fileType refers to extension: i.e. '.ttf'
RLAPI bool IsFontValid(Font font); // Check if a font is valid (font data loaded, WARNING: GPU texture not checked) RLAPI bool IsFontValid(Font font); // Check if font is valid (font data loaded, WARNING: GPU texture not checked)
RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use RLAPI GlyphInfo *LoadFontData(const unsigned char *fileData, int dataSize, int fontSize, const int *codepoints, int codepointCount, int type, int *glyphCount); // Load font data for further use
RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info RLAPI Image GenImageFontAtlas(const GlyphInfo *glyphs, Rectangle **glyphRecs, int glyphCount, int fontSize, int padding, int packMethod); // Generate image font atlas using chars info
RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM) RLAPI void UnloadFontData(GlyphInfo *glyphs, int glyphCount); // Unload font chars info data (RAM)
@ -1504,7 +1523,7 @@ RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color co
RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters RLAPI void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, float spacing, Color tint); // Draw text using font and additional parameters
RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation) RLAPI void DrawTextPro(Font font, const char *text, Vector2 position, Vector2 origin, float rotation, float fontSize, float spacing, Color tint); // Draw text using Font and pro parameters (rotation)
RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint) RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float fontSize, Color tint); // Draw one character (codepoint)
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint) RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int codepointCount, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple characters (codepoint)
// Text font info functions // Text font info functions
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
@ -1532,7 +1551,7 @@ RLAPI const char *CodepointToUTF8(int codepoint, int *utf8Size);
RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n') RLAPI char **LoadTextLines(const char *text, int *count); // Load text as separate lines ('\n')
RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines RLAPI void UnloadTextLines(char **text, int lineCount); // Unload text lines
RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied RLAPI int TextCopy(char *dst, const char *src); // Copy one string to another, returns bytes copied
RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text string are equal RLAPI bool TextIsEqual(const char *text1, const char *text2); // Check if two text strings are equal
RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending RLAPI unsigned int TextLength(const char *text); // Get text length, checks for '\0' ending
RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style) RLAPI const char *TextFormat(const char *text, ...); // Text formatting with variables (sprintf() style)
RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string RLAPI const char *TextSubtext(const char *text, int position, int length); // Get a piece of a text string
@ -1564,21 +1583,21 @@ RLAPI float TextToFloat(const char *text);
RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line RLAPI void DrawPoint3D(Vector3 position, Color color); // Draw a point in 3D space, actually a small line
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle (vertex in counter-clockwise order!) RLAPI void DrawTriangle3D(Vector3 v1, Vector3 v2, Vector3 v3, Color color); // Draw a color-filled triangle, counter-clockwise vertex order
RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points RLAPI void DrawTriangleStrip3D(const Vector3 *points, int pointCount, Color color); // Draw a triangle strip defined by points
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version) RLAPI void DrawCubeWiresV(Vector3 position, Vector3 size, Color color); // Draw cube wires (Vector version)
RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with defined rings and slices
RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color); // Draw a cylinder/cone
RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos
RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color); // Draw a cylinder/cone wires
RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos
RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos
RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int rings, int slices, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos
RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
@ -1590,19 +1609,19 @@ RLAPI void DrawGrid(int slices, float spacing);
// Model management functions // Model management functions
RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials) RLAPI Model LoadModel(const char *fileName); // Load model from files (meshes and materials)
RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material) RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh (default material)
RLAPI bool IsModelValid(Model model); // Check if a model is valid (loaded in GPU, VAO/VBOs) RLAPI bool IsModelValid(Model model); // Check if model is valid (loaded in GPU, VAO/VBOs)
RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM) RLAPI void UnloadModel(Model model); // Unload model (including meshes) from memory (RAM and/or VRAM)
RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes)
// Model drawing functions // Model drawing functions
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with custom transform
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires with custom transform
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a billboard texture
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle rec, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by rectangle
RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle rec, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source rectangle with scaling and rotation
// Mesh management functions // Mesh management functions
RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids RLAPI void UploadMesh(Mesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
@ -1631,7 +1650,7 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
// Material loading/unloading functions // Material loading/unloading functions
RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file RLAPI Material *LoadMaterials(const char *fileName, int *materialCount); // Load materials from model file
RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps)
RLAPI bool IsMaterialValid(Material material); // Check if a material is valid (shader assigned, map textures loaded in GPU) RLAPI bool IsMaterialValid(Material material); // Check if material is valid (shader assigned, map textures loaded in GPU)
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) RLAPI void SetMaterialTexture(Material *material, int mapType, Texture2D texture); // Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...)
RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh RLAPI void SetModelMeshMaterial(Model *model, int meshId, int materialId); // Set material for a mesh
@ -1668,15 +1687,15 @@ RLAPI float GetMasterVolume(void); // Get mas
// Wave/Sound loading/unloading functions // Wave/Sound loading/unloading functions
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav' RLAPI Wave LoadWaveFromMemory(const char *fileType, const unsigned char *fileData, int dataSize); // Load wave from memory buffer, fileType refers to extension: i.e. '.wav'
RLAPI bool IsWaveValid(Wave wave); // Checks if wave data is valid (data loaded and parameters) RLAPI bool IsWaveValid(Wave wave); // Check if wave data is valid (data loaded and parameters)
RLAPI Sound LoadSound(const char *fileName); // Load sound from file RLAPI Sound LoadSound(const char *fileName); // Load sound from file
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
RLAPI Sound LoadSoundAlias(Sound source); // Create a new sound that shares the same sample data as the source sound, does not own the sound data RLAPI Sound LoadSoundAlias(Sound source); // Load sound alias, new sound that shares the same sample data as the source sound, does not own the sound data
RLAPI bool IsSoundValid(Sound sound); // Checks if a sound is valid (data loaded and buffers initialized) RLAPI bool IsSoundValid(Sound sound); // Check if sound is valid (data loaded and buffers initialized)
RLAPI void UpdateSound(Sound sound, const void *data, int sampleCount); // Update sound buffer with new data (default data format: 32 bit float, stereo) RLAPI void UpdateSound(Sound sound, const void *data, int frameCount); // Update sound buffer with new data (default data format: 32 bit float, stereo)
RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadWave(Wave wave); // Unload wave data
RLAPI void UnloadSound(Sound sound); // Unload sound RLAPI void UnloadSound(Sound sound); // Unload sound
RLAPI void UnloadSoundAlias(Sound alias); // Unload a sound alias (does not deallocate sample data) RLAPI void UnloadSoundAlias(Sound alias); // Unload sound alias (does not deallocate sample data)
RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success RLAPI bool ExportWave(Wave wave, const char *fileName); // Export wave data to file, returns true on success
RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success RLAPI bool ExportWaveAsCode(Wave wave, const char *fileName); // Export wave sample data to code (.h), returns true on success
@ -1685,7 +1704,7 @@ RLAPI void PlaySound(Sound sound); // Play a
RLAPI void StopSound(Sound sound); // Stop playing a sound RLAPI void StopSound(Sound sound); // Stop playing a sound
RLAPI void PauseSound(Sound sound); // Pause a sound RLAPI void PauseSound(Sound sound); // Pause a sound
RLAPI void ResumeSound(Sound sound); // Resume a paused sound RLAPI void ResumeSound(Sound sound); // Resume a paused sound
RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing RLAPI bool IsSoundPlaying(Sound sound); // Check if sound is currently playing
RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (-1.0 left, 0.0 center, 1.0 right) RLAPI void SetSoundPan(Sound sound, float pan); // Set pan for a sound (-1.0 left, 0.0 center, 1.0 right)
@ -1698,24 +1717,24 @@ RLAPI void UnloadWaveSamples(float *samples); // Unload
// Music management functions // Music management functions
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data RLAPI Music LoadMusicStreamFromMemory(const char *fileType, const unsigned char *data, int dataSize); // Load music stream from data
RLAPI bool IsMusicValid(Music music); // Checks if a music stream is valid (context and buffers initialized) RLAPI bool IsMusicValid(Music music); // Check if music stream is valid (context and buffers initialized)
RLAPI void UnloadMusicStream(Music music); // Unload music stream RLAPI void UnloadMusicStream(Music music); // Unload music stream
RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI void PlayMusicStream(Music music); // Start music playing
RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing RLAPI bool IsMusicStreamPlaying(Music music); // Check if music is playing
RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming RLAPI void UpdateMusicStream(Music music); // Update buffers for music streaming
RLAPI void StopMusicStream(Music music); // Stop music playing RLAPI void StopMusicStream(Music music); // Stop music playing
RLAPI void PauseMusicStream(Music music); // Pause music playing RLAPI void PauseMusicStream(Music music); // Pause music playing
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds) RLAPI void SeekMusicStream(Music music, float position); // Seek music to a position (in seconds)
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level) RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level) RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for music (1.0 is base level)
RLAPI void SetMusicPan(Music music, float pan); // Set pan for a music (-1.0 left, 0.0 center, 1.0 right) RLAPI void SetMusicPan(Music music, float pan); // Set pan for music (-1.0 left, 0.0 center, 1.0 right)
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds) RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
// AudioStream management functions // AudioStream management functions
RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data) RLAPI AudioStream LoadAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Load audio stream (to stream raw audio pcm data)
RLAPI bool IsAudioStreamValid(AudioStream stream); // Checks if an audio stream is valid (buffers initialized) RLAPI bool IsAudioStreamValid(AudioStream stream); // Check if an audio stream is valid (buffers initialized)
RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory RLAPI void UnloadAudioStream(AudioStream stream); // Unload audio stream and free memory
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int frameCount); // Update audio stream buffers with data
RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill RLAPI bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
@ -1726,7 +1745,7 @@ RLAPI bool IsAudioStreamPlaying(AudioStream stream); // Check i
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level) RLAPI void SetAudioStreamVolume(AudioStream stream, float volume); // Set volume for audio stream (1.0 is max level)
RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level) RLAPI void SetAudioStreamPitch(AudioStream stream, float pitch); // Set pitch for audio stream (1.0 is base level)
RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 to 1.0 range, 0.0 is centered) RLAPI void SetAudioStreamPan(AudioStream stream, float pan); // Set pan for audio stream (-1.0 left, 0.0 center, 1.0 right)
RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams RLAPI void SetAudioStreamBufferSizeDefault(int size); // Default size for new audio streams
RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback); // Audio thread callback to request new data

View file

@ -1,6 +1,6 @@
/********************************************************************************************** /**********************************************************************************************
* *
* raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and Quaternions * raymath v2.0 - Math functions to work with Vector2, Vector3, Vector4, Matrix and Quaternions
* *
* CONVENTIONS: * CONVENTIONS:
* - Matrix structure is defined as row-major (memory layout) but parameters naming AND all * - Matrix structure is defined as row-major (memory layout) but parameters naming AND all
@ -2714,13 +2714,13 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].y)); stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].y));
stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].z)); stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].z));
} }
matColumns[0] = Vector3Scale(matColumns[0], 1.0f / stabilizer); matColumns[0] = Vector3Scale(matColumns[0], 1.0f/stabilizer);
matColumns[1] = Vector3Scale(matColumns[1], 1.0f / stabilizer); matColumns[1] = Vector3Scale(matColumns[1], 1.0f/stabilizer);
matColumns[2] = Vector3Scale(matColumns[2], 1.0f / stabilizer); matColumns[2] = Vector3Scale(matColumns[2], 1.0f/stabilizer);
// X Scale // X Scale
scl.x = Vector3Length(matColumns[0]); scl.x = Vector3Length(matColumns[0]);
if (scl.x > eps) matColumns[0] = Vector3Scale(matColumns[0], 1.0f / scl.x); if (scl.x > eps) matColumns[0] = Vector3Scale(matColumns[0], 1.0f/scl.x);
// Compute XY shear and make col2 orthogonal // Compute XY shear and make col2 orthogonal
shear[0] = Vector3DotProduct(matColumns[0], matColumns[1]); shear[0] = Vector3DotProduct(matColumns[0], matColumns[1]);
@ -2730,7 +2730,7 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
scl.y = Vector3Length(matColumns[1]); scl.y = Vector3Length(matColumns[1]);
if (scl.y > eps) if (scl.y > eps)
{ {
matColumns[1] = Vector3Scale(matColumns[1], 1.0f / scl.y); matColumns[1] = Vector3Scale(matColumns[1], 1.0f/scl.y);
shear[0] /= scl.y; // Correct XY shear shear[0] /= scl.y; // Correct XY shear
} }
@ -2744,7 +2744,7 @@ RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, Quaternion *rotatio
scl.z = Vector3Length(matColumns[2]); scl.z = Vector3Length(matColumns[2]);
if (scl.z > eps) if (scl.z > eps)
{ {
matColumns[2] = Vector3Scale(matColumns[2], 1.0f / scl.z); matColumns[2] = Vector3Scale(matColumns[2], 1.0f/scl.z);
shear[1] /= scl.z; // Correct XZ shear shear[1] /= scl.z; // Correct XZ shear
shear[2] /= scl.z; // Correct YZ shear shear[2] /= scl.z; // Correct YZ shear
} }
@ -2802,6 +2802,11 @@ inline const Vector2& operator -= (Vector2& lhs, const Vector2& rhs)
return lhs; return lhs;
} }
inline Vector2 operator * (const float& lhs, const Vector2& rhs)
{
return Vector2Scale(rhs, lhs);
}
inline Vector2 operator * (const Vector2& lhs, const float& rhs) inline Vector2 operator * (const Vector2& lhs, const float& rhs)
{ {
return Vector2Scale(lhs, rhs); return Vector2Scale(lhs, rhs);
@ -2896,6 +2901,11 @@ inline const Vector3& operator -= (Vector3& lhs, const Vector3& rhs)
return lhs; return lhs;
} }
inline Vector3 operator * (const float& lhs, const Vector3& rhs)
{
return Vector3Scale(rhs, lhs);
}
inline Vector3 operator * (const Vector3& lhs, const float& rhs) inline Vector3 operator * (const Vector3& lhs, const float& rhs)
{ {
return Vector3Scale(lhs, rhs); return Vector3Scale(lhs, rhs);
@ -2991,6 +3001,11 @@ inline const Vector4& operator -= (Vector4& lhs, const Vector4& rhs)
return lhs; return lhs;
} }
inline Vector4 operator * (const float& lhs, const Vector4& rhs)
{
return Vector4Scale(rhs, lhs);
}
inline Vector4 operator * (const Vector4& lhs, const float& rhs) inline Vector4 operator * (const Vector4& lhs, const float& rhs)
{ {
return Vector4Scale(lhs, rhs); return Vector4Scale(lhs, rhs);

View file

@ -106,11 +106,16 @@
#include "config.h" // Defines module configuration flags #include "config.h" // Defines module configuration flags
#include <stdlib.h> // Required for: srand(), rand(), atexit(), exit() #include <stdlib.h> // Required for: srand(), rand(), exit()
#include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()] #include <stdio.h> // Required for: FILE, fopen(), fseek(), ftell(), fread(), fwrite(), fprintf(), vprintf(), fclose(), sprintf() [Used in OpenURL()]
#include <string.h> // Required for: strlen(), strncpy(), strcmp(), strrchr(), memset(), strcat() #include <string.h> // Required for: strlen(), strcmp(), strrchr(), memset(), memcpy(), strcat()
#include <stdarg.h> // Required for: va_list, va_start(), va_end() [Used in TraceLog()] #include <stdarg.h> // Required for: va_list, va_start(), va_end() [Used in TraceLog()]
#ifndef PICO_RP2350
#include <time.h> // Required for: time() [Used in InitTimer()] #include <time.h> // Required for: time() [Used in InitTimer()]
#else
#include "pico/rand.h" // Pico doesn't implement time, and will implement its own hardware timer elsewhere. However, we need something to get a random seed from...
#endif
#include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()] #include <math.h> // Required for: tan() [Used in BeginMode3D()], atan2f() [Used in LoadVrStereoConfig()]
#if defined(PLATFORM_MEMORY) || defined(PLATFORM_WEB) #if defined(PLATFORM_MEMORY) || defined(PLATFORM_WEB)
@ -385,7 +390,7 @@ typedef struct CoreData {
double draw; // Time measure for frame draw (seconds) double draw; // Time measure for frame draw (seconds)
double frame; // Time measure for one frame (seconds) double frame; // Time measure for one frame (seconds)
double target; // Desired time for one frame, if 0 not applied (seconds) double target; // Desired time for one frame, if 0 not applied (seconds)
unsigned long long int base; // Base time measure for hi-res timer (ticks or nanoseconds) unsigned long long base; // Base time measure for hi-res timer (ticks or nanoseconds)
unsigned int frameCounter; // Frame counter (frames) unsigned int frameCounter; // Frame counter (frames)
} Time; } Time;
@ -442,18 +447,6 @@ typedef enum AutomationEventType {
ACTION_SETTARGETFPS // param[0]: fps ACTION_SETTARGETFPS // param[0]: fps
} AutomationEventType; } AutomationEventType;
// Event type to config events flags
// WARNING: Not used at the moment
typedef enum {
EVENT_INPUT_KEYBOARD = 0,
EVENT_INPUT_MOUSE = 1,
EVENT_INPUT_GAMEPAD = 2,
EVENT_INPUT_TOUCH = 4,
EVENT_INPUT_GESTURE = 8,
EVENT_WINDOW = 16,
EVENT_CUSTOM = 32
} EventType;
// Event type name strings, required for export // Event type name strings, required for export
static const char *autoEventTypeName[] = { static const char *autoEventTypeName[] = {
"EVENT_NONE", "EVENT_NONE",
@ -482,16 +475,6 @@ static const char *autoEventTypeName[] = {
"ACTION_SETTARGETFPS" "ACTION_SETTARGETFPS"
}; };
/*
// Automation event (24 bytes)
// NOTE: Opaque struct, internal to raylib
struct AutomationEvent {
unsigned int frame; // Event frame
unsigned int type; // Event type (AutomationEventType)
int params[4]; // Event parameters (if required)
};
*/
static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer static AutomationEventList *currentEventList = NULL; // Current automation events list, set by user, keep internal pointer
static bool automationEventRecording = false; // Recording automation events flag static bool automationEventRecording = false; // Recording automation events flag
//static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing //static short automationEventEnabled = 0b0000001111111111; // TODO: Automation events enabled for recording/playing
@ -528,11 +511,11 @@ __declspec(dllimport) void __stdcall Sleep(unsigned long msTimeout); // Required
const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed'
#endif #endif
// NOTE: PLATFORM_DESKTOP defaults to GLFW backend
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define PLATFORM_DESKTOP_GLFW #define PLATFORM_DESKTOP_GLFW
#endif #endif
// Include platform-specific submodules // Include platform-specific submodules
#if defined(PLATFORM_DESKTOP_GLFW) #if defined(PLATFORM_DESKTOP_GLFW)
#include "platforms/rcore_desktop_glfw.c" #include "platforms/rcore_desktop_glfw.c"
@ -735,8 +718,12 @@ void InitWindow(int width, int height, const char *title)
CORE.Time.frameCounter = 0; CORE.Time.frameCounter = 0;
CORE.Window.shouldClose = false; CORE.Window.shouldClose = false;
// Initialize random seed // Initialize random seed using available timer source instead of standard time() on embedded platforms
#ifndef PICO_RP2350
SetRandomSeed((unsigned int)time(NULL)); SetRandomSeed((unsigned int)time(NULL));
#else
SetRandomSeed(get_rand_32());
#endif
TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory()); TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", GetWorkingDirectory());
} }
@ -869,14 +856,14 @@ bool IsCursorOnScreen(void)
// Module Functions Definition: Screen Drawing // Module Functions Definition: Screen Drawing
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Set background color (framebuffer clear color) // Clear background (framebuffer) to color
void ClearBackground(Color color) void ClearBackground(Color color)
{ {
rlClearColor(color.r, color.g, color.b, color.a); // Set clear color rlClearColor(color.r, color.g, color.b, color.a); // Set clear color
rlClearScreenBuffers(); // Clear current framebuffers rlClearScreenBuffers(); // Clear current framebuffers
} }
// Setup canvas (framebuffer) to start drawing // Begin canvas (framebuffer) drawing
void BeginDrawing(void) void BeginDrawing(void)
{ {
// WARNING: Previously to BeginDrawing() other render textures drawing could happen, // WARNING: Previously to BeginDrawing() other render textures drawing could happen,
@ -893,7 +880,7 @@ void BeginDrawing(void)
// NOTE: Not required with OpenGL 3.3+ // NOTE: Not required with OpenGL 3.3+
} }
// End canvas drawing and swap buffers (double buffering) // End canvas (framebuffer) drawing and swap buffers (double buffering)
void EndDrawing(void) void EndDrawing(void)
{ {
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
@ -949,7 +936,7 @@ void BeginMode2D(Camera2D camera)
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera))); rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
} }
// Ends 2D mode with custom camera // End 2D mode with custom camera
void EndMode2D(void) void EndMode2D(void)
{ {
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
@ -998,7 +985,7 @@ void BeginMode3D(Camera camera)
rlEnableDepthTest(); // Enable DEPTH_TEST for 3D rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
} }
// Ends 3D mode and returns to default 2D orthographic mode // End 3D mode and returns to default 2D orthographic mode
void EndMode3D(void) void EndMode3D(void)
{ {
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
@ -1045,7 +1032,7 @@ void BeginTextureMode(RenderTexture2D target)
CORE.Window.usingFbo = true; CORE.Window.usingFbo = true;
} }
// Ends drawing to render texture // End drawing to render texture
void EndTextureMode(void) void EndTextureMode(void)
{ {
rlDrawRenderBatchActive(); // Update and draw internal render batch rlDrawRenderBatchActive(); // Update and draw internal render batch
@ -1315,7 +1302,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
return shader; return shader;
} }
// Check if a shader is valid (loaded on GPU) // Check if shader is valid (loaded on GPU)
bool IsShaderValid(Shader shader) bool IsShaderValid(Shader shader)
{ {
return ((shader.id > 0) && // Validate shader id (GPU loaded successfully) return ((shader.id > 0) && // Validate shader id (GPU loaded successfully)
@ -1514,7 +1501,7 @@ Matrix GetCameraMatrix2D(Camera2D camera)
return matTransform; return matTransform;
} }
// Get the screen space position from a 3d world space position // Get screen space position from a 3d world space position
Vector2 GetWorldToScreen(Vector3 position, Camera camera) Vector2 GetWorldToScreen(Vector3 position, Camera camera)
{ {
Vector2 screenPosition = GetWorldToScreenEx(position, camera, GetScreenWidth(), GetScreenHeight()); Vector2 screenPosition = GetWorldToScreenEx(position, camera, GetScreenWidth(), GetScreenHeight());
@ -1522,7 +1509,7 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera)
return screenPosition; return screenPosition;
} }
// Get size position for a 3d world space position (useful for texture drawing) // Get sized screen space position for a 3d world space position (useful for texture drawing)
Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height) Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height)
{ {
// Calculate projection matrix (from perspective instead of frustum // Calculate projection matrix (from perspective instead of frustum
@ -1564,7 +1551,7 @@ Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int heigh
return screenPosition; return screenPosition;
} }
// Get the screen space position for a 2d camera world space position // Get screen space position for a 2d camera world space position
Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera) Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
{ {
Matrix matCamera = GetCameraMatrix2D(camera); Matrix matCamera = GetCameraMatrix2D(camera);
@ -1573,7 +1560,7 @@ Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
return (Vector2){ transform.x, transform.y }; return (Vector2){ transform.x, transform.y };
} }
// Get the world space position for a 2d camera screen space position // Get world space position for a 2d camera screen space position
Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera) Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera)
{ {
Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera)); Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera));
@ -1757,9 +1744,9 @@ int GetRandomValue(int min, int max)
else else
{ {
// Rejection sampling to get a uniform integer in [min, max] // Rejection sampling to get a uniform integer in [min, max]
unsigned long c = (unsigned long)RAND_MAX + 1UL; // number of possible rand() results unsigned long c = (unsigned long)RAND_MAX + 1UL; // Number of possible results
unsigned long m = (unsigned long)range; // size of the target interval unsigned long m = (unsigned long)range; // Size of the target interval
unsigned long t = c - (c%m); // largest multiple of m <= c unsigned long t = c - (c%m); // Largest multiple of m <= c
unsigned long r = 0; unsigned long r = 0;
for (;;) for (;;)
@ -1826,7 +1813,6 @@ void UnloadRandomSequence(int *sequence)
} }
// Takes a screenshot of current screen // Takes a screenshot of current screen
// NOTE: Provided fileName should not contain paths, saving to working directory
void TakeScreenshot(const char *fileName) void TakeScreenshot(const char *fileName)
{ {
#if SUPPORT_MODULE_RTEXTURES #if SUPPORT_MODULE_RTEXTURES
@ -1841,7 +1827,8 @@ void TakeScreenshot(const char *fileName)
Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; Image image = { imgData, (int)((float)CORE.Window.render.width*scale.x), (int)((float)CORE.Window.render.height*scale.y), 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
char path[MAX_FILEPATH_LENGTH] = { 0 }; char path[MAX_FILEPATH_LENGTH] = { 0 };
strncpy(path, TextFormat("%s/%s", CORE.Storage.basePath, fileName), MAX_FILEPATH_LENGTH - 1); if (!IsPathAbsolute(fileName)) snprintf(path, MAX_FILEPATH_LENGTH, "%s", TextFormat("%s/%s", CORE.Storage.basePath, fileName));
else snprintf(path, MAX_FILEPATH_LENGTH, "%s", fileName);
ExportImage(image, path); // WARNING: Module required: rtextures ExportImage(image, path); // WARNING: Module required: rtextures
RL_FREE(imgData); RL_FREE(imgData);
@ -1853,7 +1840,7 @@ void TakeScreenshot(const char *fileName)
#endif #endif
} }
// Setup window configuration flags (view FLAGS) // Set up window configuration flags (view FLAGS)
// NOTE: This function is expected to be called before window creation, // NOTE: This function is expected to be called before window creation,
// because it sets up some flags for the window creation process // because it sets up some flags for the window creation process
// To configure window states after creation, use SetWindowState() // To configure window states after creation, use SetWindowState()
@ -1866,8 +1853,6 @@ void SetConfigFlags(unsigned int flags)
FLAG_SET(CORE.Window.flags, flags); FLAG_SET(CORE.Window.flags, flags);
} }
// void OpenURL(const char *url); // Defined per platform
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition: Logging system // Module Functions Definition: Logging system
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -1907,12 +1892,12 @@ void TraceLog(int logType, const char *text, ...)
switch (logType) switch (logType)
{ {
case LOG_TRACE: strncpy(buffer, "TRACE: ", 8); break; case LOG_TRACE: memcpy(buffer, "TRACE: ", 7); break;
case LOG_DEBUG: strncpy(buffer, "DEBUG: ", 8); break; case LOG_DEBUG: memcpy(buffer, "DEBUG: ", 7); break;
case LOG_INFO: strncpy(buffer, "INFO: ", 7); break; case LOG_INFO: memcpy(buffer, "INFO: ", 6); break;
case LOG_WARNING: strncpy(buffer, "WARNING: ", 10); break; case LOG_WARNING: memcpy(buffer, "WARNING: ", 9); break;
case LOG_ERROR: strncpy(buffer, "ERROR: ", 8); break; case LOG_ERROR: memcpy(buffer, "ERROR: ", 7); break;
case LOG_FATAL: strncpy(buffer, "FATAL: ", 8); break; case LOG_FATAL: memcpy(buffer, "FATAL: ", 7); break;
default: break; default: break;
} }
@ -1992,7 +1977,7 @@ unsigned char *LoadFileData(const char *fileName, int *dataSize)
size_t count = fread(data, sizeof(unsigned char), size, file); size_t count = fread(data, sizeof(unsigned char), size, file);
// WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation) // WARNING: fread() returns a size_t value, usually 'unsigned int' (32bit compilation) and 'unsigned long long' (64bit compilation)
// dataSize is unified along raylib as a 'int' type, so, for file-sizes > INT_MAX (2147483647 bytes) there is a limitation // dataSize is unified along raylib as a 'int' type, so, for file-sizes >INT_MAX (2147483647 bytes) there is a limitation
if (count > 2147483647) if (count > 2147483647)
{ {
TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName); TRACELOG(LOG_WARNING, "FILEIO: [%s] File is bigger than 2147483647 bytes, avoid using LoadFileData()", fileName);
@ -2004,7 +1989,7 @@ unsigned char *LoadFileData(const char *fileName, int *dataSize)
{ {
*dataSize = (int)count; *dataSize = (int)count;
if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, dataSize, count); if ((*dataSize) != size) TRACELOG(LOG_WARNING, "FILEIO: [%s] File partially loaded (%i bytes out of %i)", fileName, *dataSize, size);
else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName); else TRACELOG(LOG_INFO, "FILEIO: [%s] File loaded successfully", fileName);
} }
} }
@ -2028,7 +2013,7 @@ void UnloadFileData(unsigned char *data)
} }
// Save data to file from buffer // Save data to file from buffer
bool SaveFileData(const char *fileName, void *data, int dataSize) bool SaveFileData(const char *fileName, const void *data, int dataSize)
{ {
bool result = false; bool result = false;
@ -2085,7 +2070,7 @@ bool ExportDataAsCode(const unsigned char *data, int dataSize, const char *fileN
// Get file name from path // Get file name from path
char varFileName[256] = { 0 }; char varFileName[256] = { 0 };
strncpy(varFileName, GetFileNameWithoutExt(fileName), 256 - 1); snprintf(varFileName, 256, "%s", GetFileNameWithoutExt(fileName));
for (int i = 0; varFileName[i] != '\0'; i++) for (int i = 0; varFileName[i] != '\0'; i++)
{ {
// Convert variable name to uppercase // Convert variable name to uppercase
@ -2227,13 +2212,12 @@ void SetSaveFileTextCallback(SaveFileTextCallback callback)
// NOTE: Only rename file name required, not full path // NOTE: Only rename file name required, not full path
int FileRename(const char *fileName, const char *fileRename) int FileRename(const char *fileName, const char *fileRename)
{ {
int result = 0; int result = -1;
if (FileExists(fileName)) if (FileExists(fileName))
{ {
result = rename(fileName, fileRename); result = rename(fileName, fileRename);
} }
else result = -1;
return result; return result;
} }
@ -2241,13 +2225,12 @@ int FileRename(const char *fileName, const char *fileRename)
// Remove file (if exists) // Remove file (if exists)
int FileRemove(const char *fileName) int FileRemove(const char *fileName)
{ {
int result = 0; int result = -1;
if (FileExists(fileName)) if (FileExists(fileName))
{ {
result = remove(fileName); result = remove(fileName);
} }
else result = -1;
return result; return result;
} }
@ -2256,18 +2239,21 @@ int FileRemove(const char *fileName)
// NOTE: If destination path does not exist, it is created! // NOTE: If destination path does not exist, it is created!
int FileCopy(const char *srcPath, const char *dstPath) int FileCopy(const char *srcPath, const char *dstPath)
{ {
int result = 0; int result = -1;
int srcDataSize = 0; int srcDataSize = 0;
unsigned char *srcFileData = LoadFileData(srcPath, &srcDataSize); unsigned char *srcFileData = LoadFileData(srcPath, &srcDataSize);
// Create required paths if they do not exist // Create required paths if they do not exist
if (!DirectoryExists(GetDirectoryPath(dstPath))) if (DirectoryExists(GetDirectoryPath(dstPath))) result = 0; // Already exists
result = MakeDirectory(GetDirectoryPath(dstPath)); else result = MakeDirectory(GetDirectoryPath(dstPath));
if (result == 0) // Directory created successfully (or already exists) if (result == 0) // Directory created successfully or already exists
{ {
if ((srcFileData != NULL) && (srcDataSize > 0)) if ((srcFileData != NULL) && (srcDataSize > 0))
result = SaveFileData(dstPath, srcFileData, srcDataSize); {
bool saved = SaveFileData(dstPath, srcFileData, srcDataSize);
if (saved) result = 0;
}
} }
UnloadFileData(srcFileData); UnloadFileData(srcFileData);
@ -2283,9 +2269,19 @@ int FileMove(const char *srcPath, const char *dstPath)
if (FileExists(srcPath)) if (FileExists(srcPath))
{ {
if (FileCopy(srcPath, dstPath) == 0) result = FileRemove(srcPath); result = FileCopy(srcPath, dstPath);
if (result == 0)
{
// Make sure file has been correctly copied before removing
if (FileExists(dstPath) && (GetFileLength(srcPath) == GetFileLength(dstPath)))
{
result = FileRemove(srcPath);
if (result != 0) TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to remove source file after copy", srcPath);
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Failed to copy file to [%s]", srcPath, dstPath);
} }
}
else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath); else TRACELOG(LOG_WARNING, "FILEIO: [%s] Source file does not exist", srcPath);
return result; return result;
@ -2295,16 +2291,18 @@ int FileMove(const char *srcPath, const char *dstPath)
// WARNING: DEPENDENCY: [rtext] module // WARNING: DEPENDENCY: [rtext] module
int FileTextReplace(const char *fileName, const char *search, const char *replacement) int FileTextReplace(const char *fileName, const char *search, const char *replacement)
{ {
int result = 0; int result = -1;
#if SUPPORT_MODULE_RTEXT
char *fileText = NULL; char *fileText = NULL;
char *fileTextUpdated = { 0 }; char *fileTextUpdated = { 0 };
#if SUPPORT_MODULE_RTEXT
if (FileExists(fileName)) if (FileExists(fileName))
{ {
fileText = LoadFileText(fileName); fileText = LoadFileText(fileName);
fileTextUpdated = TextReplaceAlloc(fileText, search, replacement); fileTextUpdated = TextReplaceAlloc(fileText, search, replacement);
result = SaveFileText(fileName, fileTextUpdated); bool saved = SaveFileText(fileName, fileTextUpdated);
if (saved) result = 0;
MemFree(fileTextUpdated); MemFree(fileTextUpdated);
UnloadFileText(fileText); UnloadFileText(fileText);
} }
@ -2337,7 +2335,7 @@ bool FileExists(const char *fileName)
{ {
bool result = false; bool result = false;
if (ACCESS(fileName) != -1) result = true; if ((fileName != NULL) && (ACCESS(fileName) != -1)) result = true;
// NOTE: Alternatively, stat() can be used instead of access() // NOTE: Alternatively, stat() can be used instead of access()
//#include <sys/stat.h> //#include <sys/stat.h>
@ -2362,8 +2360,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
{ {
int fileExtLength = (int)strlen(fileExt); int fileExtLength = (int)strlen(fileExt);
char fileExtLower[16] = { 0 }; char fileExtLower[16] = { 0 };
char *fileExtLowerPtr = fileExtLower; for (int i = 0; (i < fileExtLength) && (i < 15); i++)
for (int i = 0; (i < fileExtLength) && (i < 16); i++)
{ {
// Copy and convert to lower-case // Copy and convert to lower-case
if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32; if ((fileExt[i] >= 'A') && (fileExt[i] <= 'Z')) fileExtLower[i] = fileExt[i] + 32;
@ -2374,7 +2371,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
int extLength = (int)strlen(ext); int extLength = (int)strlen(ext);
char *extList = (char *)RL_CALLOC(extLength + 1, 1); char *extList = (char *)RL_CALLOC(extLength + 1, 1);
char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 }; char *extListPtrs[MAX_FILE_EXTENSIONS] = { 0 };
strncpy(extList, ext, extLength); memcpy(extList, ext, extLength);
extListPtrs[0] = extList; extListPtrs[0] = extList;
for (int i = 0; i < extLength; i++) for (int i = 0; i < extLength; i++)
@ -2383,19 +2380,23 @@ bool IsFileExtension(const char *fileName, const char *ext)
if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32; if ((extList[i] >= 'A') && (extList[i] <= 'Z')) extList[i] += 32;
// Get pointer to next extension and add null-terminator // Get pointer to next extension and add null-terminator
if ((extList[i] == ';') && (extCount < (MAX_FILE_EXTENSIONS - 1))) if (extList[i] == ';')
{ {
extList[i] = '\0'; extList[i] = '\0';
if (extCount < MAX_FILE_EXTENSIONS)
{
extListPtrs[extCount] = extList + i + 1; extListPtrs[extCount] = extList + i + 1;
extCount++; extCount++;
} }
} }
}
for (int i = 0; i < extCount; i++) for (int i = 0; i < extCount; i++)
{ {
// Consider the case where extension provided // Consider the case where extension provided
// does not start with the '.' // does not start with the '.'
fileExtLowerPtr = fileExtLower; char *fileExtLowerPtr = fileExtLower;
if (extListPtrs[i][0] != '.') fileExtLowerPtr++; if (extListPtrs[i][0] != '.') fileExtLowerPtr++;
if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0) if (strcmp(fileExtLowerPtr, extListPtrs[i]) == 0)
@ -2411,7 +2412,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
return result; return result;
} }
// Check if a directory path exists // Check if directory path exists
bool DirectoryExists(const char *dirPath) bool DirectoryExists(const char *dirPath)
{ {
bool result = false; bool result = false;
@ -2513,7 +2514,7 @@ const char *GetFileNameWithoutExt(const char *filePath)
if (filePath != NULL) if (filePath != NULL)
{ {
strncpy(fileName, GetFileName(filePath), MAX_FILENAME_LENGTH - 1); // Get filename.ext without path snprintf(fileName, MAX_FILENAME_LENGTH, "%s", GetFileName(filePath)); // Get filename.ext without path
int fileNameLength = (int)strlen(fileName); // Get size in bytes int fileNameLength = (int)strlen(fileName); // Get size in bytes
for (int i = fileNameLength; i > 0; i--) // Reverse search '.' for (int i = fileNameLength; i > 0; i--) // Reverse search '.'
@ -2530,7 +2531,7 @@ const char *GetFileNameWithoutExt(const char *filePath)
return fileName; return fileName;
} }
// Get directory for a given filePath // Get directory for a provided filePath
const char *GetDirectoryPath(const char *filePath) const char *GetDirectoryPath(const char *filePath)
{ {
/* /*
@ -2567,7 +2568,6 @@ const char *GetDirectoryPath(const char *filePath)
} }
else else
{ {
// NOTE: Be careful, strncpy() is not safe, it does not care about '\0'
char *dirPathPtr = dirPath; char *dirPathPtr = dirPath;
if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/')) dirPathPtr += 2; // Skip drive letter, "C:" if ((filePath[1] != ':') && (filePath[0] != '\\') && (filePath[0] != '/')) dirPathPtr += 2; // Skip drive letter, "C:"
memcpy(dirPathPtr, filePath, strlen(filePath) - (strlen(lastSlash) - 1)); memcpy(dirPathPtr, filePath, strlen(filePath) - (strlen(lastSlash) - 1));
@ -2578,25 +2578,33 @@ const char *GetDirectoryPath(const char *filePath)
return dirPath; return dirPath;
} }
// Get previous directory path for a given path // Get previous directory path for a provided path
const char *GetPrevDirectoryPath(const char *dirPath) const char *GetPrevDirectoryPath(const char *dirPath)
{ {
static char prevDirPath[MAX_FILEPATH_LENGTH] = { 0 }; static char prevDirPath[MAX_FILEPATH_LENGTH] = { 0 };
memset(prevDirPath, 0, MAX_FILEPATH_LENGTH); memset(prevDirPath, 0, MAX_FILEPATH_LENGTH);
int dirPathLength = (int)strlen(dirPath);
if (dirPathLength <= 3) strncpy(prevDirPath, dirPath, MAX_FILEPATH_LENGTH - 1); const int lastIndex = (int)strlen(dirPath) - 1;
bool isFile = IsPathFile(dirPath);
for (int i = (dirPathLength - 1); (i >= 0) && (dirPathLength > 3); i--) for (int i = lastIndex; i >= 0; i--)
{ {
// If the character is a path separator.
if ((dirPath[i] == '\\') || (dirPath[i] == '/')) if ((dirPath[i] == '\\') || (dirPath[i] == '/'))
{ {
// Check for root: "C:\" or "/" // If this character is a leading '/' (e.g. the '/' in "/usr") or
if (((i == 2) && (dirPath[1] ==':')) || (i == 0)) i++; // part of a drive root (e.g. "C:\"), include it with the result.
if ((i == 0) || ((i == 2) && (dirPath[1] == ':'))) i += 1;
// If this character is a trailing path separator (e.g. the last
// '/' in "/usr/bin/" or the last '\' in "C:\raylib\"), continue.
else if (i == lastIndex) continue;
strncpy(prevDirPath, dirPath, i); if (!isFile)
{
memcpy(prevDirPath, dirPath, i);
break; break;
} }
else isFile = false;
}
} }
return prevDirPath; return prevDirPath;
@ -2608,7 +2616,7 @@ const char *GetWorkingDirectory(void)
static char currentDir[MAX_FILEPATH_LENGTH] = { 0 }; static char currentDir[MAX_FILEPATH_LENGTH] = { 0 };
memset(currentDir, 0, MAX_FILEPATH_LENGTH); memset(currentDir, 0, MAX_FILEPATH_LENGTH);
char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH - 1); char *path = GETCWD(currentDir, MAX_FILEPATH_LENGTH);
return path; return path;
} }
@ -2816,23 +2824,61 @@ int MakeDirectory(const char *dirPath)
} }
// Change working directory, returns true on success // Change working directory, returns true on success
bool ChangeDirectory(const char *dirPath) int ChangeDirectory(const char *dirPath)
{ {
bool result = CHDIR(dirPath); // NOTE: On success, CHDIR() return 0; on error, returns -1 and errno is set to indicate the error,
// depending on the filesystem, other errors can be returned
int result = CHDIR(dirPath);
if (result != 0) TRACELOG(LOG_WARNING, "SYSTEM: Failed to change to directory: %s", dirPath); if (result != 0) TRACELOG(LOG_WARNING, "SYSTEM: Failed to change to directory: %s", dirPath);
else TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", dirPath); else TRACELOG(LOG_INFO, "SYSTEM: Working Directory: %s", dirPath);
return (result == 0); return result;
} }
// Check if a given path point to a file // Check if provided path point to a file
bool IsPathFile(const char *path) bool IsPathFile(const char *path)
{ {
struct stat result = { 0 }; bool result = false;
stat(path, &result);
return S_ISREG(result.st_mode); struct stat info = { 0 };
stat(path, &info);
if (S_ISREG(info.st_mode)) result = true;
return result;
}
// Check if provided path point to a directory
bool IsPathDirectory(const char *path)
{
bool result = false;
if (!IsPathFile(path)) result = true;
return result;
}
// Check if provided path is an absolute path
bool IsPathAbsolute(const char *path)
{
int result = false;
if ((path != NULL) && (path[0] != '\0'))
{
#if defined(_WIN32)
// Check UNC path (\\server\share)
if ((path[0] == '\\') && (path[1] == '\\')) result = true;
// Check path starts with a drive letter (e.g. C:\ or D:/)
else if ((((path[0] >= 'A') && (path[0] <= 'Z')) || ((path[0] >= 'a') && (path[0] <= 'z'))) &&
(path[1] != '\0') && (path[1] == ':') && (path[2] != '\0') && ((path[2] == '\\') || (path[2] == '/'))) result = true;
#else
// Check POSIX path, must start with /
if (path[0] == '/') result = true;
#endif
}
return result;
} }
// Check if fileName is valid for the platform/OS // Check if fileName is valid for the platform/OS
@ -2891,7 +2937,7 @@ bool IsFileNameValid(const char *fileName)
return valid; return valid;
} }
// Check if a file has been dropped into window // Check if file has been dropped into window
bool IsFileDropped(void) bool IsFileDropped(void)
{ {
bool result = false; bool result = false;
@ -2955,9 +3001,9 @@ unsigned int GetDirectoryFileCountEx(const char *basePath, const char *filter, b
{ {
// Construct new path from our base path // Construct new path from our base path
#if defined(_WIN32) #if defined(_WIN32)
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, entity->d_name); int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, entity->d_name);
#else #else
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, entity->d_name); int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, entity->d_name);
#endif #endif
// Don't add to count if path too long // Don't add to count if path too long
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
@ -3160,7 +3206,7 @@ unsigned char *DecodeDataBase64(const char *text, int *outputSize)
} }
// Compute CRC32 hash code // Compute CRC32 hash code
unsigned int ComputeCRC32(unsigned char *data, int dataSize) unsigned int ComputeCRC32(const unsigned char *data, int dataSize)
{ {
static unsigned int crcTable[256] = { static unsigned int crcTable[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
@ -3206,7 +3252,7 @@ unsigned int ComputeCRC32(unsigned char *data, int dataSize)
// Compute MD5 hash code // Compute MD5 hash code
// NOTE: Returns a static int[4] array (16 bytes) // NOTE: Returns a static int[4] array (16 bytes)
unsigned int *ComputeMD5(unsigned char *data, int dataSize) unsigned int *ComputeMD5(const unsigned char *data, int dataSize)
{ {
#define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) #define ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
@ -3266,7 +3312,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer memcpy(msg + newDataSize, &bitsLen, 4); // Append the len in bits at the end of the buffer
// Process the message in successive 512-bit chunks for each 512-bit chunk of message // Process the message in successive 512-bit chunks for each 512-bit chunk of message
for (int offset = 0; offset < newDataSize; offset += (512/8)) for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
{ {
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int *w = (unsigned int *)(msg + offset); unsigned int *w = (unsigned int *)(msg + offset);
@ -3324,7 +3370,7 @@ unsigned int *ComputeMD5(unsigned char *data, int dataSize)
// Compute SHA-1 hash code // Compute SHA-1 hash code
// NOTE: Returns a static int[5] array (20 bytes) // NOTE: Returns a static int[5] array (20 bytes)
unsigned int *ComputeSHA1(unsigned char *data, int dataSize) unsigned int *ComputeSHA1(const unsigned char *data, int dataSize)
{ {
#define SHA1_ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c)))) #define SHA1_ROTATE_LEFT(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
@ -3352,27 +3398,27 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
memcpy(msg, data, dataSize); memcpy(msg, data, dataSize);
msg[dataSize] = 128; // Write the '1' bit msg[dataSize] = 128; // Write the '1' bit
unsigned long long bitsLen = 8ULL * dataSize; unsigned long long bitsLen = 8ULL*dataSize;
msg[newDataSize-1] = (unsigned char)(bitsLen); msg[newDataSize - 1] = (unsigned char)(bitsLen);
msg[newDataSize-2] = (unsigned char)(bitsLen >> 8); msg[newDataSize - 2] = (unsigned char)(bitsLen >> 8);
msg[newDataSize-3] = (unsigned char)(bitsLen >> 16); msg[newDataSize - 3] = (unsigned char)(bitsLen >> 16);
msg[newDataSize-4] = (unsigned char)(bitsLen >> 24); msg[newDataSize - 4] = (unsigned char)(bitsLen >> 24);
msg[newDataSize-5] = (unsigned char)(bitsLen >> 32); msg[newDataSize - 5] = (unsigned char)(bitsLen >> 32);
msg[newDataSize-6] = (unsigned char)(bitsLen >> 40); msg[newDataSize - 6] = (unsigned char)(bitsLen >> 40);
msg[newDataSize-7] = (unsigned char)(bitsLen >> 48); msg[newDataSize - 7] = (unsigned char)(bitsLen >> 48);
msg[newDataSize-8] = (unsigned char)(bitsLen >> 56); msg[newDataSize - 8] = (unsigned char)(bitsLen >> 56);
// Process the message in successive 512-bit chunks // Process the message in successive 512-bit chunks
for (int offset = 0; offset < newDataSize; offset += (512/8)) for (int offset = 0; offset < newDataSize; offset += 64) // 512/8
{ {
// Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15 // Break chunk into sixteen 32-bit words w[j], 0 <= j <= 15
unsigned int w[80] = { 0 }; unsigned int w[80] = { 0 };
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
w[i] = (msg[offset + (i*4) + 0] << 24) | w[i] = ((unsigned int)msg[offset + (i*4) + 0] << 24) |
(msg[offset + (i*4) + 1] << 16) | ((unsigned int)msg[offset + (i*4) + 1] << 16) |
(msg[offset + (i*4) + 2] << 8) | ((unsigned int)msg[offset + (i*4) + 2] << 8) |
(msg[offset + (i*4) + 3]); ((unsigned int)msg[offset + (i*4) + 3]);
} }
// Message schedule: extend the sixteen 32-bit words into eighty 32-bit words: // Message schedule: extend the sixteen 32-bit words into eighty 32-bit words:
@ -3434,7 +3480,7 @@ unsigned int *ComputeSHA1(unsigned char *data, int dataSize)
// Compute SHA-256 hash code // Compute SHA-256 hash code
// NOTE: Returns a static int[8] array (32 bytes) // NOTE: Returns a static int[8] array (32 bytes)
unsigned int *ComputeSHA256(unsigned char *data, int dataSize) unsigned int *ComputeSHA256(const unsigned char *data, int dataSize)
{ {
#define SHA256_ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int)*8) - c))) #define SHA256_ROTATE_RIGHT(x, c) ((x >> c) | (x << ((sizeof(unsigned int)*8) - c)))
#define SHA256_A0(x) (SHA256_ROTATE_RIGHT(x, 7) ^ SHA256_ROTATE_RIGHT(x, 18) ^ (x >> 3)) #define SHA256_A0(x) (SHA256_ROTATE_RIGHT(x, 7) ^ SHA256_ROTATE_RIGHT(x, 18) ^ (x >> 3))
@ -3469,8 +3515,8 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
hash[6] = 0x1f83d9ab; hash[6] = 0x1f83d9ab;
hash[7] = 0x5be0cd19; hash[7] = 0x5be0cd19;
const unsigned long long int bitLen = ((unsigned long long int)dataSize)*8; const unsigned long long bitLen = 8ULL*dataSize;
unsigned long long int paddedSize = dataSize + sizeof(dataSize); unsigned long long paddedSize = dataSize + sizeof(dataSize);
paddedSize += (64 - (paddedSize%64)); paddedSize += (64 - (paddedSize%64));
unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char)); unsigned char *buffer = (unsigned char *)RL_CALLOC(paddedSize, sizeof(unsigned char));
@ -3481,7 +3527,7 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF; buffer[(paddedSize - sizeof(bitLen)) + (i - 1)] = (bitLen >> (8*(sizeof(bitLen) - i))) & 0xFF;
} }
for (unsigned long long int blockN = 0; blockN < paddedSize/64; blockN++) for (unsigned long long blockN = 0; blockN < paddedSize/64; blockN++)
{ {
unsigned int a = hash[0]; unsigned int a = hash[0];
unsigned int b = hash[1]; unsigned int b = hash[1];
@ -3503,7 +3549,7 @@ unsigned int *ComputeSHA256(unsigned char *data, int dataSize)
} }
for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16]; for (int t = 16; t < 64; t++) w[t] = SHA256_A1(w[t - 2]) + w[t - 7] + SHA256_A0(w[t - 15]) + w[t - 16];
for (unsigned long long int t = 0; t < 64; t++) for (int t = 0; t < 64; t++)
{ {
unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25)); unsigned int e1 = (SHA256_ROTATE_RIGHT(e, 6) ^ SHA256_ROTATE_RIGHT(e, 11) ^ SHA256_ROTATE_RIGHT(e, 25));
unsigned int ch = ((e & f) ^ (~e & g)); unsigned int ch = ((e & f) ^ (~e & g));
@ -3594,10 +3640,14 @@ AutomationEventList LoadAutomationEventList(const char *fileName)
case 'c': sscanf(buffer, "c %i", &list.count); break; case 'c': sscanf(buffer, "c %i", &list.count); break;
case 'e': case 'e':
{ {
sscanf(buffer, "e %d %d %d %d %d %d %[^\n]s", &list.events[counter].frame, &list.events[counter].type, if (counter < list.capacity)
{
sscanf(buffer, "e %d %d %d %d %d %d %63[^\n]s", &list.events[counter].frame, &list.events[counter].type,
&list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc); &list.events[counter].params[0], &list.events[counter].params[1], &list.events[counter].params[2], &list.events[counter].params[3], eventDesc);
counter++; counter++;
}
else TRACELOG(LOG_WARNING, "AUTOMATION: Event goes beyond automated list capacity (MAX: %u): %s", list.capacity, buffer);
} break; } break;
default: break; default: break;
} }
@ -3802,7 +3852,7 @@ void PlayAutomationEvent(AutomationEvent event)
// Module Functions Definition: Input Handling: Keyboard // Module Functions Definition: Input Handling: Keyboard
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Check if a key has been pressed once // Check if key has been pressed once
bool IsKeyPressed(int key) bool IsKeyPressed(int key)
{ {
bool pressed = false; bool pressed = false;
@ -3815,7 +3865,7 @@ bool IsKeyPressed(int key)
return pressed; return pressed;
} }
// Check if a key has been pressed again // Check if key has been pressed again
bool IsKeyPressedRepeat(int key) bool IsKeyPressedRepeat(int key)
{ {
bool repeat = false; bool repeat = false;
@ -3828,7 +3878,7 @@ bool IsKeyPressedRepeat(int key)
return repeat; return repeat;
} }
// Check if a key is being pressed (key held down) // Check if key is being pressed (key held down)
bool IsKeyDown(int key) bool IsKeyDown(int key)
{ {
bool down = false; bool down = false;
@ -3841,7 +3891,7 @@ bool IsKeyDown(int key)
return down; return down;
} }
// Check if a key has been released once // Check if key has been released once
bool IsKeyReleased(int key) bool IsKeyReleased(int key)
{ {
bool released = false; bool released = false;
@ -3854,7 +3904,7 @@ bool IsKeyReleased(int key)
return released; return released;
} }
// Check if a key is NOT being pressed (key not held down) // Check if key is NOT being pressed (key not held down)
bool IsKeyUp(int key) bool IsKeyUp(int key)
{ {
bool up = false; bool up = false;
@ -3925,12 +3975,12 @@ void SetExitKey(int key)
// NOTE: Functions with a platform-specific implementation on rcore_<platform>.c // NOTE: Functions with a platform-specific implementation on rcore_<platform>.c
//int SetGamepadMappings(const char *mappings) //int SetGamepadMappings(const char *mappings)
// Check if a gamepad is available // Check if gamepad is available
bool IsGamepadAvailable(int gamepad) bool IsGamepadAvailable(int gamepad)
{ {
bool result = false; bool result = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad]) result = true; if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad]) result = true;
return result; return result;
} }
@ -3938,15 +3988,19 @@ bool IsGamepadAvailable(int gamepad)
// Get gamepad internal name id // Get gamepad internal name id
const char *GetGamepadName(int gamepad) const char *GetGamepadName(int gamepad)
{ {
return CORE.Input.Gamepad.name[gamepad]; const char *name = NULL;
if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS)) name = CORE.Input.Gamepad.name[gamepad];
return name;
} }
// Check if a gamepad button has been pressed once // Check if gamepad button has been pressed once
bool IsGamepadButtonPressed(int gamepad, int button) bool IsGamepadButtonPressed(int gamepad, int button)
{ {
bool pressed = false; bool pressed = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS)) if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
{ {
if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 0) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) pressed = true; if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 0) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1)) pressed = true;
} }
@ -3954,12 +4008,12 @@ bool IsGamepadButtonPressed(int gamepad, int button)
return pressed; return pressed;
} }
// Check if a gamepad button is being pressed // Check if gamepad button is being pressed
bool IsGamepadButtonDown(int gamepad, int button) bool IsGamepadButtonDown(int gamepad, int button)
{ {
bool down = false; bool down = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS)) if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
{ {
if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1) down = true; if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 1) down = true;
} }
@ -3967,12 +4021,12 @@ bool IsGamepadButtonDown(int gamepad, int button)
return down; return down;
} }
// Check if a gamepad button has NOT been pressed once // Check if gamepad button has NOT been pressed once
bool IsGamepadButtonReleased(int gamepad, int button) bool IsGamepadButtonReleased(int gamepad, int button)
{ {
bool released = false; bool released = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS)) if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
{ {
if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 1) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) released = true; if ((CORE.Input.Gamepad.previousButtonState[gamepad][button] == 1) && (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0)) released = true;
} }
@ -3980,12 +4034,12 @@ bool IsGamepadButtonReleased(int gamepad, int button)
return released; return released;
} }
// Check if a gamepad button is NOT being pressed // Check if gamepad button is NOT being pressed
bool IsGamepadButtonUp(int gamepad, int button) bool IsGamepadButtonUp(int gamepad, int button)
{ {
bool up = false; bool up = false;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS)) if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS))
{ {
if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0) up = true; if (CORE.Input.Gamepad.currentButtonState[gamepad][button] == 0) up = true;
} }
@ -4003,7 +4057,11 @@ int GetGamepadButtonPressed(void)
// Get gamepad axis count // Get gamepad axis count
int GetGamepadAxisCount(int gamepad) int GetGamepadAxisCount(int gamepad)
{ {
return CORE.Input.Gamepad.axisCount[gamepad]; int result = 0;
if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS)) result = CORE.Input.Gamepad.axisCount[gamepad];
return result;
} }
// Get axis movement vector for a gamepad // Get axis movement vector for a gamepad
@ -4011,7 +4069,7 @@ float GetGamepadAxisMovement(int gamepad, int axis)
{ {
float value = ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))? -1.0f : 0.0f; float value = ((axis == GAMEPAD_AXIS_LEFT_TRIGGER) || (axis == GAMEPAD_AXIS_RIGHT_TRIGGER))? -1.0f : 0.0f;
if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXES)) if ((gamepad >= 0) && (gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXES))
{ {
float movement = (value < 0.0f)? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]); float movement = (value < 0.0f)? CORE.Input.Gamepad.axisState[gamepad][axis] : fabsf(CORE.Input.Gamepad.axisState[gamepad][axis]);
@ -4029,7 +4087,7 @@ float GetGamepadAxisMovement(int gamepad, int axis)
//void SetMousePosition(int x, int y) //void SetMousePosition(int x, int y)
//void SetMouseCursor(int cursor) //void SetMouseCursor(int cursor)
// Check if a mouse button has been pressed once // Check if mouse button has been pressed once
bool IsMouseButtonPressed(int button) bool IsMouseButtonPressed(int button)
{ {
bool pressed = false; bool pressed = false;
@ -4045,7 +4103,7 @@ bool IsMouseButtonPressed(int button)
return pressed; return pressed;
} }
// Check if a mouse button is being pressed // Check if mouse button is being pressed
bool IsMouseButtonDown(int button) bool IsMouseButtonDown(int button)
{ {
bool down = false; bool down = false;
@ -4061,7 +4119,7 @@ bool IsMouseButtonDown(int button)
return down; return down;
} }
// Check if a mouse button has been released once // Check if mouse button has been released once
bool IsMouseButtonReleased(int button) bool IsMouseButtonReleased(int button)
{ {
bool released = false; bool released = false;
@ -4077,7 +4135,7 @@ bool IsMouseButtonReleased(int button)
return released; return released;
} }
// Check if a mouse button is NOT being pressed // Check if mouse button is NOT being pressed
bool IsMouseButtonUp(int button) bool IsMouseButtonUp(int button)
{ {
bool up = false; bool up = false;
@ -4195,7 +4253,7 @@ Vector2 GetTouchPosition(int index)
return position; return position;
} }
// Get touch point identifier for given index // Get touch point identifier for provided index
int GetTouchPointId(int index) int GetTouchPointId(int index)
{ {
int id = -1; int id = -1;
@ -4235,7 +4293,7 @@ void InitTimer(void)
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
{ {
CORE.Time.base = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; CORE.Time.base = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
} }
else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available"); else TRACELOG(LOG_WARNING, "TIMER: Hi-resolution timer not available");
#endif #endif
@ -4283,9 +4341,9 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
{ {
// Construct new path from our base path // Construct new path from our base path
#if defined(_WIN32) #if defined(_WIN32)
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s\\%s", basePath, dp->d_name); int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s\\%s", basePath, dp->d_name);
#else #else
int pathLength = snprintf(path, MAX_FILEPATH_LENGTH - 1, "%s/%s", basePath, dp->d_name); int pathLength = snprintf(path, MAX_FILEPATH_LENGTH, "%s/%s", basePath, dp->d_name);
#endif #endif
if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH)) if ((pathLength < 0) || (pathLength >= MAX_FILEPATH_LENGTH))
@ -4297,7 +4355,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) || if ((filter == NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL) ||
(strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter)) (strstr(filter, FILE_FILTER_TAG_FILE_ONLY) != NULL) || IsFileExtension(path, filter))
{ {
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); memcpy(files->paths[files->count], path, pathLength);
files->count++; files->count++;
} }
} }
@ -4305,7 +4363,7 @@ static void ScanDirectoryFiles(const char *basePath, FilePathList *files, const
{ {
if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL))) if ((filter != NULL) && ((strstr(filter, FILE_FILTER_TAG_DIR_ONLY) != NULL) || (strstr(filter, FILE_FILTER_TAG_ALL) != NULL)))
{ {
strncpy(files->paths[files->count], path, MAX_FILEPATH_LENGTH - 1); memcpy(files->paths[files->count], path, pathLength);
files->count++; files->count++;
} }

View file

@ -59,10 +59,13 @@
// NOTE: Below types are required for standalone usage // NOTE: Below types are required for standalone usage
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Boolean type // Boolean type
#if !defined(__cplusplus)
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) #elif !defined(bool)
typedef enum bool { false = 0, true = !false } bool; typedef enum bool { false = 0, true = !false } bool;
#define RL_BOOL_TYPE
#endif
#endif #endif
#if !defined(RL_VECTOR2_TYPE) #if !defined(RL_VECTOR2_TYPE)
@ -124,7 +127,7 @@ void UpdateGestures(void); // Update gestures detec
#if defined(RGESTURES_STANDALONE) #if defined(RGESTURES_STANDALONE)
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
bool IsGestureDetected(int gesture); // Check if a gesture has been detected bool IsGestureDetected(int gesture); // Check if gesture has been detected
int GetGestureDetected(void); // Get latest detected gesture int GetGestureDetected(void); // Get latest detected gesture
float GetGestureHoldDuration(void); // Get gesture hold time in seconds float GetGestureHoldDuration(void); // Get gesture hold time in seconds
@ -154,8 +157,8 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
extern "C" { // Prevents name mangling of functions extern "C" { // Prevents name mangling of functions
#endif #endif
// Functions required to query time on Windows // Functions required to query time on Windows
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceCounter(unsigned long long *lpPerformanceCount);
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); int __stdcall QueryPerformanceFrequency(unsigned long long *lpFrequency);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
@ -254,7 +257,7 @@ void SetGesturesEnabled(unsigned int flags)
GESTURES.enabledFlags = flags; GESTURES.enabledFlags = flags;
} }
// Check if a gesture have been detected // Check if gesture have been detected
bool IsGestureDetected(unsigned int gesture) bool IsGestureDetected(unsigned int gesture)
{ {
if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true; if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true;
@ -350,7 +353,7 @@ void ProcessGestureEvent(GestureEvent event)
GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y; GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
} }
} }
else if (GESTURES.Touch.pointCount == 2) // Two touch points else if (GESTURES.Touch.pointCount == 2)
{ {
if (event.touchAction == TOUCH_ACTION_DOWN) if (event.touchAction == TOUCH_ACTION_DOWN)
{ {
@ -515,37 +518,36 @@ static double rgGetCurrentTime(void)
time = GetTime(); time = GetTime();
#else #else
#if defined(_WIN32) #if defined(_WIN32)
unsigned long long int clockFrequency, currentTime; unsigned long long clockFrequency = 0;
unsigned long long currentClockTicks = 0;
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation! QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
QueryPerformanceCounter(&currentTime); QueryPerformanceCounter(&currentClockTicks);
time = (double)currentTime/clockFrequency; // Time in seconds time = (double)currentClockTicks/clockFrequency; // Time in seconds
#endif #endif
#if defined(__linux__) #if defined(__linux__)
// NOTE: Only for Linux-based systems // NOTE: Only for Linux-based systems
struct timespec now; struct timespec now = { 0 };
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
time = ((double)nowTime*1e-9); // Time in seconds time = ((double)nanoSeconds*1e-9); // Time in seconds
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
//#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01 //#define CLOCK_REALTIME CALENDAR_CLOCK // returns UTC time since 1970-01-01
//#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time //#define CLOCK_MONOTONIC SYSTEM_CLOCK // returns the time since boot time
clock_serv_t cclock; clock_serv_t cclock = { 0 };
mach_timespec_t now; mach_timespec_t now = { 0 };
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
// NOTE: OS X does not have clock_gettime(), using clock_get_time() // NOTE: OS X does not have clock_gettime(), using clock_get_time()
clock_get_time(cclock, &now); clock_get_time(cclock, &now);
mach_port_deallocate(mach_task_self(), cclock); mach_port_deallocate(mach_task_self(), cclock);
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds unsigned long long nanoSeconds = (unsigned long long)now.tv_sec*1000000000LLU + (unsigned long long)now.tv_nsec;
time = ((double)nowTime*1e-9); // Time in seconds time = ((double)nanoSeconds*1e-9); // Time in seconds
#endif #endif
#endif #endif

View file

@ -77,6 +77,15 @@
#include "external/glfw/src/window.c" #include "external/glfw/src/window.c"
#include "external/glfw/src/input.c" #include "external/glfw/src/input.c"
#include "external/glfw/src/vulkan.c" #include "external/glfw/src/vulkan.c"
#include "external/glfw/src/egl_context.c"
#include "external/glfw/src/osmesa_context.c"
//We need to define this function because GLFW calls it even though raylib does
//not use GLFW's Null platform
GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform)
{
return GLFW_FALSE;
}
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
#include "external/glfw/src/win32_init.c" #include "external/glfw/src/win32_init.c"
@ -87,9 +96,6 @@
#include "external/glfw/src/win32_time.c" #include "external/glfw/src/win32_time.c"
#include "external/glfw/src/win32_thread.c" #include "external/glfw/src/win32_thread.c"
#include "external/glfw/src/wgl_context.c" #include "external/glfw/src/wgl_context.c"
#include "external/glfw/src/egl_context.c"
#include "external/glfw/src/osmesa_context.c"
#endif #endif
#if defined(__linux__) #if defined(__linux__)
@ -100,19 +106,42 @@
#include "external/glfw/src/linux_joystick.c" #include "external/glfw/src/linux_joystick.c"
#include "external/glfw/src/xkb_unicode.c" #include "external/glfw/src/xkb_unicode.c"
#include "external/glfw/src/egl_context.c"
#include "external/glfw/src/osmesa_context.c"
#if defined(_GLFW_WAYLAND) #if defined(_GLFW_WAYLAND)
//These functions need to be temporarily renamed because including
//source files for both Wayland and X11 results in pairs of functions
//with the same name and thus a build error
#define createKeyTables createKeyTablesWayland
#define translateKey translateKeyWayland
#define acquireMonitor acquireMonitorWayland
#define releaseMonitor releaseMonitorWayland
#include "external/glfw/src/wl_init.c" #include "external/glfw/src/wl_init.c"
#include "external/glfw/src/wl_monitor.c" #include "external/glfw/src/wl_monitor.c"
#include "external/glfw/src/wl_window.c" #include "external/glfw/src/wl_window.c"
#undef createKeyTables
#undef translateKey
#undef acquireMonitor
#undef releaseMonitor
#endif #endif
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
//These functions need to be temporarily renamed because including
//source files for both Wayland and X11 results in pairs of functions
//with the same name and thus a build error
#define createKeyTables createKeyTablesX11
#define translateKey translateKeyX11
#define acquireMonitor acquireMonitorX11
#define releaseMonitor releaseMonitorX11
#include "external/glfw/src/x11_init.c" #include "external/glfw/src/x11_init.c"
#include "external/glfw/src/x11_monitor.c" #include "external/glfw/src/x11_monitor.c"
#include "external/glfw/src/x11_window.c" #include "external/glfw/src/x11_window.c"
#include "external/glfw/src/glx_context.c" #include "external/glfw/src/glx_context.c"
#undef createKeyTables
#undef translateKey
#undef acquireMonitor
#undef releaseMonitor
#endif #endif
#endif #endif
@ -128,9 +157,6 @@
#include "external/glfw/src/x11_monitor.c" #include "external/glfw/src/x11_monitor.c"
#include "external/glfw/src/x11_window.c" #include "external/glfw/src/x11_window.c"
#include "external/glfw/src/glx_context.c" #include "external/glfw/src/glx_context.c"
#include "external/glfw/src/egl_context.c"
#include "external/glfw/src/osmesa_context.c"
#endif #endif
#if defined(__APPLE__) #if defined(__APPLE__)
@ -140,9 +166,6 @@
#include "external/glfw/src/cocoa_joystick.m" #include "external/glfw/src/cocoa_joystick.m"
#include "external/glfw/src/cocoa_monitor.m" #include "external/glfw/src/cocoa_monitor.m"
#include "external/glfw/src/cocoa_window.m" #include "external/glfw/src/cocoa_window.m"
#include "external/glfw/src/cocoa_time.c" #include "external/glfw/src/macos_time.c"
#include "external/glfw/src/nsgl_context.m" #include "external/glfw/src/nsgl_context.m"
#include "external/glfw/src/egl_context.c"
#include "external/glfw/src/osmesa_context.c"
#endif #endif

View file

@ -56,8 +56,8 @@
* #define RL_CULL_DISTANCE_NEAR 0.05 // Default projection matrix near cull distance * #define RL_CULL_DISTANCE_NEAR 0.05 // Default projection matrix near cull distance
* #define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance * #define RL_CULL_DISTANCE_FAR 4000.0 // Default projection matrix far cull distance
* *
* When loading a shader, the following vertex attributes and uniform * When loading a shader, the following vertex attributes and uniform location names are tried to be set automatically:
* location names are tried to be set automatically: * WARNING: Pre-defined names can not be changed, they are used by default shaders and all raylib examples shaders, they are just listed here for reference
* *
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION * #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
@ -67,6 +67,8 @@
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2 * #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES * #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS * #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
* #define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM
*
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix * #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
@ -74,6 +76,7 @@
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)))
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color) * #define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
* #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices * #define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices
*
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
* #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2) * #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
@ -324,6 +327,7 @@
#define RL_DRAW_FRAMEBUFFER 0x8CA9 // GL_DRAW_FRAMEBUFFER #define RL_DRAW_FRAMEBUFFER 0x8CA9 // GL_DRAW_FRAMEBUFFER
// Default shader vertex attribute locations // Default shader vertex attribute locations
// NOTE: Locations can be redefined by user if required
#ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION #ifndef RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
#define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0 #define RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
#endif #endif
@ -358,11 +362,13 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#if !defined(__cplusplus)
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800) #if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
#include <stdbool.h> #include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool) && !defined(RL_BOOL_TYPE) #elif !defined(bool)
// Boolean type typedef enum bool { false = 0, true = !false } bool;
typedef enum bool { false = 0, true = !false } bool; #define RL_BOOL_TYPE
#endif
#endif #endif
#if !defined(RL_MATRIX_TYPE) #if !defined(RL_MATRIX_TYPE)
@ -894,7 +900,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
// It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi // It seems OpenGL ES 2.0 instancing entry points are not defined on Raspberry Pi
// provided headers (despite being defined in official Khronos GLES2 headers) // provided headers (despite being defined in official Khronos GLES2 headers)
// TODO: Avoid raylib platform-dependent code on rlgl, it should be a completely portable library // TODO: Avoid raylib platform-dependent code on rlgl, it should be a completely portable library
#if defined(PLATFORM_DRM) #if defined(PLATFORM_DRM) // Use CONFIG_DRM?
typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor);
@ -904,6 +910,7 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#include <stdlib.h> // Required for: calloc(), free() #include <stdlib.h> // Required for: calloc(), free()
#include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading] #include <string.h> // Required for: strcmp(), strlen() [Used in rlglInit(), on extensions loading]
#include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log() #include <math.h> // Required for: sqrtf(), sinf(), cosf(), floor(), log()
#include <limits.h> // Required for: INT_MAX
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
@ -991,65 +998,28 @@ RLAPI void rlLoadDrawQuad(void); // Load and draw a quad
#endif #endif
// Default shader vertex attribute names to set location points // Default shader vertex attribute names to set location points
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION // WARNING: Pre-defined names can not be changed, they are used by default shaders and all raylib examples shaders, they are just listed here for reference
#define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION #define RL_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
#endif #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD #define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
#endif #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES
#endif #define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR #define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM
#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_COLOR
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TANGENT
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD2
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEINDICES "vertexBoneIndices" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEINDICES
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS
#define RL_DEFAULT_SHADER_ATTRIB_NAME_BONEWEIGHTS "vertexBoneWeights" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_BONEWEIGHTS
#endif
#ifndef RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCETRANSFORM "instanceTransform" // Bound by default to shader location: RL_DEFAULT_SHADER_ATTRIB_LOCATION_INSTANCETRANSFORM #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
#endif #define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices (required for GPU skinning)
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MVP #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
#endif #define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW
#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION
#define RL_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL
#define RL_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView))
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR
#define RL_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
#endif
#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
#endif
#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
#endif
#ifndef RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2
#define RL_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
#endif
#ifndef RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES
#define RL_DEFAULT_SHADER_UNIFORM_NAME_BONEMATRICES "boneMatrices" // bone matrices (required for GPU skinning)
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Types and Structures Definition // Module Types and Structures Definition
@ -1235,7 +1205,11 @@ void rlMatrixMode(int mode)
// Push the current matrix into RLGL.State.stack // Push the current matrix into RLGL.State.stack
void rlPushMatrix(void) void rlPushMatrix(void)
{ {
if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE) TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)"); if (RLGL.State.stackCounter >= RL_MAX_MATRIX_STACK_SIZE)
{
TRACELOG(RL_LOG_ERROR, "RLGL: Matrix stack overflow (RL_MAX_MATRIX_STACK_SIZE)");
return;
}
if (RLGL.State.currentMatrixMode == RL_MODELVIEW) if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
{ {
@ -2496,7 +2470,7 @@ void rlLoadExtensions(void *loader)
// NOTE: String duplication rquired because glGetString() returns a const string // NOTE: String duplication rquired because glGetString() returns a const string
int extensionsLength = (int)strlen(extensions); // Get extensions string size in bytes int extensionsLength = (int)strlen(extensions); // Get extensions string size in bytes
char *extensionsDup = (char *)RL_CALLOC(extensionsLength + 1, sizeof(char)); // Allocate space for copy with additional EOL byte char *extensionsDup = (char *)RL_CALLOC(extensionsLength + 1, sizeof(char)); // Allocate space for copy with additional EOL byte
strncpy(extensionsDup, extensions, extensionsLength); snprintf(extensionsDup, extensionsLength, "%s", extensions);
extList[numExt] = extensionsDup; extList[numExt] = extensionsDup;
for (int i = 0; i < extensionsLength; i++) for (int i = 0; i < extensionsLength; i++)
@ -3016,7 +2990,7 @@ void rlDrawRenderBatch(rlRenderBatch *batch)
// NOTE: glMapBuffer() causes sync issue // NOTE: glMapBuffer() causes sync issue
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job // If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job
// To avoid waiting (idle), glBufferData() can bee called first with NULL pointer before glMapBuffer() // To avoid waiting (idle), glBufferData() can be called first with NULL pointer before glMapBuffer()
// Doing that, the previous data in PBO will be discarded and glMapBuffer() returns a new // Doing that, the previous data in PBO will be discarded and glMapBuffer() returns a new
// allocated pointer immediately even if GPU is still working with the previous data // allocated pointer immediately even if GPU is still working with the previous data
@ -3366,8 +3340,15 @@ unsigned int rlLoadTexture(const void *data, int width, int height, int format,
// Texture parameters configuration // Texture parameters configuration
// NOTE: glTexParameteri does NOT affect texture uploading // NOTE: glTexParameteri does NOT affect texture uploading
#if defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_ES2)
// Check if texture is power-of-two (POT)
bool texIsPOT = false;
if (((width > 0) && ((width & (width - 1)) == 0)) &&
((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
if (RLGL.ExtSupported.texNPOT) if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
{ {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
@ -3638,7 +3619,7 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break; case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_ARB; break;
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break; case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_ARB; break;
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break; case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_ARB; break;
#else // defined(GRAPHICS_API_OPENGL_ES2) #else // GRAPHICS_API_OPENGL_ES2
case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float case RL_PIXELFORMAT_UNCOMPRESSED_R16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float case RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: if (RLGL.ExtSupported.texFloat16) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_HALF_FLOAT_OES; break; // NOTE: Requires extension OES_texture_half_float
@ -3768,9 +3749,17 @@ void *rlReadTexturePixels(unsigned int id, int width, int height, int format)
// Attach our texture to FBO // Attach our texture to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0);
#if defined(FBO_READ_TEXTURE_AS_RGBA)
// Reading data as RGBA because FBO texture is configured as RGBA, despite binding another texture format // Reading data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
pixels = RL_CALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8), 1); pixels = RL_CALLOC(rlGetPixelDataSize(width, height, RL_PIXELFORMAT_UNCOMPRESSED_R8G8B8A8), 1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
#else
// Reading data as original texture format, in some platforms (RPI, Wasm) it works
pixels = (unsigned char *)RL_MALLOC(rlGetPixelDataSize(width, height, format));
unsigned int glInternalFormat = 0, glFormat = 0, glType = 0;
rlGetGlTextureFormats(format, &glInternalFormat, &glFormat, &glType);
glReadPixels(0, 0, width, height, glFormat, glType, pixels);
#endif
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -3804,6 +3793,10 @@ unsigned char *rlReadScreenPixels(int width, int height)
{ {
unsigned char *imgData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char)); unsigned char *imgData = (unsigned char *)RL_CALLOC(width*height*4, sizeof(unsigned char));
// NOTE: Buffer retrieved is GL_FRONT in single-buffered configurations
// and GL_BACK in double-buffered configurations, make sure to call it at the end of frame
//glReadBuffer(GL_BACK);
// NOTE: glReadPixels() returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer // NOTE: glReadPixels() returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
// WARNING: Getting alpha channel! Be careful, it can be transparent if not cleared properly! // WARNING: Getting alpha channel! Be careful, it can be transparent if not cleared properly!
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, imgData); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
@ -5248,7 +5241,9 @@ static int rlGetPixelDataSize(int width, int height, int format)
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*8; unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*8;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA: case RL_PIXELFORMAT_COMPRESSED_DXT3_RGBA:
case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA: case RL_PIXELFORMAT_COMPRESSED_DXT5_RGBA:
@ -5257,13 +5252,17 @@ static int rlGetPixelDataSize(int width, int height, int format)
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*16; unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*16;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block case RL_PIXELFORMAT_COMPRESSED_ASTC_8x8_RGBA: // 4 bytes per each 4x4 block
{ {
int blockWidth = (width + 3)/4; int blockWidth = (width + 3)/4;
int blockHeight = (height + 3)/4; int blockHeight = (height + 3)/4;
dataSize = blockWidth*blockHeight*4; unsigned long long dataSizeBytes = (unsigned long long)blockWidth*blockHeight*4;
if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} break; } break;
default: break; default: break;
} }
@ -5272,10 +5271,12 @@ static int rlGetPixelDataSize(int width, int height, int format)
if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) && if ((format >= RL_PIXELFORMAT_UNCOMPRESSED_GRAYSCALE) &&
(format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16)) (format <= RL_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16))
{ {
double bytesPerPixel = (double)bpp/8.0; unsigned long long dataSizeBytes = ((unsigned long long)width*height*bpp) >> 3; // Get size in bytes (dividing by 8)
dataSize = (int)(bytesPerPixel*width*height); // Total data size in bytes if (dataSizeBytes < INT_MAX) dataSize = (int)dataSizeBytes;
} }
if (dataSize == 0) TRACELOG(LOG_WARNING, "Requested image size is larger than 2GB, it can not be allocated");
return dataSize; return dataSize;
} }

Some files were not shown because too many files have changed in this diff Show more