Merge branch 'master' into window-visibility

This commit is contained in:
Ray 2019-01-10 16:57:15 +01:00 committed by GitHub
commit 56173d7cf4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
115 changed files with 19921 additions and 16373 deletions

View file

@ -17,7 +17,7 @@ matrix:
env: ARCH=amd64 INSTALL_GLFW=YES USE_EXTERNAL_GLFW=OFF
sudo: required
- os: linux
env: ARCH=amd64 INSTALL_GLFW=YES OPENAL=ON STATIC=OFF RELEASE=NO
env: ARCH=amd64 INSTALL_GLFW=YES STATIC=OFF RELEASE=NO
sudo: required
- os: linux
env: WAYLAND=ON ARCH=amd64 RELEASE=NO
@ -42,6 +42,9 @@ matrix:
- os: linux
env: ARCH=html5 RELEASE=NO
sudo: required
- os: windows
compiler: gcc
env: ARCH=i386 SHARED=OFF RELEASE=NO
before_script:
@ -49,7 +52,6 @@ before_install:
- if [ -z "$USE_EXTERNAL_GLFW" ]; then export USE_EXTERNAL_GLFW=IF_POSSIBLE; fi
- if [ -z "$SHARED" ]; then export SHARED=ON ; fi
- if [ -z "$STATIC" ]; then export STATIC=ON ; fi
- if [ -z "$OPENAL" ]; then export OPENAL=OFF; fi
- if [[ "$INSTALL_GLFW" == "YES" && "$USE_EXTERNAL_GLFW" != "OFF" ]]; then
export DONT_TEST=1;
fi
@ -101,6 +103,11 @@ before_install:
export RAYLIB_PACKAGE_SUFFIX="-macOS";
if [ "$INSTALL_GLFW" == "YES" ]; then brew update; brew install glfw; fi;
fi
- if [ "$TRAVIS_OS_NAME" == "windows" ]; then
export DONT_TEST=1;
export RAYLIB_PACKAGE_SUFFIX="-windows";
export CMAKE_ARCH_ARGS='-DPLATFORM=Desktop';
fi
- mkdir build
- $RUNNER $CC --version
@ -111,7 +118,7 @@ script:
sudo dpkg -i extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb;
git clone git://anongit.freedesktop.org/wayland/wayland-protocols;
pushd wayland-protocols;
git checkout 1.12 && ./autogen.sh --prefix=/usr && make && sudo make install;
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
popd;
fi
- $RUNNER cmake $CMAKE_ARCH_ARGS
@ -121,10 +128,15 @@ script:
-DUSE_EXTERNAL_GLFW=$USE_EXTERNAL_GLFW
-DUSE_WAYLAND=$WAYLAND
-DINCLUDE_EVERYTHING=ON
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON
..
- $RUNNER make VERBOSE=1
- if [ "$RELEASE" != "NO" ]; then $RUNNER make package; fi
- sudo $RUNNER make install
- $RUNNER cmake --build . --target
- if [ "$RELEASE" != "NO" ]; then $RUNNER cmake --build . --target package; fi
- if [ -n "$RUNNER" ]; then
sudo $RUNNER cmake --build . --target install;
else
$(which sudo) $RUNNER "$(which cmake)" --build . --target install;
fi
- if [ ! "$DONT_TEST" ]; then
pkg-config --static --libs raylib;
nm -g release/libraylib.a | grep glfwGetProcAddress || (echo "libraylib.a doesn't contain GLFW symbols! Aborting..." && false);

View file

@ -61,6 +61,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
- [raylib](https://github.com/raysan5/raylib) : raylib **C/C++** version (default)
- [raylib-lua](https://github.com/raysan5/raylib-lua) : raylib **Lua** binding
- [raylib-lua-ffi](https://github.com/raysan5/raylib/issues/693) : raylib **Lua** ffi binding
- [raylib-go](https://github.com/gen2brain/raylib-go) : raylib **Go** binding
- [raylib-Nim](https://gitlab.com/define-private-public/raylib-Nim) : raylib **Nim** binding
- [cray](https://gitlab.com/Zatherz/cray) - raylib **Crystal** binding
@ -74,7 +75,9 @@ Some people ported raylib to other languages in form of bindings or wrappers to
- [raylib-py](https://github.com/overdev/raylib-py) : raylib **Python** binding
- [raylib-haskell](https://github.com/DevJac/raylib-haskell) : raylib **Haskell** binding
- [raylib-java](https://github.com/XoanaIO/raylib-java) : raylib **Java** binding
- *[raylib flat-assembler Usage example](http://forum.raylib.com/index.php?p=/discussion/comment/425/#Comment_425)*
- [raylib-chaiscript](https://github.com/RobLoach/raylib-chaiscript) : raylib **ChaiScript** binding
- [node-raylib](https://github.com/RobLoach/node-raylib) : **Node.js** raylib binding
- *[raylib flat-assembler Usage example]()*
- *[raylib COBOL Usage example](https://github.com/Martinfx/Cobol/tree/master/OpenCobol/Games/raylib)*
Usually, raylib bindings follow the convention: `raylib-{language}`

View file

@ -149,7 +149,7 @@ On November 2016, only 4 months after raylib 1.5, arrives raylib 1.6. This new v
Complete [raylib Lua binding](https://github.com/raysan5/raylib-lua). All raylib functions plus the +60 code examples have been ported to Lua, now Lua users can enjoy coding videogames in Lua while using all the internal power of raylib. This addition also open the doors to Lua scripting support for a future raylib-based engine, being able to move game logic (Init, Update, Draw, De-Init) to Lua scripts while keep using raylib functionality.
Completely redesigned [audio module](https://github.com/raysan5/raylib/blob/master/src/audio.c). Based on the new direction taken in raylib 1.5, it has been further improved and more functionality added (+20 new functions) to allow raw audio processing and streaming. [FLAC file format support](https://github.com/raysan5/raylib/blob/master/src/external/dr_flac.h) has also been added. In the same line, [OpenAL Soft](https://github.com/kcat/openal-soft) backend is now provided as a static library in Windows to allow static linking and get ride of OpenAL32.dll. Now raylib Windows games are completey self-contained, no external libraries required any more!
Completely redesigned [audio module](https://github.com/raysan5/raylib/blob/master/src/raudio.c). Based on the new direction taken in raylib 1.5, it has been further improved and more functionality added (+20 new functions) to allow raw audio processing and streaming. [FLAC file format support](https://github.com/raysan5/raylib/blob/master/src/external/dr_flac.h) has also been added. In the same line, [OpenAL Soft](https://github.com/kcat/openal-soft) backend is now provided as a static library in Windows to allow static linking and get ride of OpenAL32.dll. Now raylib Windows games are completey self-contained, no external libraries required any more!
[Physac](https://github.com/victorfisac/Physac) module has been moved to its own repository and it has been improved A LOT, actually, library has been completely rewritten from scratch by [@victorfisac](https://github.com/victorfisac), multiple samples have been added together with countless new features to match current standard 2D physic libraries. Results are amazing!

View file

@ -10,7 +10,7 @@ NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames progra
no fancy interface, no visual helpers, no auto-debugging... just coding in the most
pure spartan-programmers way. Are you ready to learn? Jump to [code examples!](http://www.raylib.com/examples.html)
[![Build Status](https://travis-ci.org/raysan5/raylib.svg?branch=develop)](https://travis-ci.org/raysan5/raylib)
[![Build Status](https://travis-ci.org/raysan5/raylib.svg?branch=master)](https://travis-ci.org/raysan5/raylib)
[![https://ci.appveyor.com/api/projects/status/github/raysan5/raylib?svg=true](https://ci.appveyor.com/api/projects/status/github/raysan5/raylib?svg=true)](https://ci.appveyor.com/project/raysan5/raylib)
[![Chat on Discord](https://img.shields.io/discord/308323056592486420.svg?logo=discord)](https://discord.gg/VkzNHUE)
[![License](https://img.shields.io/badge/license-zlib%2Flibpng-blue.svg)](LICENSE.md)
@ -35,7 +35,7 @@ features
raylib uses on its [core](https://github.com/raysan5/raylib/blob/master/src/core.c) module the outstanding [GLFW3](http://www.glfw.org/) library, embedded inside raylib in the form of [rglfw](https://github.com/raysan5/raylib/blob/master/src/rglfw.c) module, avoiding that way external dependencies.
raylib uses on its [audio](https://github.com/raysan5/raylib/blob/master/src/audio.c) module, the amazing [mini_al](https://github.com/dr-soft/mini_al) audio library, single-file header-only and supporting multiple platforms and multiple audio backends.
raylib uses on its [audio](https://github.com/raysan5/raylib/blob/master/src/raudio.c) module, the amazing [mini_al](https://github.com/dr-soft/mini_al) audio library, single-file header-only and supporting multiple platforms and multiple audio backends.
raylib uses internally multiple single-file header-only libraries to support multiple fileformats loading and saving, all those libraries are embedded with raylib and available in [src/external](https://github.com/raysan5/raylib/tree/master/src/external) directory.

View file

@ -52,6 +52,7 @@ if(${PLATFORM} MATCHES "Android")
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_model_shader.c)
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_postprocessing.c)
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_raymarching.c)
list(REMOVE_ITEM example_sources ${CMAKE_CURRENT_SOURCE_DIR}/shaders/shaders_palette_switch.c)
elseif(${PLATFORM} MATCHES "Web")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Os -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1")

View file

@ -118,8 +118,8 @@ endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# Emscripten required variables
EMSDK_PATH = C:/emsdk
EMSCRIPTEN_VERSION = 1.38.20
CLANG_VERSION = e1.38.20_64bit
EMSCRIPTEN_VERSION = 1.38.21
CLANG_VERSION = e1.38.21_64bit
PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64
NODE_VERSION = 8.9.1_64bit
export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH)
@ -130,23 +130,23 @@ endif
# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version.
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),WINDOWS)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/win32/mingw32
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
ifeq ($(PLATFORM_OS),LINUX)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/linux
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
ifeq ($(PLATFORM_OS),OSX)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/osx
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
ifeq ($(PLATFORM_OS),BSD)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/bsd
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/rpi
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/release/libs/html5
RAYLIB_RELEASE_PATH = $(RAYLIB_PATH)/src
endif
# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
@ -249,7 +249,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
# -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter
# --profiling # include information for code profiling
# --preload-file resources # specify a resources folder for data compilation
CFLAGS += -Os -s USE_GLFW=3 -s USE_SDL=2 -s ASSERTIONS=1 -s WASM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1
CFLAGS += -Os -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1
# NOTE: Simple raylib examples are compiled to be interpreter by emterpreter, that way,
# we can compile same code for ALL platforms with no change required, but, working on bigger
@ -407,7 +407,7 @@ EXAMPLES = \
models/models_box_collisions \
models/models_billboard \
models/models_obj_loading \
models/models_obj_viewing \
models/models_obj_viewer \
models/models_heightmap \
models/models_cubicmap \
models/models_mesh_picking \
@ -420,6 +420,7 @@ EXAMPLES = \
shaders/shaders_custom_uniform \
shaders/shaders_postprocessing \
shaders/shaders_raymarching \
shaders/shaders_palette_switch \
audio/audio_sound_loading \
audio/audio_music_stream \
audio/audio_module_playing \

View file

@ -30,11 +30,11 @@ int main()
int screenWidth = 800;
int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X
SetConfigFlags(FLAG_MSAA_4X_HINT); // NOTE: Try to enable MSAA 4X
InitWindow(screenWidth, screenHeight, "raylib [audio] example - module playing (streaming)");
InitAudioDevice(); // Initialize audio device
InitAudioDevice(); // Initialize audio device
Color colors[14] = { ORANGE, RED, GOLD, LIME, BLUE, VIOLET, BROWN, LIGHTGRAY, PINK,
YELLOW, GREEN, SKYBLUE, PURPLE, BEIGE };
@ -52,7 +52,7 @@ int main()
circles[i].color = colors[GetRandomValue(0, 13)];
}
Music xm = LoadMusicStream("resources/mini1111.xm");
Music xm = LoadMusicStream("resources/chiptun1.mod");
PlayMusicStream(xm);

View file

@ -64,7 +64,7 @@ int main()
// Send to material PBR shader camera view position
float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };
SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, 3);
SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3);
//----------------------------------------------------------------------------------
// Draw
@ -148,15 +148,15 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS);
// Setup required shader locations
SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1);
SetShaderValuei(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, 1);
SetShaderValuei(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, 1);
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
SetShaderValue(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, UNIFORM_INT);
SetShaderValue(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, UNIFORM_INT);
Texture2D texHDR = LoadTexture("resources/dresden_square.hdr");
Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE);
mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE);
mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE);
mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE);
mat.maps[MAP_BRDF].texture = GenTextureBRDF(shdrBRDF, BRDF_SIZE);
UnloadTexture(cubemap);
UnloadTexture(texHDR);
@ -174,14 +174,14 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness)
SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR);
// Enable sample usage in shader for assigned textures
SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, 1);
SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, 1);
SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, 1);
SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, 1);
SetShaderValuei(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, 1);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "albedo.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "normals.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "metalness.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "roughness.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
SetShaderValue(mat.shader, GetShaderLocation(mat.shader, "occlusion.useSampler"), (int[1]){ 1 }, UNIFORM_INT);
int renderModeLoc = GetShaderLocation(mat.shader, "renderMode");
SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1);
SetShaderValue(mat.shader, renderModeLoc, (int[1]){ 0 }, UNIFORM_INT);
// Set up material properties color
mat.maps[MAP_ALBEDO].color = albedo;

View file

@ -21,7 +21,7 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing");
// Define the camera to look into our 3d world
Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 4.0f, 1.0f, 4.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f, 0 };
// Load skybox model
Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f);
@ -30,11 +30,11 @@ int main()
// Load skybox shader and set required locations
// NOTE: Some locations are automatically set at shader loading
skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs");
SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1);
SetShaderValue(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, UNIFORM_INT);
// Load cubemap shader and setup required shader locations
Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs");
SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1);
SetShaderValue(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, UNIFORM_INT);
// Load HDR panorama (sphere) texture
Texture2D texHDR = LoadTexture("resources/dresden_square.hdr");

View file

@ -1,12 +1,15 @@
/*******************************************************************************************
*
* rPBR [shader] - Bidirectional reflectance distribution function fragment shader
* BRDF LUT Generation - Bidirectional reflectance distribution function fragment shader
*
* REF: https://github.com/HectorMF/BRDFGenerator
*
* Copyright (c) 2017 Victor Fisac
*
**********************************************************************************************/
#version 330
#define MAX_SAMPLES 1024u
// Input vertex attributes (from vertex shader)
@ -18,43 +21,30 @@ const float PI = 3.14159265359;
// Output fragment color
out vec4 finalColor;
float DistributionGGX(vec3 N, vec3 H, float roughness);
float RadicalInverse_VdC(uint bits);
vec2 Hammersley(uint i, uint N);
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
float RadicalInverseVdC(uint bits);
float GeometrySchlickGGX(float NdotV, float roughness);
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);
vec2 IntegrateBRDF(float NdotV, float roughness);
float DistributionGGX(vec3 N, vec3 H, float roughness)
float RadicalInverseVdC(uint bits)
{
float a = roughness*roughness;
float a2 = a*a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH;
float nom = a2;
float denom = (NdotH2*(a2 - 1.0) + 1.0);
denom = PI*denom*denom;
return nom/denom;
}
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
// Compute Hammersley coordinates
vec2 Hammersley(uint i, uint N)
{
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
return vec2(float(i)/float(N), RadicalInverseVdC(i));
}
// Integrate number of importance samples for (roughness and NoV)
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
{
float a = roughness*roughness;
@ -85,6 +75,7 @@ float GeometrySchlickGGX(float NdotV, float roughness)
return nom/denom;
}
// Compute the geometry term for the BRDF given roughness squared, NoV, NoL
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0);
@ -97,29 +88,31 @@ float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
vec2 IntegrateBRDF(float NdotV, float roughness)
{
vec3 V = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV);
float A = 0.0;
float B = 0.0;
float B = 0.0;
vec3 V = vec3(sqrt(1.0 - NdotV*NdotV), 0.0, NdotV);
vec3 N = vec3(0.0, 0.0, 1.0);
for(uint i = 0u; i < MAX_SAMPLES; i++)
for (int i = 0; i < MAX_SAMPLES; i++)
{
// Generate a sample vector that's biased towards the preferred alignment direction (importance sampling)
vec2 Xi = Hammersley(i, MAX_SAMPLES);
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
vec3 L = normalize(2.0*dot(V, H)*H - V);
float NdotL = max(L.z, 0.0);
float NdotH = max(H.z, 0.0);
float VdotH = max(dot(V, H), 0.0);
vec2 Xi = Hammersley(i, MAX_SAMPLES); // Compute a Hammersely coordinate
vec3 H = ImportanceSampleGGX(Xi, N, roughness); // Integrate number of importance samples for (roughness and NoV)
vec3 L = normalize(2.0*dot(V, H)*H - V); // Compute reflection vector L
float NdotL = max(L.z, 0.0); // Compute normal dot light
float NdotH = max(H.z, 0.0); // Compute normal dot half
float VdotH = max(dot(V, H), 0.0); // Compute view dot half
if (NdotL > 0.0)
{
float G = GeometrySmith(N, V, L, roughness);
float G_Vis = (G*VdotH)/(NdotH*NdotV);
float Fc = pow(1.0 - VdotH, 5.0);
float G = GeometrySmith(N, V, L, roughness); // Compute the geometry term for the BRDF given roughness squared, NoV, NoL
float GVis = (G*VdotH)/(NdotH*NdotV); // Compute the visibility term given G, VoH, NoH, NoV, NoL
float Fc = pow(1.0 - VdotH, 5.0); // Compute the fresnel term given VoH
A += (1.0 - Fc)*G_Vis;
B += Fc*G_Vis;
A += (1.0 - Fc)*GVis; // Sum the result given fresnel, geometry, visibility
B += Fc*GVis;
}
}

View file

@ -9,7 +9,7 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec3 fragPos;
in vec3 fragPosition;
// Input uniform values
uniform sampler2D equirectangularMap;
@ -28,7 +28,7 @@ vec2 SampleSphericalMap(vec3 v)
void main()
{
// Normalize local position
vec2 uv = SampleSphericalMap(normalize(fragPos));
vec2 uv = SampleSphericalMap(normalize(fragPosition));
// Fetch color from texture map
vec3 color = texture(equirectangularMap, uv).rgb;

View file

@ -16,12 +16,12 @@ uniform mat4 projection;
uniform mat4 view;
// Output vertex attributes (to fragment shader)
out vec3 fragPos;
out vec3 fragPosition;
void main()
{
// Calculate fragment position based on model transformations
fragPos = vertexPosition;
fragPosition = vertexPosition;
// Calculate final vertex position
gl_Position = projection*view*vec4(vertexPosition, 1.0);

View file

@ -9,7 +9,7 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec3 fragPos;
in vec3 fragPosition;
// Input uniform values
uniform samplerCube environmentMap;
@ -20,7 +20,7 @@ out vec4 finalColor;
void main()
{
// Fetch color from texture map
vec3 color = texture(environmentMap, fragPos).rgb;
vec3 color = texture(environmentMap, fragPosition).rgb;
// Apply gamma correction
color = color/(color + vec3(1.0));

View file

@ -16,12 +16,12 @@ uniform mat4 projection;
uniform mat4 view;
// Output vertex attributes (to fragment shader)
out vec3 fragPos;
out vec3 fragPosition;
void main()
{
// Calculate fragment position based on model transformations
fragPos = vertexPosition;
fragPosition = vertexPosition;
// Remove translation from the view matrix
mat4 rotView = mat4(mat3(view));

View file

@ -158,20 +158,20 @@ Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shade
void UpdateLightValues(Shader shader, Light light)
{
// Send to shader light enabled state and type
SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1);
SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1);
SetShaderValue(shader, light.enabledLoc, &light.enabled, UNIFORM_INT);
SetShaderValue(shader, light.typeLoc, &light.type, UNIFORM_INT);
// Send to shader light position values
float position[3] = { light.position.x, light.position.y, light.position.z };
SetShaderValue(shader, light.posLoc, position, 3);
SetShaderValue(shader, light.posLoc, position, UNIFORM_VEC3);
// Send to shader light target position values
float target[3] = { light.target.x, light.target.y, light.target.z };
SetShaderValue(shader, light.targetLoc, target, 3);
SetShaderValue(shader, light.targetLoc, target, UNIFORM_VEC3);
// Send to shader light color values
float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 };
SetShaderValue(shader, light.colorLoc, diff, 4);
SetShaderValue(shader, light.colorLoc, diff, UNIFORM_VEC4);
}
#endif // RLIGHTS_IMPLEMENTATION

View file

@ -1,19 +1,19 @@
/*******************************************************************************************
*
* raylib [audio] example - Using audio module as standalone module
* raylib [audio] example - Using raudio module as standalone module
*
* NOTE: This example does not require any graphic device, it can run directly on console.
*
* DEPENDENCIES:
* mini_al.h - Audio device management lib (http://kcat.strangesoft.net/openal.html)
* stb_vorbis.c - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
* stb_vorbis.h - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
* jar_xm.h - XM module file loading
* jar_mod.h - MOD audio file loading
* dr_flac.h - FLAC audio file loading
*
* COMPILATION:
* gcc -c ..\..\src\external\mini_al.c -Wall -I.
* gcc -o audio_standalone.exe audio_standalone.c ..\..\src\audio.c ..\..\src\external\stb_vorbis.c mini_al.o /
* gcc -o audio_standalone.exe audio_standalone.c ..\..\src\raudio.c mini_al.o /
* -I..\..\src -I..\..\src\external -L. -Wall -std=c99 /
* -DAUDIO_STANDALONE -DSUPPORT_FILEFORMAT_WAV -DSUPPORT_FILEFORMAT_OGG
*
@ -22,7 +22,7 @@
* This example is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software:
*
* Copyright (c) 2014-2018 Ramon Santamaria (@raysan5)
* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5)
*
* 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.
@ -41,7 +41,7 @@
*
********************************************************************************************/
#include "audio.h" // Audio library
#include "raudio.h" // raylib audio library
#include <stdio.h> // Required for: printf()

View file

@ -350,9 +350,6 @@ static void GetShaderLightsLocations(Shader shader)
// Set shader uniform values for lights
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0
// TODO: Replace glUniform1i(), glUniform1f(), glUniform3f(), glUniform4f():
//SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
//SetShaderValuei(Shader shader, int uniformLoc, int *value, int size)
static void SetShaderLightsValues(Shader shader)
{
int tempInt[8] = { 0 };
@ -363,20 +360,20 @@ static void SetShaderLightsValues(Shader shader)
if (i < lightsCount)
{
tempInt[0] = lights[i]->enabled;
SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], lights[i]->enabled);
SetShaderValue(shader, lightsLocs[i][0], tempInt, UNIFORM_INT); //glUniform1i(lightsLocs[i][0], lights[i]->enabled);
tempInt[0] = lights[i]->type;
SetShaderValuei(shader, lightsLocs[i][1], tempInt, 1); //glUniform1i(lightsLocs[i][1], lights[i]->type);
SetShaderValue(shader, lightsLocs[i][1], tempInt, UNIFORM_INT); //glUniform1i(lightsLocs[i][1], lights[i]->type);
tempFloat[0] = (float)lights[i]->diffuse.r/255.0f;
tempFloat[1] = (float)lights[i]->diffuse.g/255.0f;
tempFloat[2] = (float)lights[i]->diffuse.b/255.0f;
tempFloat[3] = (float)lights[i]->diffuse.a/255.0f;
SetShaderValue(shader, lightsLocs[i][5], tempFloat, 4);
SetShaderValue(shader, lightsLocs[i][5], tempFloat, UNIFORM_VEC4);
//glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255);
tempFloat[0] = lights[i]->intensity;
SetShaderValue(shader, lightsLocs[i][6], tempFloat, 1);
SetShaderValue(shader, lightsLocs[i][6], tempFloat, UNIFORM_FLOAT);
switch (lights[i]->type)
{
@ -385,10 +382,10 @@ static void SetShaderLightsValues(Shader shader)
tempFloat[0] = lights[i]->position.x;
tempFloat[1] = lights[i]->position.y;
tempFloat[2] = lights[i]->position.z;
SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3);
SetShaderValue(shader, lightsLocs[i][2], tempFloat, UNIFORM_VEC3);
tempFloat[0] = lights[i]->radius;
SetShaderValue(shader, lightsLocs[i][4], tempFloat, 1);
SetShaderValue(shader, lightsLocs[i][4], tempFloat, UNIFORM_FLOAT);
//glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
//glUniform1f(lightsLocs[i][4], lights[i]->radius);
@ -401,7 +398,7 @@ static void SetShaderLightsValues(Shader shader)
tempFloat[0] = direction.x;
tempFloat[1] = direction.y;
tempFloat[2] = direction.z;
SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3);
SetShaderValue(shader, lightsLocs[i][3], tempFloat, UNIFORM_VEC3);
//glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
} break;
@ -410,7 +407,7 @@ static void SetShaderLightsValues(Shader shader)
tempFloat[0] = lights[i]->position.x;
tempFloat[1] = lights[i]->position.y;
tempFloat[2] = lights[i]->position.z;
SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3);
SetShaderValue(shader, lightsLocs[i][2], tempFloat, UNIFORM_VEC3);
//glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
@ -420,11 +417,11 @@ static void SetShaderLightsValues(Shader shader)
tempFloat[0] = direction.x;
tempFloat[1] = direction.y;
tempFloat[2] = direction.z;
SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3);
SetShaderValue(shader, lightsLocs[i][3], tempFloat, UNIFORM_VEC3);
//glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z);
tempFloat[0] = lights[i]->coneAngle;
SetShaderValue(shader, lightsLocs[i][7], tempFloat, 1);
SetShaderValue(shader, lightsLocs[i][7], tempFloat, UNIFORM_FLOAT);
//glUniform1f(lightsLocs[i][7], lights[i]->coneAngle);
} break;
default: break;
@ -433,7 +430,7 @@ static void SetShaderLightsValues(Shader shader)
else
{
tempInt[0] = 0;
SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], 0); // Light disabled
SetShaderValue(shader, lightsLocs[i][0], tempInt, UNIFORM_INT); //glUniform1i(lightsLocs[i][0], 0); // Light disabled
}
}
}

View file

@ -0,0 +1,29 @@
#version 100
precision mediump float;
const int colors = 8;
// Input vertex attributes (from vertex shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform ivec3 palette[colors];
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord) * fragColor;
// Convert the (normalized) texel color RED component (GB would work, too)
// to the palette index by scaling up from [0, 1] to [0, 255].
int index = int(texelColor.r * 255.0);
ivec3 color = palette[index];
// Calculate final fragment color. Note that the palette color components
// are defined in the range [0, 255] and need to be normalized to [0, 1]
// for OpenGL to work.
gl_FragColor = vec4(color / 255.0, texelColor.a);
}

View file

@ -0,0 +1,27 @@
#version 120
const int colors = 8;
// Input fragment attributes (from fragment shader)
varying vec2 fragTexCoord;
varying vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform ivec3 palette[colors];
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord) * fragColor;
// Convert the (normalized) texel color RED component (GB would work, too)
// to the palette index by scaling up from [0, 1] to [0, 255].
int index = int(texelColor.r * 255.0);
ivec3 color = palette[index];
// Calculate final fragment color. Note that the palette color components
// are defined in the range [0, 255] and need to be normalized to [0, 1]
// for OpenGL to work.
gl_FragColor = vec4(color / 255.0, texelColor.a);
}

View file

@ -0,0 +1,30 @@
#version 330
const int colors = 8;
// Input fragment attributes (from fragment shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Input uniform values
uniform sampler2D texture0;
uniform ivec3 palette[colors];
// Output fragment color
out vec4 finalColor;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord)*fragColor;
// Convert the (normalized) texel color RED component (GB would work, too)
// to the palette index by scaling up from [0, 1] to [0, 255].
int index = int(texelColor.r * 255.0);
ivec3 color = palette[index];
// Calculate final fragment color. Note that the palette color components
// are defined in the range [0, 255] and need to be normalized to [0, 1]
// for OpenGL to work.
finalColor = vec4(color / 255.0, texelColor.a);
}

View file

@ -79,7 +79,7 @@ int main()
swirlCenter[1] = screenHeight - mousePosition.y;
// Send new value to the shader to be used on drawing
SetShaderValue(shader, swirlCenterLoc, swirlCenter, 2);
SetShaderValue(shader, swirlCenterLoc, swirlCenter, UNIFORM_VEC2);
UpdateCamera(&camera); // Update camera
//----------------------------------------------------------------------------------

View file

@ -0,0 +1,165 @@
/*******************************************************************************************
*
* raylib [shaders] example - Color palette switch
*
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
* on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
* raylib comes with shaders ready for both versions, check raylib/shaders install folder
*
* This example has been created using raylib 2.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2019 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100
#endif
#define MAX_PALETTES 3
#define COLORS_PER_PALETTE 8
#define VALUES_PER_COLOR 3
static const int palettes[MAX_PALETTES][COLORS_PER_PALETTE*VALUES_PER_COLOR] = {
{
0, 0, 0,
255, 0, 0,
0, 255, 0,
0, 0, 255,
0, 255, 255,
255, 0, 255,
255, 255, 0,
255, 255, 255,
},
{
4, 12, 6,
17, 35, 24,
30, 58, 41,
48, 93, 66,
77, 128, 97,
137, 162, 87,
190, 220, 127,
238, 255, 204,
},
{
21, 25, 26,
138, 76, 88,
217, 98, 117,
230, 184, 193,
69, 107, 115,
75, 151, 166,
165, 189, 194,
255, 245, 247,
}
};
static const char *paletteText[] = {
"3-BIT RGB",
"AMMO-8 (GameBoy-like)",
"RKBV (2-strip film)"
};
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - color palette switch");
// Load shader to be used on some parts drawing
// NOTE 1: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version
// NOTE 2: Defining 0 (NULL) for vertex shader forces usage of internal default vertex shader
Shader shader = LoadShader(0, FormatText("resources/shaders/glsl%i/palette-switch.fs", GLSL_VERSION));
// Get variable (uniform) location on the shader to connect with the program
// NOTE: If uniform variable could not be found in the shader, function returns -1
int paletteLoc = GetShaderLocation(shader, "palette");
// Initial index not set, will be automatically bounded below.
int currentPalette = -1;
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
int paletteIndex = currentPalette;
if (IsKeyPressed(KEY_RIGHT)) paletteIndex++;
else if (IsKeyPressed(KEY_LEFT)) paletteIndex--;
if (paletteIndex >= MAX_PALETTES) paletteIndex = 0;
else if (paletteIndex < 0) paletteIndex = MAX_PALETTES - 1;
// Send new value to the shader to be used on drawing.
// Note that we are sending RGB triplets w/o the alpha channel *only* if the current
// palette index has changed (in order to save performances).
if (currentPalette != paletteIndex)
{
currentPalette = paletteIndex;
SetShaderValueV(shader, paletteLoc, palettes[currentPalette], UNIFORM_IVEC3, COLORS_PER_PALETTE);
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginShaderMode(shader);
// Draw horizontal screen-wide rectangles with increasing "palette index".
// The used palette index is encoded in the RGB components of the pixel.
int linesPerRectangle = screenHeight / COLORS_PER_PALETTE;
int leftover = screenHeight % COLORS_PER_PALETTE;
int y = 0;
for (int i = 0; i < COLORS_PER_PALETTE; ++i)
{
int height = linesPerRectangle;
if (leftover > 0)
{
height += 1;
leftover -= 1;
}
DrawRectangle(0, y, screenWidth, height, (Color){ i, i, i, 255 });
y += height;
}
EndShaderMode();
DrawText("CURRENT PALETTE:", 10, 15, 20, RAYWHITE);
DrawText(paletteText[currentPalette], 240, 15, 20, RED);
DrawText("< >", 540, 10, 30, DARKBLUE);
DrawFPS(700, 15);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadShader(shader); // Unload shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View file

@ -48,7 +48,7 @@ int main()
int resolutionLoc = GetShaderLocation(shader, "resolution");
float resolution[2] = { screenWidth, screenHeight };
SetShaderValue(shader, resolutionLoc, resolution, 2);
SetShaderValue(shader, resolutionLoc, resolution, UNIFORM_VEC2);
float runTime = 0.0f;
@ -70,11 +70,11 @@ int main()
runTime += deltaTime;
// Set shader required uniform values
SetShaderValue(shader, viewEyeLoc, cameraPos, 3);
SetShaderValue(shader, viewCenterLoc, cameraTarget, 3);
SetShaderValue(shader, viewUpLoc, cameraUp, 3);
SetShaderValue(shader, deltaTimeLoc, &deltaTime, 1);
SetShaderValue(shader, runTimeLoc, &runTime, 1);
SetShaderValue(shader, viewEyeLoc, cameraPos, UNIFORM_VEC3);
SetShaderValue(shader, viewCenterLoc, cameraTarget, UNIFORM_VEC3);
SetShaderValue(shader, viewUpLoc, cameraUp, UNIFORM_VEC3);
SetShaderValue(shader, deltaTimeLoc, &deltaTime, UNIFORM_FLOAT);
SetShaderValue(shader, runTimeLoc, &runTime, UNIFORM_FLOAT);
//----------------------------------------------------------------------------------
// Draw

View file

@ -2,7 +2,7 @@
*
* raylib [shapes] example - raylib logo animation
*
* This example has been created using raylib 1.4 (www.raylib.com)
* This example has been created using raylib 2.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
@ -140,7 +140,7 @@ int main()
DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
DrawText(TextSubtext("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
}
else if (state == 4)
{

View file

@ -0,0 +1,120 @@
/*******************************************************************************************
*
* raylib [text] example - Draw text inside a rectangle
*
* This example has been created using raylib 2.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2018 Vlad Adrian (@demizdor)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [text] example - draw text inside a rectangle");
char text[] = "Text cannot escape\tthis container\t...word wrap also works when active so here's\
a long text for testing.\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\
tempor incididunt ut labore et dolore magna aliqua. Nec ullamcorper sit amet risus nullam eget felis eget.";
bool resizing = false;
bool wordWrap = true;
Rectangle container = { 25, 25, screenWidth - 50, screenHeight - 250};
Rectangle resizer = { container.x + container.width - 17, container.y + container.height - 17, 14, 14 };
// Minimum width and heigh for the container rectangle
const int minWidth = 60;
const int minHeight = 60;
const int maxWidth = screenWidth - 50;
const int maxHeight = screenHeight - 160;
Vector2 lastMouse = { 0, 0 }; // Stores last mouse coordinates
Color borderColor = MAROON; // Container border color
Font font = GetFontDefault(); // Get default system font
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyPressed(KEY_SPACE)) wordWrap = !wordWrap;
Vector2 mouse = GetMousePosition();
// Check if the mouse is inside the container and toggle border color
if (CheckCollisionPointRec(mouse, container)) borderColor = Fade(MAROON, 0.4f);
else if (!resizing) borderColor = MAROON;
// Container resizing logic
if (resizing)
{
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) resizing = false;
int width = container.width + (mouse.x - lastMouse.x);
container.width = (width > minWidth)? ((width < maxWidth)? width : maxWidth) : minWidth;
int height = container.height + (mouse.y - lastMouse.y);
container.height = (height > minHeight)? ((height < maxHeight)? height : maxHeight) : minHeight;
}
else
{
// Check if we're resizing
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointRec(mouse, resizer)) resizing = true;
}
// Move resizer rectangle properly
resizer.x = container.x + container.width - 17;
resizer.y = container.y + container.height - 17;
lastMouse = mouse; // Update mouse
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawRectangleLinesEx(container, 3, borderColor); // Draw container border
// Draw text in container (add some padding)
DrawTextRec(font, text,
(Rectangle){ container.x + 4, container.y + 4, container.width - 4, container.height - 4 },
20.0f, 2.0f, wordWrap, GRAY);
DrawRectangleRec(resizer, borderColor); // Draw the resize box
// Draw info
DrawText("Word Wrap: ", 313, screenHeight-115, 20, BLACK);
if (wordWrap) DrawText("ON", 447, screenHeight - 115, 20, RED);
else DrawText("OFF", 447, screenHeight - 115, 20, BLACK);
DrawText("Press [SPACE] to toggle word wrap", 218, screenHeight - 91, 20, GRAY);
DrawRectangle(0, screenHeight - 54, screenWidth, 54, GRAY);
DrawText("Click hold & drag the to resize the container", 155, screenHeight - 38, 20, RAYWHITE);
DrawRectangleRec((Rectangle){ 382, screenHeight - 34, 12, 12 }, MAROON);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -2,7 +2,7 @@
*
* raylib [text] example - Text Writing Animation
*
* This example has been created using raylib 1.4 (www.raylib.com)
* This example has been created using raylib 2.3 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
@ -44,7 +44,7 @@ int main()
ClearBackground(RAYWHITE);
DrawText(SubText(message, 0, framesCounter/10), 210, 160, 20, MAROON);
DrawText(TextSubtext(message, 0, framesCounter/10), 210, 160, 20, MAROON);
DrawText("PRESS [ENTER] to RESTART!", 240, 260, 20, LIGHTGRAY);
DrawText("PRESS [SPACE] to SPEED UP!", 239, 300, 20, LIGHTGRAY);

View file

@ -21,7 +21,7 @@ int main()
InitWindow(screenWidth, screenHeight, "raylib [texture] example - image text drawing");
// TTF Font loading with custom generation parameters
Font font = LoadFontEx("resources/KAISG.ttf", 64, 95, 0);
Font font = LoadFontEx("resources/KAISG.ttf", 64, 0, 0);
Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM)

View file

@ -32,8 +32,8 @@ int main()
UnloadImage(fudesumiRaw); // Unload CPU (RAM) image data
// Generate a checked texture by code (1024x1024 pixels)
int width = 1024;
int height = 1024;
int width = 960;
int height = 480;
// Dynamic memory allocation to store pixels data (Color type)
Color *pixels = (Color *)malloc(width*height*sizeof(Color));
@ -42,8 +42,8 @@ int main()
{
for (int x = 0; x < width; x++)
{
if (((x/32+y/32)/1)%2 == 0) pixels[y*height + x] = ORANGE;
else pixels[y*height + x] = GOLD;
if (((x/32+y/32)/1)%2 == 0) pixels[y*width + x] = ORANGE;
else pixels[y*width + x] = GOLD;
}
}
@ -73,9 +73,9 @@ int main()
DrawTexture(checked, screenWidth/2 - checked.width/2, screenHeight/2 - checked.height/2, Fade(WHITE, 0.5f));
DrawTexture(fudesumi, 430, -30, WHITE);
DrawText("CHECKED TEXTURE ", 84, 100, 30, BROWN);
DrawText("GENERATED by CODE", 72, 164, 30, BROWN);
DrawText("and RAW IMAGE LOADING", 46, 226, 30, BROWN);
DrawText("CHECKED TEXTURE ", 84, 85, 30, BROWN);
DrawText("GENERATED by CODE", 72, 148, 30, BROWN);
DrawText("and RAW IMAGE LOADING", 46, 210, 30, BROWN);
DrawText("(c) Fudesumi sprite by Eiden Marsal", 310, screenHeight - 20, 10, BROWN);

View file

@ -35,7 +35,6 @@ int main()
const int screenHeight = 720;
// Init window
ShowLogo();
InitWindow(screenWidth, screenHeight, "Dr. Turtle & Mr. GAMERA");
// Initialize audio device

View file

@ -50,7 +50,6 @@ int main(void) {
const int screenHeight = 720;
const char windowTitle[30] = "KOALA SEASONS";
//ShowLogo();
//SetConfigFlags(FLAG_FULLSCREEN_MODE);
// Note that windowTitle is ignored on Android

View file

@ -35,13 +35,13 @@
//----------------------------------------------------------------------------------
// Global Variables Definition (local to this module)
//----------------------------------------------------------------------------------
static char *codingWords[MAX_CODING_WORDS] = {
"pollo\0",
"conejo\0",
static char *codingWords[MAX_CODING_WORDS] = {
"pollo\0",
"conejo\0",
"huevo\0",
"nido\0",
"aire\0",
"armario\0",
"nido\0",
"aire\0",
"armario\0",
"agujero\0",
"platano\0",
"pastel\0",
@ -82,21 +82,21 @@ void InitEndingScreen(void)
{
framesCounter = 0;
finishScreen = 0;
rotation = 0.1f;
scale = 0.05f;
state = 0;
texBackground = LoadTexture("resources/textures/ending_background.png");
texVignette = LoadTexture("resources/textures/message_vignette.png");
fxNews = LoadSound("resources/audio/fx_batman.ogg");
missions = LoadMissions("resources/missions.txt");
int wordsCount = missions[currentMission].wordsCount;
strcpy(headline, missions[currentMission].msg); // Base headline
int len = strlen(headline);
// Remove @ from headline
// TODO: Also remove additional spaces
for (int i = 0; i < len; i++)
@ -110,7 +110,7 @@ void InitEndingScreen(void)
{
// WARNING: It fails if the last sentence word has a '.' after space
char *title = StringReplace(headline, messageWords[i].text, codingWords[messageWords[i].id]);
if (title != NULL)
{
strcpy(headline, title); // Base headline updated
@ -118,14 +118,14 @@ void InitEndingScreen(void)
}
}
}
TraceLog(LOG_WARNING, "Titular: %s", headline);
// Generate newspaper with title and subtitle
Image imNewspaper = LoadImage("resources/textures/ending_newspaper.png");
fontNews = LoadFontEx("resources/fonts/Lora-Bold.ttf", 32, 250, 0);
fontNews = LoadFontEx("resources/fonts/Lora-Bold.ttf", 32, 0, 250);
ImageDrawTextEx(&imNewspaper, (Vector2){ 50, 220 }, fontNews, headline, fontNews.baseSize, 0, DARKGRAY);
texNewspaper = LoadTextureFromImage(imNewspaper);
//UnloadFont(fontNews);
UnloadImage(imNewspaper);
@ -135,25 +135,25 @@ void InitEndingScreen(void)
void UpdateEndingScreen(void)
{
framesCounter++;
if (framesCounter == 10) PlaySound(fxNews);
if (state == 0)
{
rotation += 18.0f;
scale += 0.0096f;
if (scale >= 1.0f)
if (scale >= 1.0f)
{
scale = 1.0f;
state = 1;
}
}
if ((state == 1) && (IsKeyPressed(KEY_ENTER) || IsButtonPressed()))
if ((state == 1) && (IsKeyPressed(KEY_ENTER) || IsButtonPressed()))
{
currentMission++;
if (currentMission >= totalMissions) finishScreen = 2;
else finishScreen = 1;
}
@ -163,16 +163,16 @@ void UpdateEndingScreen(void)
void DrawEndingScreen(void)
{
DrawTexture(texBackground, 0, 0, WHITE);
DrawTexturePro(texNewspaper, (Rectangle){ 0, 0, texNewspaper.width, texNewspaper.height },
(Rectangle){ GetScreenWidth()/2, GetScreenHeight()/2, texNewspaper.width*scale, texNewspaper.height*scale },
(Rectangle){ GetScreenWidth()/2, GetScreenHeight()/2, texNewspaper.width*scale, texNewspaper.height*scale },
(Vector2){ (float)texNewspaper.width*scale/2, (float)texNewspaper.height*scale/2 }, rotation, WHITE);
DrawTextureEx(texVignette, (Vector2){ 0, 0 }, 0.0f, 2.0f, WHITE);
// Draw debug information
DrawTextEx(fontNews, headline, (Vector2){ 10, 10 }, fontNews.baseSize, 0, RAYWHITE);
for (int i = 0; i < missions[currentMission].wordsCount; i++)
{
DrawText(codingWords[messageWords[i].id], 10, 60 + 30*i, 20, (messageWords[i].id == missions[currentMission].sols[i]) ? GREEN : RED);
@ -187,9 +187,9 @@ void UnloadEndingScreen(void)
UnloadTexture(texBackground);
UnloadTexture(texNewspaper);
UnloadTexture(texVignette);
UnloadSound(fxNews);
free(missions);
free(missions);
}
// Ending Screen should finish?
@ -213,16 +213,16 @@ static char *StringReplace(char *orig, char *rep, char *with)
// Sanity checks and initialization
if (!orig || !rep) return NULL;
len_rep = strlen(rep);
if (len_rep == 0) return NULL; // Empty rep causes infinite loop during count
if (!with) with = ""; // Replace with nothing if not provided
len_with = strlen(with);
// Count the number of replacements needed
ins = orig;
for (count = 0; tmp = strstr(ins, rep); ++count)
for (count = 0; tmp = strstr(ins, rep); ++count)
{
ins = tmp + len_rep;
}
@ -235,7 +235,7 @@ static char *StringReplace(char *orig, char *rep, char *with)
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while (count--)
while (count--)
{
ins = strstr(orig, rep);
len_front = ins - orig;
@ -243,8 +243,8 @@ static char *StringReplace(char *orig, char *rep, char *with)
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}

View file

@ -35,9 +35,9 @@
#define MAX_LINE_CHAR 30
/*
// NOTE: Coding words are generic and the same words
// are used for all missions,
typedef enum CodingWords {
// NOTE: Coding words are generic and the same words
// are used for all missions,
typedef enum CodingWords {
POLLO = 0,
CONEJO,
HUEVO,
@ -50,13 +50,13 @@ typedef enum CodingWords {
} CodingWords;
*/
static char *codingWords[MAX_CODING_WORDS] = {
"pollo\0",
"conejo\0",
static char *codingWords[MAX_CODING_WORDS] = {
"pollo\0",
"conejo\0",
"huevo\0",
"nido\0",
"aire\0",
"armario\0",
"nido\0",
"aire\0",
"armario\0",
"agujero\0",
"platano\0",
"pastel\0",
@ -125,19 +125,19 @@ void InitGameplayScreen(void)
{
framesCounter = 0;
finishScreen = 0;
fontMessage = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 30, 250, 0);
fontMessage = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 30, 0, 250);
texBackground = LoadTexture("resources/textures/message_background.png");
texVignette = LoadTexture("resources/textures/message_vignette.png");
fxGrab = LoadSound("resources/audio/fx_grab.ogg");
fxPlace = LoadSound("resources/audio/fx_place.ogg");
fxLeave = LoadSound("resources/audio/fx_leave.ogg");
musSpy = LoadMusicStream("resources/audio/s_p_y.xm");
PlayMusicStream(musSpy);
#if defined(PLATFORM_WEB)
#define WORD_ATLAS_FROM_FILE
#endif
@ -147,20 +147,20 @@ void InitGameplayScreen(void)
// Generate coding words atlas directly from text
Image imWordsBase = LoadImage("resources/textures/words_base.png");
Image imWords = GenImageColor(imWordsBase.width, imWordsBase.height*MAX_CODING_WORDS, WHITE);
for (int i = 0; i < MAX_CODING_WORDS; i++)
{
ImageDraw(&imWords, imWordsBase,
ImageDraw(&imWords, imWordsBase,
(Rectangle){ 0, 0, imWordsBase.width, imWordsBase.height },
(Rectangle){ 0, imWordsBase.height*i, imWordsBase.width, imWordsBase.height });
ImageDrawTextEx(&imWords,(Vector2){ imWordsBase.width/2 - MeasureTextEx(fontMessage, codingWords[i],
fontMessage.baseSize, 0).x/2, imWordsBase.height*i }, fontMessage, codingWords[i],
fontMessage.baseSize, 0, BLACK);
ImageDrawTextEx(&imWords,(Vector2){ imWordsBase.width/2 - MeasureTextEx(fontMessage, codingWords[i],
fontMessage.baseSize, 0).x/2, imWordsBase.height*i }, fontMessage, codingWords[i],
fontMessage.baseSize, 0, BLACK);
}
texWordsAtlas = LoadTextureFromImage(imWords);
UnloadImage(imWordsBase);
UnloadImage(imWords);
#endif
@ -183,13 +183,13 @@ void InitGameplayScreen(void)
words[i].iniRec = words[i].rec;
words[i].hover = false; // Mouse hover detected
words[i].picked = false; // Mouse picked
//words[i].text = ''; //codingWords[i]; // Fill text if required...
}
// Analize missions[currentMission].msg string for words!
int msgLen = strlen(missions[currentMission].msg);
// Add '/' each MAX_LINE_CHAR chars
int currentLine = 1;
int i = currentLine * MAX_LINE_CHAR;
@ -203,39 +203,35 @@ void InitGameplayScreen(void)
i = currentLine*MAX_LINE_CHAR;
}
else i++;
}
}
int currentWord = 0;
int offsetX = 0;
int offsetY = 0;
bool foundWord = false;
int wordInitPosX = 0;
int wordInitPosY = 0;
// TODO: messageWords should be reseted every mission
//memcpy(messageWords, 0, sizeof(Word)*MAX_MISSION_WORDS);
for (int i = 0; i < msgLen; i++)
{
{
char c = missions[currentMission].msg[i];
if (foundWord && (c == ' ' || c == '.'))
{
foundWord = false;
messageWords[currentWord - 1].rec.width = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), 30, 0).x;
messageWords[currentWord - 1].rec.width = (int)MeasureTextEx(fontMessage, TextSubtext(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), 30, 0).x;
messageWords[currentWord - 1].rec.height = fontMessage.baseSize;
//TODO: Guardar en message
strncpy(messageWords[currentWord - 1].text, SubText(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), i - wordInitPosX);
strncpy(messageWords[currentWord - 1].text, TextSubtext(missions[currentMission].msg, wordInitPosX, (i - wordInitPosX)), i - wordInitPosX);
}
if (c == '@') // One word to change
{
foundWord = true;
missions[currentMission].msg[i] = ' ';
offsetX = (int)MeasureTextEx(fontMessage, SubText(missions[currentMission].msg, wordInitPosY, (i + 1) - wordInitPosY), 30, 0).x;
offsetX = (int)MeasureTextEx(fontMessage, TextSubtext(missions[currentMission].msg, wordInitPosY, (i + 1) - wordInitPosY), 30, 0).x;
messageWords[currentWord].rec.x = offsetX;
messageWords[currentWord].rec.y = offsetY;
@ -254,16 +250,16 @@ void InitGameplayScreen(void)
for (int i = 0; i < missions[currentMission].wordsCount; i++)
{
messageWords[i].id = -1; // Not required for message words, id is the array position
// Recalculate words rectangles considering text offset on screen
messageWords[i].rec.x += msgOffset.x;
messageWords[i].rec.y += msgOffset.y;
// Recalculate words rectangle considering new width height
messageWords[i].rec.x -= (texWordsAtlas.width - messageWords[i].rec.width)/2;
messageWords[i].rec.y -= ((texWordsAtlas.height / MAX_CODING_WORDS) - messageWords[i].rec.height)/2;
//Recalculate width height
//Recalculate width height
messageWords[i].rec.width = texWordsAtlas.width;
messageWords[i].rec.height = texWordsAtlas.height / MAX_CODING_WORDS;
@ -276,13 +272,13 @@ void InitGameplayScreen(void)
void UpdateGameplayScreen(void)
{
UpdateMusicStream(musSpy);
for (int i = 0; i < MAX_CODING_WORDS; i++)
{
if (CheckCollisionPointRec(GetMousePosition(), words[i].rec))
{
words[i].hover = true;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
words[i].picked = true;
@ -290,41 +286,41 @@ void UpdateGameplayScreen(void)
}
}
else words[i].hover = false;
if (words[i].picked)
{
{
for (int j = 0; j < missions[currentMission].wordsCount; j++)
{
{
if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec)) messageWords[j].hover = true;
else messageWords[j].hover = false;
}
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
{
{
words[i].picked = false;
for (int j = 0; j < missions[currentMission].wordsCount; j++)
{
{
messageWords[j].hover = false;
if (CheckCollisionPointRec(GetMousePosition(), messageWords[j].rec))
{
PlaySound(fxPlace);
words[i].rec.x = messageWords[j].rec.x;
words[i].rec.y = messageWords[j].rec.y;
if (messageWords[j].id != -1)
{
int id = messageWords[j].id;
words[id].rec = words[id].iniRec;
}
messageWords[j].id = i;
for (int k = 0; k < missions[currentMission].wordsCount; k++)
{
if (j != k && messageWords[j].id == messageWords[k].id)
if (j != k && messageWords[j].id == messageWords[k].id)
{
messageWords[k].id = -1;
break;
@ -332,60 +328,53 @@ void UpdateGameplayScreen(void)
}
break;
}
else
else
{
PlaySound(fxLeave);
words[i].rec = words[i].iniRec;
if (i == messageWords[j].id) messageWords[j].id = -1;
}
}
}
}
}
}
// TODO: Move word picked with mouse
// Move word picked with mouse
if (words[i].picked)
{
words[i].rec.x = GetMouseX() - words[i].rec.width/2;
words[i].rec.y = GetMouseY() - words[i].rec.height/2;
// TODO: Check if label is placed in some mission word position
//if (CheckCollisionRecs(words[i].rec))
}
else
{
//if (words[i].id != -1)
}
}
canSend = true;
for(int j = 0; j < missions[currentMission].wordsCount; j++)
{
if(messageWords[j].id == -1)
for (int j = 0; j < missions[currentMission].wordsCount; j++)
{
if (messageWords[j].id == -1)
{
canSend = false;
break;
}
}
if (canSend && (IsKeyPressed(KEY_ENTER) || IsButtonPressed()))
{
if (canSend && (IsKeyPressed(KEY_ENTER) || IsButtonPressed()))
{
finishScreen = true;
}
}
}
// Gameplay Screen Draw logic
void DrawGameplayScreen(void)
{
DrawTexture(texBackground, 0, 0, WHITE);
DrawTextEx(fontMessage, missions[currentMission].msg, msgOffset, fontMessage.baseSize, 0, BLACK);
for (int i = 0; i < missions[currentMission].wordsCount; i++)
{
Rectangle recLines = messageWords[i].rec;
DrawRectangleLines(recLines.x, recLines.y, recLines.width, recLines.height, Fade(RED, 0.35f));
if(messageWords[i].hover) DrawRectangleRec(messageWords[i].rec, Fade(RED, 0.30f));
if (messageWords[i].hover) DrawRectangleRec(messageWords[i].rec, Fade(RED, 0.30f));
DrawText(FormatText("%i", messageWords[i].id), i*25, 0, 30, RED);
}
for (int i = 0; i < MAX_CODING_WORDS; i++)
@ -394,9 +383,9 @@ void DrawGameplayScreen(void)
else if (words[i].hover) DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, RED);
else DrawTextureRec(texWordsAtlas, (Rectangle){ 0, i*35, 140, 35 }, (Vector2){ words[i].rec.x, words[i].rec.y }, WHITE);
}
DrawTexturePro(texVignette, (Rectangle){0,0,texVignette.width, texVignette.height}, (Rectangle){0,0,GetScreenWidth(), GetScreenHeight()}, (Vector2){0,0}, 0, WHITE);
if (canSend) DrawButton("enviar");
}
@ -406,13 +395,13 @@ void UnloadGameplayScreen(void)
UnloadTexture(texBackground);
UnloadTexture(texVignette);
UnloadTexture(texWordsAtlas);
UnloadSound(fxGrab);
UnloadSound(fxLeave);
UnloadSound(fxPlace);
UnloadMusicStream(musSpy);
free(missions);
}

View file

@ -61,15 +61,15 @@ void InitLogoScreen(void)
// Logo Screen Update logic
void UpdateLogoScreen(void)
{
if(!fadeOut)
if (!fadeOut)
{
fadeValue += 0.02f;
if(fadeValue > 1.01f)
if (fadeValue > 1.01f)
{
fadeValue = 1.0f;
framesCounter++;
if(framesCounter % showLogoFrames == 0)
if ((framesCounter%showLogoFrames) == 0)
{
fadeOut = true;
finishScreen = true;
@ -77,10 +77,7 @@ void UpdateLogoScreen(void)
}
}
if(IsKeyPressed(KEY_ENTER))
{
finishScreen = true;
}
if (IsKeyPressed(KEY_ENTER)) finishScreen = true;
}
// Logo Screen Draw logic

View file

@ -88,34 +88,33 @@ static Music musMission;
// Mission Screen Functions Definition
//----------------------------------------------------------------------------------
static void WriteMissionText();
static void EndWritting();
static void BlinkKeyword();
// Mission Screen Initialization logic
void InitMissionScreen(void)
{
framesCounter = 0;
finishScreen = 0;
fadeButton = 0.80f;
fadeButton = 0.80f;
texBackground = LoadTexture("resources/textures/mission_background.png");
texBackline = LoadTexture("resources/textures/mission_backline.png");
texBackline = LoadTexture("resources/textures/mission_backline.png");
sourceRecBackLine = (Rectangle){0,0,GetScreenWidth(), texBackline.height};
destRecBackLine = (Rectangle){0,0,sourceRecBackLine.width, sourceRecBackLine.height};
fadeBackLine = 0;
fxTransmit = LoadSound("resources/audio/fx_message.ogg");
musMission = LoadMusicStream("resources/audio/music_mission.ogg");
PlayMusicStream(musMission);
// Initialize missions
missions = LoadMissions("resources/missions.txt");
missionMaxLength = strlen(missions[currentMission].brief);
// Insert line breaks every MAX_LINE_CHAR
int currentLine = 1;
int i = currentLine * MAX_LINE_CHAR;
@ -129,35 +128,35 @@ void InitMissionScreen(void)
i = currentLine*MAX_LINE_CHAR;
}
else i++;
}
missionSize = 30;
}
missionSize = 30;
missionLenght = 0;
missionSpeed = 1;
numberColor = RAYWHITE;
missionColor = LIGHTGRAY;
keywordColor = (Color){198, 49, 60, 255}; //RED
numberPosition = (Vector2){150, 185};
missionPosition = (Vector2){numberPosition.x, numberPosition.y + 60};
keywordPosition = (Vector2){missionPosition.x, missionPosition.y + MeasureTextEx(fontMission, missions[currentMission].brief, missionSize, 0).y + 60};
startWritting = false;
writeNumber = false;
writeMission = false;
writeKeyword = false;
writeEnd = false;
writtingMission = false;
showNumberWaitFrames = 30;
showMissionWaitFrames = 60;
showKeywordWaitFrames = 60;
showMissionWaitFrames = 60;
showKeywordWaitFrames = 60;
blinkKeyWord = true;
blinkFrames = 15;
PlaySound(fxTransmit);
}
@ -165,37 +164,52 @@ void InitMissionScreen(void)
void UpdateMissionScreen(void)
{
UpdateMusicStream(musMission);
if (!writeEnd) WriteMissionText();
else BlinkKeyword();
if (!writeEnd) WriteMissionText();
else
{
framesCounter++;
if ((framesCounter%blinkFrames) == 0)
{
framesCounter = 0;
blinkKeyWord = !blinkKeyWord;
}
}
if (showButton)
{
if (IsKeyPressed(KEY_ENTER) || IsButtonPressed())
if (IsKeyPressed(KEY_ENTER) || IsButtonPressed())
{
if (!writeEnd) EndWritting();
if (!writeEnd)
{
writeEnd = true;
writeKeyword = true;
writeNumber = true;
missionLenght = missionMaxLength;
}
else
{
finishScreen = true;
showButton = false;
}
}
}
}
}
// Mission Screen Draw logic
void DrawMissionScreen(void)
{
// TODO: Draw MISSION screen here!
// Draw MISSION screen here!
DrawTexture(texBackground, 0,0, WHITE);
DrawTexturePro(texBackline, sourceRecBackLine, destRecBackLine, (Vector2){0,0},0, Fade(WHITE, fadeBackLine));
if (writeNumber) DrawTextEx(fontMission, FormatText("Filtración #%02i ", currentMission + 1), numberPosition, missionSize + 10, 0, numberColor);
DrawTextEx(fontMission, SubText(missions[currentMission].brief, 0, missionLenght), missionPosition, missionSize, 0, missionColor);
if (writeKeyword && blinkKeyWord) DrawTextEx(fontMission, FormatText("Keyword: %s", missions[currentMission].key), keywordPosition, missionSize + 10, 0, keywordColor);
if (showButton)
{
if (writeNumber) DrawTextEx(fontMission, FormatText("Filtración #%02i ", currentMission + 1), numberPosition, missionSize + 10, 0, numberColor);
DrawTextEx(fontMission, TextSubtext(missions[currentMission].brief, 0, missionLenght), missionPosition, missionSize, 0, missionColor);
if (writeKeyword && blinkKeyWord) DrawTextEx(fontMission, FormatText("Keyword: %s", missions[currentMission].key), keywordPosition, missionSize + 10, 0, keywordColor);
if (showButton)
{
if (!writeEnd) DrawButton("saltar");
else DrawButton("codificar");
}
@ -204,8 +218,8 @@ void DrawMissionScreen(void)
// Mission Screen Unload logic
void UnloadMissionScreen(void)
{
// TODO: Unload MISSION screen variables here!
UnloadTexture(texBackground);
// Unload MISSION screen variables here!
UnloadTexture(texBackground);
UnloadTexture(texBackline);
UnloadSound(fxTransmit);
UnloadMusicStream(musMission);
@ -220,74 +234,58 @@ int FinishMissionScreen(void)
static void WriteMissionText()
{
if(!startWritting)
if (!startWritting)
{
framesCounter++;
if(framesCounter % 60 == 0)
if (framesCounter % 60 == 0)
{
framesCounter = 0;
startWritting = true;
}
}
else if(!writeNumber)
}
else if (!writeNumber)
{
framesCounter++;
fadeBackLine += 0.020f;
if(framesCounter % showNumberWaitFrames == 0)
if (framesCounter % showNumberWaitFrames == 0)
{
framesCounter = 0;
writeNumber = true;
showButton = true;
}
}
else if(!writeMission)
else if (!writeMission)
{
framesCounter ++;
if(framesCounter % showMissionWaitFrames == 0)
if (framesCounter % showMissionWaitFrames == 0)
{
framesCounter = 0;
writeMission = true;
writtingMission = true;
}
}
else if(writeMission && writtingMission)
else if (writeMission && writtingMission)
{
framesCounter++;
if(framesCounter % missionSpeed == 0)
if (framesCounter % missionSpeed == 0)
{
framesCounter = 0;
missionLenght++;
if(missionLenght == missionMaxLength)
missionLenght++;
if (missionLenght == missionMaxLength)
{
writtingMission = false;
}
}
}
else if(!writeKeyword)
else if (!writeKeyword)
{
framesCounter++;
if(framesCounter % showKeywordWaitFrames == 0)
if (framesCounter % showKeywordWaitFrames == 0)
{
framesCounter = 0;
writeKeyword = true;
writeEnd = true;
}
}
}
static void EndWritting()
{
writeEnd = true;
writeKeyword = true;
writeNumber = true;
missionLenght = missionMaxLength;
}
static void BlinkKeyword()
{
framesCounter++;
if(framesCounter % blinkFrames == 0)
{
framesCounter = 0;
blinkKeyWord = !blinkKeyWord;
}
}

View file

@ -137,8 +137,8 @@ void UpdateTitleScreen(void)
void DrawTitleScreen(void)
{
DrawTexture(texBackground, 0,0, WHITE);
DrawTextEx(fontTitle, SubText(textTitle, 0, transmissionLenght), transmissionPosition, titleSize, 0, titleColor);
DrawTextEx(fontTitle, SubText(textTitle, 12, missionLenght), missionPositon, titleSize, 0, titleColor);
DrawTextEx(fontTitle, TextSubtext(textTitle, 0, transmissionLenght), transmissionPosition, titleSize, 0, titleColor);
DrawTextEx(fontTitle, TextSubtext(textTitle, 12, missionLenght), missionPositon, titleSize, 0, titleColor);
DrawButton("start");
}

View file

@ -70,7 +70,7 @@ int main(void)
SetMusicVolume(music, 1.0f);
PlayMusicStream(music);
fontMission = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 64, 250, 0);
fontMission = LoadFontEx("resources/fonts/traveling_typewriter.ttf", 64, 0, 250);
texButton = LoadTexture("resources/textures/title_ribbon.png");
// UI BUTTON

View file

@ -23,14 +23,14 @@ gcc -O2 -c shapes.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c textures.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c text.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c models.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c audio.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c external/stb_vorbis.c -Wall -I.
gcc -O2 -c raudio.c -std=c99 -Wall -DPLATFORM_DESKTOP
gcc -O2 -c external/mini_al.c -Wall -I.
gcc -O2 -c utils.c -std=c99 -Wall -DPLATFORM_DESKTOP
:: .
:: . > Generate raylib library
:: ------------------------------
ar rcs libraylib.a core.o rglfw.o shapes.o textures.o text.o models.o audio.o mini_al.o stb_vorbis.o utils.o
ar rcs libraylib.a core.o rglfw.o shapes.o textures.o text.o models.o raudio.o mini_al.o utils.o
:: .
:: > Installing raylib library
:: -----------------------------

View file

@ -379,6 +379,8 @@ RLAPI Texture2D GetTextureDefault(void); // Get
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
RLAPI void SetShaderValue(Shader shader, int uniformLoc, const float *value, int size); // Set shader uniform value (float)
RLAPI void SetShaderValuei(Shader shader, int uniformLoc, const int *value, int size); // Set shader uniform value (int)
RLAPI void SetShaderValueArray(Shader shader, int uniformLoc, const float *value, int size, int count); // Set shader uniform value (array of float/vec2/vec3/vec4)
RLAPI void SetShaderValueArrayi(Shader shader, int uniformLoc, const int *value, int size, int count); // Set shader uniform value (array of int/ivec2/ivec3/ivec4)
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)

View file

@ -153,7 +153,6 @@
<ItemGroup>
<ClCompile Include="..\..\..\src\audio.c" />
<ClCompile Include="..\..\..\src\core.c" />
<ClCompile Include="..\..\..\src\external\stb_vorbis.c" />
<ClCompile Include="..\..\..\src\models.c" />
<ClCompile Include="..\..\..\src\shapes.c" />
<ClCompile Include="..\..\..\src\text.c" />

View file

@ -235,7 +235,6 @@
<ClCompile Include="..\..\..\src\audio.c" />
<ClCompile Include="..\..\..\src\core.c" />
<ClCompile Include="..\..\..\src\external\mini_al.c" />
<ClCompile Include="..\..\..\src\external\stb_vorbis.c" />
<ClCompile Include="..\..\..\src\models.c" />
<ClCompile Include="..\..\..\src\rglfw.c" />
<ClCompile Include="..\..\..\src\shapes.c" />

View file

@ -162,7 +162,6 @@
<ClCompile Include="..\..\..\src\audio.c" />
<ClCompile Include="..\..\..\src\core.c" />
<ClCompile Include="..\..\..\src\external\mini_al.c" />
<ClCompile Include="..\..\..\src\external\stb_vorbis.c" />
<ClCompile Include="..\..\..\src\models.c" />
<ClCompile Include="..\..\..\src\rglfw.c" />
<ClCompile Include="..\..\..\src\shapes.c" />

View file

@ -19,7 +19,7 @@
},
"osx": {
"args": [
"RAYLIB_PATH=/Users/murray/work/ray/raylib"
"RAYLIB_PATH=<path_to_raylib>/raylib"
],
},
"group": {
@ -42,7 +42,7 @@
},
"osx": {
"args": [
"RAYLIB_PATH=/Users/murray/work/ray/raylib",
"RAYLIB_PATH=<path_to_raylib>/raylib",
],
},
"group": "build"

View file

@ -0,0 +1,68 @@
Here are dependency-less build scripts for raylib projects.
## Dependencies
The scripts, as mentioned above, do not have dependencies. There's one
exception to this however, and that is Windows, because Windows
doesn't have a built-in C compiler. On Windows, you'll need to install
[Visual Studio][visual-studio] or the [build tools][vs-tools]. If you
didn't install them in the default location, write your changes around
line 101 of [`windows-build.bat`](windows-build.bat).
## Script customization
First of all, the scripts have a few variables at the very top, which
are supposed to be configured for each project separately:
- `GAME_NAME` variable is used for the executable name.
- `SOURCES` is a list of .c source files, divided by spaces, which are
going to be compiled and linked with raylib to create the final
executable. You can use wildcards, so if you have all your .c files
in a directory called `src`, you can just set `SOURCES` to
`../../src/*.c`. Note: the paths should be either absolute, or
relative to `builds/platform`, hence `../../`.
- `RAYLIB_SRC` should point to the raylib/src directory. In this case,
it's `../../src`, but as with the `SOURCES`, if the path is
relative, it should be relative to `temp/debug`, so it's actually
`../../../../src`.
## Compilation flags
- `-Os` (`/O1` with MSVC, `-O2` with clang\*) is used for release
builds, to save space. Since it's a good practice to make your games
run on the slowest possible systems, only a few games would benefit
from additional runtime performance on almost all systems. Other
flags: `-flto` (`/GL` and `/LTCG` for MSVC) in release builds, `-O0
-g` (`/Od /Zi` for MSVC) in debug builds.
- `-Wall -Wextra -Wpedantic` (`/Wall` for MSVC) are used for warnings.
\* Clang 7.0.1 seems to have problems compiling with `-flto` and `-Os`
enabled at the same time, so `-Os` is replaced with `-O2` for clang.
## Command line arguments
The build scripts accept some flags, which can be given either one at
a time (`-d -c -r`) or in bunches (`-dcr`). Here's a description of
all of the flags.
- `-h` Describes all the flags, and a few example commands
- `-d` Faster builds that have debug symbols, and enable warnings
- `-u` Run upx\* on the executable after compilation (before -r)
- `-r` Run the executable after compilation
- `-c` Remove the temp/(debug|release) directory, ie. full recompile
- `-q` Suppress this script's informational prints
- `-qq` Suppress all prints, complete silence
- `-v` cl.exe normally prints out a lot of superficial information, as
well as the MSVC build environment activation scripts, but these are
mostly suppressed by default. If you do want to see everything, use
this flag.
\* This is mostly here to make building simple "shipping" versions
easier, and it's a very small bit in the build scripts. The option
requires that you have upx installed and on your path, of course.
#### Examples
| What the command does | Command |
|-------------------------------------------------------------|---------------------------|
| Build a release build, on Windows | `windows-build.bat` |
| Build a release build, full recompile, on Linux | `./linux-build.sh -c` |
| Build a debug build and run, on macOS | `./osx-build.sh -d -r` |
| Build in debug, run, don't print at all, on Linux with `sh` | `sh linux-build.sh -drqq` |
[visual-studio]: https://visualstudio.microsoft.com/downloads/#visual-studio-community-2017
[vs-tools]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2017

View file

@ -0,0 +1,62 @@
/*******************************************************************************************
*
* raylib [core] example - Basic window
*
* Welcome to raylib!
*
* To test examples, just press F6 and execute raylib_compile_execute script
* Note that compiled executable is placed in the same folder as .c file
*
* You can find all basic examples on C:\raylib\raylib\examples folder or
* raylib official webpage: www.raylib.com
*
* Enjoy using raylib. :)
*
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
int main()
{
// Initialization
//--------------------------------------------------------------------------------------
int screenWidth = 800;
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
// TODO: Update your variables here
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

158
projects/scripts/linux-build.sh Executable file
View file

@ -0,0 +1,158 @@
#!/bin/sh
# Change your executable name here
GAME_NAME="game"
# Set your sources here (relative to the ./builds/linux directory)
# Example with two source folders:
# SOURCES="../../src/*.c ../../src/submodule/*.c"
SOURCES="../../core_basic_window.c"
# Set your raylib/src location here, relative to the ./temp/x directory
RAYLIB_SRC="../../../../src"
# About this build script: it does many things, but in essence, it's
# very simple. It has 3 compiler invocations: building raylib (which
# is not done always, see logic by searching "Build raylib"), building
# src/*.c files, and linking together those two. Each invocation is
# wrapped in an if statement to make the -qq flag work, it's pretty
# verbose, sorry.
# Get arguments
while getopts ":hdurcq" opt; do
case $opt in
h)
echo "Usage: ./linux-build.sh [-hdurcqq]"
echo " -h Show this information"
echo " -d Faster builds that have debug symbols, and enable warnings"
echo " -u Run upx* on the executable after compilation (before -r)"
echo " -r Run the executable after compilation"
echo " -c Remove the temp/(debug|release) directory, ie. full recompile"
echo " -q Suppress this script's informational prints"
echo " -qq Suppress all prints, complete silence (> /dev/null 2>&1)"
echo ""
echo "* This is mostly here to make building simple \"shipping\" versions"
echo " easier, and it's a very small bit in the build scripts. The option"
echo " requires that you have upx installed and on your path, of course."
echo ""
echo "Examples:"
echo " Build a release build: ./linux-build.sh"
echo " Build a release build, full recompile: ./linux-build.sh -c"
echo " Build a debug build and run: ./linux-build.sh -d -r"
echo " Build in debug, run, don't print at all: ./linux-build.sh -drqq"
exit 0
;;
d)
BUILD_DEBUG="1"
;;
u)
UPX_IT="1"
;;
r)
RUN_AFTER_BUILD="1"
;;
c)
BUILD_ALL="1"
;;
q)
if [ -n "$QUIET" ]; then
REALLY_QUIET="1"
else
QUIET="1"
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
# Set CC if it's not set already
if [ -z "$CC" ]; then
CC=cc
fi
# Flags
OUTPUT_DIR="builds/linux"
COMPILATION_FLAGS="-std=c99 -Os -flto"
if [ "$CC" = "clang" ]; then
# Clang 7.0.1 fails to compile with -Os, possibly the same bug as this:
# https://www.mail-archive.com/llvm-bugs@lists.llvm.org/msg25771.html
COMPILATION_FLAGS="-std=c99 -O2 -flto"
[ -z "$QUIET" ] && echo "COMPILE-WARNING: \$CC is clang, using -O2 instead of -Os."
fi
FINAL_COMPILE_FLAGS="-s"
WARNING_FLAGS="-Wall -Wextra -Wpedantic"
LINK_FLAGS="-lm -ldl -lpthread -lX11 -lxcb -lGL -lGLX -lXext -lGLdispatch -lXau -lXdmcp"
# Debug changes to flags
if [ -n "$BUILD_DEBUG" ]; then
OUTPUT_DIR="builds-debug/linux"
COMPILATION_FLAGS="-std=c99 -O0 -g"
FINAL_COMPILE_FLAGS=""
fi
# Display what we're doing
if [ -n "$BUILD_DEBUG" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling in debug mode. ($COMPILATION_FLAGS $WARNING_FLAGS)"
else
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling in release mode. ($COMPILATION_FLAGS $FINAL_COMPILE_FLAGS)"
fi
# Create the raylib cache directory
ROOT_DIR=$(pwd)
TEMP_DIR="temp/release"
if [ -n "$BUILD_DEBUG" ]; then
TEMP_DIR="temp/debug"
fi
# If there's a -c flag, remove the cache
if [ -d "$TEMP_DIR" ] && [ -n "$BUILD_ALL" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Found cached raylib, rebuilding."
rm -r "$TEMP_DIR"
fi
# If temp directory doesn't exist, build raylib
if [ ! -d "$TEMP_DIR" ]; then
mkdir -p $TEMP_DIR
cd $TEMP_DIR
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
RAYLIB_C_FILES="$RAYLIB_SRC/core.c $RAYLIB_SRC/shapes.c $RAYLIB_SRC/textures.c $RAYLIB_SRC/text.c $RAYLIB_SRC/models.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c $RAYLIB_SRC/rglfw.c $RAYLIB_SRC/external/mini_al.c"
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
if [ -n "$REALLY_QUIET" ]; then
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS $RAYLIB_C_FILES > /dev/null 2>&1
else
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS $RAYLIB_C_FILES
fi
[ -z "$QUIET" ] && echo "COMPILE-INFO: Raylib compiled into object files in: $TEMP_DIR/"
cd $ROOT_DIR
fi
# Build the actual game
mkdir -p $OUTPUT_DIR
cd $OUTPUT_DIR
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling game code."
if [ -n "$REALLY_QUIET" ]; then
$CC -c -o main.o -I$RAYLIB_SRC $COMPILATION_FLAGS $WARNING_FLAGS $SOURCES > /dev/null 2>&1
$CC -o $GAME_NAME $ROOT_DIR/$TEMP_DIR/*.o main.o $LINK_FLAGS > /dev/null 2>&1
else
$CC -c -o main.o -I$RAYLIB_SRC $COMPILATION_FLAGS $WARNING_FLAGS $SOURCES
$CC -o $GAME_NAME $ROOT_DIR/$TEMP_DIR/*.o main.o $LINK_FLAGS
fi
rm main.o
[ -z "$QUIET" ] && echo "COMPILE-INFO: Game compiled into an executable in: $OUTPUT_DIR/"
if [ -n "$UPX_IT" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Packing $GAME_NAME with upx."
upx $GAME_NAME > /dev/null 2>&1
fi
if [ -n "$RUN_AFTER_BUILD" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Running."
if [ -n "$REALLY_QUIET" ]; then
./$GAME_NAME > /dev/null 2>&1
else
./$GAME_NAME
fi
fi
cd $ROOT_DIR
[ -z "$QUIET" ] && echo "COMPILE-INFO: All done."

154
projects/scripts/osx-build.sh Executable file
View file

@ -0,0 +1,154 @@
#!/bin/sh
# Change your executable name here
GAME_NAME="game"
# Set your sources here (relative to the ./builds/osx directory)
# Example with two source folders:
# SOURCES="../../src/*.c ../../src/submodule/*.c"
SOURCES="../../core_basic_window.c"
# Set your raylib/src location here, relative to the ./temp/x directory
RAYLIB_SRC="../../../../src"
# About this build script: it does many things, but in essence, it's
# very simple. It has 3 compiler invocations: building raylib (which
# is not done always, see logic by searching "Build raylib"), building
# src/*.c files, and linking together those two. Each invocation is
# wrapped in an if statement to make the -qq flag work, it's pretty
# verbose, sorry.
# Get arguments
while getopts ":hdurcq" opt; do
case $opt in
h)
echo "Usage: ./osx-build.sh [-hdurcqq]"
echo " -h Show this information"
echo " -d Faster builds that have debug symbols, and enable warnings"
echo " -u Run upx* on the executable after compilation (before -r)"
echo " -r Run the executable after compilation"
echo " -c Remove the temp/(debug|release) directory, ie. full recompile"
echo " -q Suppress this script's informational prints"
echo " -qq Suppress all prints, complete silence (> /dev/null 2>&1)"
echo ""
echo "* This is mostly here to make building simple \"shipping\" versions"
echo " easier, and it's a very small bit in the build scripts. The option"
echo " requires that you have upx installed and on your path, of course."
echo ""
echo "Examples:"
echo " Build a release build: ./osx-build.sh"
echo " Build a release build, full recompile: ./osx-build.sh -c"
echo " Build a debug build and run: ./osx-build.sh -d -r"
echo " Build in debug, run, don't print at all: ./osx-build.sh -drqq"
exit 0
;;
d)
BUILD_DEBUG="1"
;;
u)
UPX_IT="1"
;;
r)
RUN_AFTER_BUILD="1"
;;
c)
BUILD_ALL="1"
;;
q)
if [ -n "$QUIET" ]; then
REALLY_QUIET="1"
else
QUIET="1"
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
# Set CC if it's not set already
if [ -z "$CC" ]; then
CC=cc
fi
# Flags
OUTPUT_DIR="builds/osx"
COMPILATION_FLAGS="-std=c99 -O2 -flto"
FINAL_COMPILE_FLAGS="-s"
WARNING_FLAGS="-Wall -Wextra -Wpedantic"
LINK_FLAGS="-framework OpenGL -framework OpenAL -framework IOKit -framework CoreVideo -framework Cocoa"
# Debug changes to flags
if [ -n "$BUILD_DEBUG" ]; then
OUTPUT_DIR="builds-debug/osx"
COMPILATION_FLAGS="-std=c99 -O0 -g"
FINAL_COMPILE_FLAGS=""
fi
# Display what we're doing
if [ -n "$BUILD_DEBUG" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling in debug mode. ($COMPILATION_FLAGS $WARNING_FLAGS)"
else
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling in release mode. ($COMPILATION_FLAGS $FINAL_COMPILE_FLAGS)"
fi
# Create the raylib cache directory
ROOT_DIR=$(pwd)
TEMP_DIR="temp/release"
if [ -n "$BUILD_DEBUG" ]; then
TEMP_DIR="temp/debug"
fi
# If there's a -c flag, remove the cache
if [ -d "$TEMP_DIR" ] && [ -n "$BUILD_ALL" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Found cached raylib, rebuilding."
rm -r "$TEMP_DIR"
fi
# If temp directory doesn't exist, build raylib
if [ ! -d "$TEMP_DIR" ]; then
mkdir -p $TEMP_DIR
cd $TEMP_DIR
RAYLIB_DEFINES="-D_DEFAULT_SOURCE -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33"
RAYLIB_C_FILES="$RAYLIB_SRC/core.c $RAYLIB_SRC/shapes.c $RAYLIB_SRC/textures.c $RAYLIB_SRC/text.c $RAYLIB_SRC/models.c $RAYLIB_SRC/utils.c $RAYLIB_SRC/raudio.c $RAYLIB_SRC/external/mini_al.c"
RAYLIB_INCLUDE_FLAGS="-I$RAYLIB_SRC -I$RAYLIB_SRC/external/glfw/include"
if [ -n "$REALLY_QUIET" ]; then
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS -x objective-c $RAYLIB_SRC/rglfw.c > /dev/null 2>&1
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS $RAYLIB_C_FILES > /dev/null 2>&1
else
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS -x objective-c $RAYLIB_SRC/rglfw.c
$CC -c $RAYLIB_DEFINES $RAYLIB_INCLUDE_FLAGS $COMPILATION_FLAGS $RAYLIB_C_FILES
fi
[ -z "$QUIET" ] && echo "COMPILE-INFO: Raylib compiled into object files in: $TEMP_DIR/"
cd $ROOT_DIR
fi
# Build the actual game
mkdir -p $OUTPUT_DIR
cd $OUTPUT_DIR
[ -z "$QUIET" ] && echo "COMPILE-INFO: Compiling game code."
if [ -n "$REALLY_QUIET" ]; then
$CC -c -o main.o -I$RAYLIB_SRC $COMPILATION_FLAGS $WARNING_FLAGS $SOURCES > /dev/null 2>&1
$CC -o $GAME_NAME $ROOT_DIR/$TEMP_DIR/*.o main.o $LINK_FLAGS > /dev/null 2>&1
else
$CC -c -o main.o -I$RAYLIB_SRC $COMPILATION_FLAGS $WARNING_FLAGS $SOURCES
$CC -o $GAME_NAME $ROOT_DIR/$TEMP_DIR/*.o main.o $LINK_FLAGS
fi
rm main.o
[ -z "$QUIET" ] && echo "COMPILE-INFO: Game compiled into an executable in: $OUTPUT_DIR/"
if [ -n "$UPX_IT" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Packing $GAME_NAME with upx."
upx $GAME_NAME > /dev/null 2>&1
fi
if [ -n "$RUN_AFTER_BUILD" ]; then
[ -z "$QUIET" ] && echo "COMPILE-INFO: Running."
if [ -n "$REALLY_QUIET" ]; then
./$GAME_NAME > /dev/null 2>&1
else
./$GAME_NAME
fi
fi
cd $ROOT_DIR
[ -z "$QUIET" ] && echo "COMPILE-INFO: All done."

View file

@ -0,0 +1,211 @@
@echo off
REM Change your executable name here
set GAME_NAME=game.exe
REM Set your sources here (relative to the builds\windows directory)
REM Example with two source folders:
REM set SOURCES=..\..\src\*.c ..\..\src\submodule\*.c
set SOURCES=..\..\core_basic_window.c
REM Set your raylib/src location here, relative to the ./temp/x directory
set RAYLIB_SRC=..\..\..\..\src
REM About this build script: it does many things, but in essence, it's
REM very simple. It has 3 compiler invocations: building raylib (which
REM is not done always, see logic by searching "Build raylib"), building
REM src/*.c files, and linking together those two. Each invocation is
REM wrapped in an if statement to make the -qq flag work, it's pretty
REM verbose, sorry.
REM To skip to the actual building part of the script, search for ":BUILD"
REM For the ! variable notation
setlocal EnableDelayedExpansion
REM For shifting, which the command line argument parsing needs
setlocal EnableExtensions
:ARG_LOOP
set ARG=%1
if "!ARG!" == "" ( goto PREPARE )
IF NOT "x!ARG!" == "x!ARG:h=!" (
goto HELP
)
IF NOT "x!ARG!" == "x!ARG:d=!" (
set BUILD_DEBUG=1
)
IF NOT "x!ARG!" == "x!ARG:u=!" (
set UPX_IT=1
)
IF NOT "x!ARG!" == "x!ARG:r=!" (
set RUN_AFTER_BUILD=1
)
IF NOT "x!ARG!" == "x!ARG:c=!" (
set BUILD_ALL=1
)
IF NOT "x!ARG!" == "x!ARG:qq=!" (
set QUIET=1
set REALLY_QUIET=1
) ELSE IF NOT "x!ARG!" == "x!ARG:q=!" (
IF DEFINED QUIET (
set REALLY_QUIET=1
) ELSE (
set QUIET=1
)
)
IF NOT "x!ARG!" == "x!ARG:v=!" (
set VERBOSE=1
)
IF NOT "%1" == "" (
shift /1
goto ARG_LOOP
)
:HELP
echo Usage: windows-build.bat [-hdurcqqv]
echo -h Show this information
echo -d Faster builds that have debug symbols, and enable warnings
echo -u Run upx* on the executable after compilation (before -r)
echo -r Run the executable after compilation
echo -c Remove the temp\{debug,release} directory, ie. full recompile
echo -q Suppress this script's informational prints
echo -qq Suppress all prints, complete silence
echo -v cl.exe normally prints out a lot of superficial information, as
echo well as the MSVC build environment activation scripts, but these are
echo mostly suppressed by default. If you do want to see everything, use
echo this flag.
echo.
echo * This is mostly here to make building simple "shipping" versions
echo easier, and it's a very small bit in the build scripts. The option
echo requires that you have upx installed and on your path, of course.
echo.
echo Examples:
echo Build a release build: windows-build.bat
echo Build a release build, full recompile: windows-build.bat -c
echo Build a debug build and run: windows-build.bat -d -r
echo Build in debug, run, don't print at all: windows-build.bat -drqq
exit /B
:PREPARE
REM Activate the msvc build environment
IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" (
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat"
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" (
set VC_INIT="C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat"
) ELSE IF EXIST "C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat" (
set VC_INIT="C:\Program Files (x86)\Microsoft Visual C++ Build Tools\vcbuildtools.bat"
) ELSE (
REM Initialize your vc environment here if the defaults don't work
REM set VC_INIT="C:\your\path\here\vcvarsall.bat"
REM And then remove/comment out the following two lines
echo "Couldn't find vcvarsall.bat or vcbuildtools.bat, please set it manually."
exit /B
)
IF DEFINED VERBOSE (
call !VC_INIT! x86
) ELSE (
call !VC_INIT! x86 > NUL 2>&1
)
:BUILD
REM Flags
set OUTPUT_FLAG=/Fe: "!GAME_NAME!"
set COMPILATION_FLAGS=/O1 /GL
set WARNING_FLAGS=
set SUBSYSTEM_FLAGS=/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup
set LINK_FLAGS=/link /LTCG kernel32.lib user32.lib shell32.lib winmm.lib gdi32.lib opengl32.lib
set OUTPUT_DIR=builds\windows
REM Debug changes to flags
IF DEFINED BUILD_DEBUG (
set OUTPUT_FLAG=/Fe: "!GAME_NAME!"
set COMPILATION_FLAGS=/Od /Zi
set WARNING_FLAGS=/Wall
set SUBSYSTEM_FLAGS=
set LINK_FLAGS=/link kernel32.lib user32.lib shell32.lib winmm.lib gdi32.lib opengl32.lib
set OUTPUT_DIR=builds-debug\windows
)
IF NOT DEFINED VERBOSE (
set VERBOSITY_FLAG=/nologo
)
REM Display what we're doing
IF DEFINED BUILD_DEBUG (
IF NOT DEFINED QUIET echo COMPILE-INFO: Compiling in debug mode, flags: !COMPILATION_FLAGS! !WARNING_FLAGS!
) ELSE (
IF NOT DEFINED QUIET echo COMPILE-INFO: Compiling in release mode, flags: !COMPILATION_FLAGS! /link /LTCG
)
REM Create the temp directory for raylib
set "ROOT_DIR=%CD%"
set "TEMP_DIR=temp\release"
IF DEFINED BUILD_DEBUG (
set "TEMP_DIR=temp\debug"
)
IF DEFINED BUILD_ALL (
IF EXIST !TEMP_DIR!\ (
IF NOT DEFINED QUIET echo COMPILE-INFO: Found cached raylib, rebuilding.
del /Q !TEMP_DIR!
rmdir !TEMP_DIR!
)
)
REM Build raylib if it hasn't been cached in TEMP_DIR
IF NOT EXIST !TEMP_DIR!\ (
mkdir !TEMP_DIR!
cd !TEMP_DIR!
REM Raylib's src folder
set "RAYLIB_DEFINES=/D_DEFAULT_SOURCE /DPLATFORM_DESKTOP /DGRAPHICS_API_OPENGL_33"
set RAYLIB_C_FILES="!RAYLIB_SRC!\core.c" "!RAYLIB_SRC!\shapes.c" "!RAYLIB_SRC!\textures.c" "!RAYLIB_SRC!\text.c" "!RAYLIB_SRC!\models.c" "!RAYLIB_SRC!\utils.c" "!RAYLIB_SRC!\raudio.c" "!RAYLIB_SRC!\rglfw.c" "!RAYLIB_SRC!\external\mini_al.c"
set RAYLIB_INCLUDE_FLAGS=/I"!RAYLIB_SRC!" /I"!RAYLIB_SRC!\external\glfw\include"
IF DEFINED REALLY_QUIET (
cl.exe /w /c !RAYLIB_DEFINES! !RAYLIB_INCLUDE_FLAGS! !COMPILATION_FLAGS! !RAYLIB_C_FILES! > NUL 2>&1
) ELSE (
cl.exe /w /c !VERBOSITY_FLAG! !RAYLIB_DEFINES! !RAYLIB_INCLUDE_FLAGS! !COMPILATION_FLAGS! !RAYLIB_C_FILES!
)
IF NOT DEFINED QUIET echo COMPILE-INFO: Raylib compiled into object files in: !TEMP_DIR!\
REM Out of the temp directory
cd !ROOT_DIR!
)
REM Move to the build directory
IF NOT EXIST !OUTPUT_DIR! mkdir !OUTPUT_DIR!
cd !OUTPUT_DIR!
REM Build the actual game
IF NOT DEFINED QUIET echo COMPILE-INFO: Compiling game code.
IF DEFINED REALLY_QUIET (
cl.exe !VERBOSITY_FLAG! /Fo"main.obj" !COMPILATION_FLAGS! !WARNING_FLAGS! /c /I"!RAYLIB_SRC!" !SOURCES! > NUL 2>&1
cl.exe !VERBOSITY_FLAG! !OUTPUT_FLAG! "!ROOT_DIR!\!TEMP_DIR!\*.obj" main.obj !LINK_FLAGS! !SUBSYSTEM_FLAGS! > NUL 2>&1
) ELSE (
cl.exe !VERBOSITY_FLAG! /Fo"main.obj" !COMPILATION_FLAGS! !WARNING_FLAGS! /c /I"!RAYLIB_SRC!" !SOURCES!
cl.exe !VERBOSITY_FLAG! !OUTPUT_FLAG! "!ROOT_DIR!\!TEMP_DIR!\*.obj" main.obj !LINK_FLAGS! !SUBSYSTEM_FLAGS!
)
del main.obj
IF NOT DEFINED QUIET echo COMPILE-INFO: Game compiled into an executable in: !OUTPUT_DIR!\
REM Run upx
IF DEFINED UPX_IT (
IF NOT DEFINED QUIET echo COMPILE-INFO: Packing !GAME_NAME! with upx.
upx !GAME_NAME! > NUL 2>&1
)
REM Finally, run the produced executable
IF DEFINED RUN_AFTER_BUILD (
IF NOT DEFINED QUIET echo COMPILE-INFO: Running.
IF DEFINED REALLY_QUIET (
!GAME_NAME! > NUL 2>&1
) ELSE (
!GAME_NAME!
)
)
REM Back to development directory
cd !ROOT_DIR!
IF NOT DEFINED QUIET echo COMPILE-INFO: All done.

View file

@ -47,12 +47,11 @@ add_definitions("-DRAYLIB_CMAKE=1")
if(USE_AUDIO)
file(GLOB mini_al external/mini_al.c)
MESSAGE(STATUS "Audio Backend: mini_al")
file(GLOB stb_vorbis external/stb_vorbis.c)
set(sources ${raylib_sources} ${mini_al} ${stb_vorbis})
set(sources ${raylib_sources} ${mini_al})
else()
MESSAGE(STATUS "Audio Backend: None (-DUSE_AUDIO=OFF)")
set(INCLUDE_AUDIO_MODULE 0)
list(REMOVE_ITEM raylib_sources ${CMAKE_CURRENT_SOURCE_DIR}/audio.c)
list(REMOVE_ITEM raylib_sources ${CMAKE_CURRENT_SOURCE_DIR}/raudio.c)
set(sources ${raylib_sources})
endif()
@ -251,7 +250,7 @@ file(COPY "raylib.h" DESTINATION ".")
file(COPY "rlgl.h" DESTINATION ".")
file(COPY "physac.h" DESTINATION ".")
file(COPY "raymath.h" DESTINATION ".")
file(COPY "audio.h" DESTINATION ".")
file(COPY "raudio.h" DESTINATION ".")
# Print the flags for the user
message(STATUS "Compiling with the flags:")

View file

@ -61,7 +61,7 @@ option(SUPPORT_FILEFORMAT_OBJ "Support loading OBJ file format" ON)
option(SUPPORT_FILEFORMAT_MTL "Support loading MTL file format" ON)
option(SUPPORT_MESH_GENERATION "Support procedural mesh generation functions, uses external par_shapes.h library. NOTE: Some generated meshes DO NOT include generated texture coordinates" ON)
# audio.c
# raudio.c
option(SUPPORT_FILEFORMAT_WAV "Support loading WAV for sound" ON)
option(SUPPORT_FILEFORMAT_OGG "Support loading OGG for sound" ON)
option(SUPPORT_FILEFORMAT_XM "Support loading XM for sound" ON)

View file

@ -149,8 +149,8 @@ endif
ifeq ($(PLATFORM),PLATFORM_WEB)
# Emscripten required variables
EMSDK_PATH = C:/emsdk
EMSCRIPTEN_VERSION = 1.38.20
CLANG_VERSION = e1.38.20_64bit
EMSCRIPTEN_VERSION ?= 1.38.21
CLANG_VERSION = e$(EMSCRIPTEN_VERSION)_64bit
PYTHON_VERSION = 2.7.13.1_64bit\python-2.7.13.amd64
NODE_VERSION = 8.9.1_64bit
export PATH = $(EMSDK_PATH);$(EMSDK_PATH)\clang\$(CLANG_VERSION);$(EMSDK_PATH)\node\$(NODE_VERSION)\bin;$(EMSDK_PATH)\python\$(PYTHON_VERSION);$(EMSDK_PATH)\emscripten\$(EMSCRIPTEN_VERSION);C:\raylib\MinGW\bin:$$(PATH)
@ -300,7 +300,7 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
# -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing
# -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
# -s USE_PTHREADS=1 # multithreading support
CFLAGS += -s USE_GLFW=3 -s USE_SDL=2 -s ASSERTIONS=1 --profiling
CFLAGS += -s USE_GLFW=3 -s ASSERTIONS=1 --profiling
endif
ifeq ($(PLATFORM),PLATFORM_ANDROID)
# Compiler flags for arquitecture
@ -403,8 +403,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
endif
ifeq ($(INCLUDE_AUDIO_MODULE),TRUE)
OBJS += audio.o
OBJS += stb_vorbis.o
OBJS += raudio.o
OBJS += mini_al.o
endif
@ -530,17 +529,13 @@ models.o : models.c raylib.h rlgl.h raymath.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM) -D$(GRAPHICS)
# Compile audio module
audio.o : audio.c raylib.h
raudio.o : raudio.c raylib.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
# Compile mini_al audio library
mini_al.o : external/mini_al.c external/mini_al.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
# Compile stb_vorbis library
stb_vorbis.o: external/stb_vorbis.c external/stb_vorbis.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
# Compile utils module
utils.o : utils.c utils.h
$(CC) -c $< $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
@ -628,9 +623,9 @@ endif
# Clean everything
clean:
ifeq ($(PLATFORM_OS),WINDOWS)
del *.o $(RAYLIB_RELEASE_PATH)/libraylib.a $(RAYLIB_RELEASE_PATH)/libraylib.bc $(RAYLIB_RELEASE_PATH)/libraylib.so external/stb_vorbis.o
del *.o $(RAYLIB_RELEASE_PATH)/libraylib.a $(RAYLIB_RELEASE_PATH)/libraylib.bc $(RAYLIB_RELEASE_PATH)/libraylib.so
else
rm -fv *.o $(RAYLIB_RELEASE_PATH)/libraylib.a $(RAYLIB_RELEASE_PATH)/libraylib.bc $(RAYLIB_RELEASE_PATH)/libraylib.so* external/stb_vorbis.o
rm -fv *.o $(RAYLIB_RELEASE_PATH)/libraylib.a $(RAYLIB_RELEASE_PATH)/libraylib.bc $(RAYLIB_RELEASE_PATH)/libraylib.so*
endif
ifeq ($(PLATFORM),PLATFORM_ANDROID)
rm -rf $(ANDROID_TOOLCHAIN)

View file

@ -25,7 +25,7 @@
*
**********************************************************************************************/
#define RAYLIB_VERSION "2.2-dev"
#define RAYLIB_VERSION "2.4-dev"
// Edit to control what features Makefile'd raylib is compiled with
#if defined(RAYLIB_CMAKE)

View file

@ -65,7 +65,7 @@
* NOTE: Some generated meshes DO NOT include generated texture coordinates */
#cmakedefine SUPPORT_MESH_GENERATION 1
// audio.c
// raudio.c
/* Desired fileformats to be supported for loading. */
#cmakedefine SUPPORT_FILEFORMAT_WAV 1
#cmakedefine SUPPORT_FILEFORMAT_OGG 1

View file

@ -175,11 +175,9 @@
#include <GLFW/glfw3native.h> // Required for: glfwGetX11Window()
#elif defined(__APPLE__)
#include <unistd.h> // Required for: usleep()
#include <objc/message.h> // Required for: objc_msgsend(), sel_registerName()
//#define GLFW_EXPOSE_NATIVE_COCOA // WARNING: Fails due to type redefinition
#define GLFW_EXPOSE_NATIVE_NSGL
#include <GLFW/glfw3native.h> // Required for: glfwGetCocoaWindow(), glfwGetNSGLContext()
#include <GLFW/glfw3native.h> // Required for: glfwGetCocoaWindow()
#endif
#endif
@ -277,10 +275,6 @@ static bool windowReady = false; // Check if window has been init
static bool windowMinimized = false; // Check if window has been minimized
static const char *windowTitle = NULL; // Window text title...
#if defined(__APPLE__)
static int windowNeedsUpdating = 2; // Times the Cocoa window needs to be updated initially
#endif
static unsigned int displayWidth, displayHeight;// Display width and height (monitor, device-screen, LCD, ...)
static int screenWidth, screenHeight; // Screen width and height (used render area)
static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required)
@ -311,7 +305,7 @@ extern EGLNativeWindowType uwpWindow; // Native EGL window handler for
static struct android_app *androidApp; // Android activity
static struct android_poll_source *source; // Android events polling source
static int ident, events; // Android ALooper_pollAll() variables
static const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files)
static const char *internalDataPath = NULL; // Android internal data path to write data (/data/data/<package>/files)
static bool appEnabled = true; // Used to detec if app is active
static bool contextRebindRequired = false; // Used to know context rebind required
@ -332,8 +326,9 @@ static int defaultKeyboardMode; // Used to store default keyboar
#endif
// Mouse states
static Vector2 mousePosition; // Mouse position on screen
static float mouseScale = 1.0f; // Mouse default scale
static Vector2 mousePosition = { 0.0f, 0.0f }; // Mouse position on screen
static Vector2 mouseScale = { 1.0f, 1.0f }; // Mouse scaling
static Vector2 mouseOffset = { 0.0f, 0.0f }; // Mouse offset
static bool cursorHidden = false; // Track if cursor is hidden
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
@ -1485,12 +1480,6 @@ Color Fade(Color color, float alpha)
return (Color){color.r, color.g, color.b, (unsigned char)(255.0f*alpha)};
}
// Activate raylib logo at startup (can be done with flags)
void ShowLogo(void)
{
showLogo = true;
}
// Setup window configuration flags (view FLAGS)
void SetConfigFlags(unsigned char flags)
{
@ -1503,17 +1492,32 @@ void SetConfigFlags(unsigned char flags)
// NOTE TraceLog() function is located in [utils.h]
// Takes a screenshot of current screen (saved a .png)
// NOTE: This function could work in any platform but some platforms: PLATFORM_ANDROID and PLATFORM_WEB
// have their own internal file-systems, to dowload image to user file-system some additional mechanism is required
void TakeScreenshot(const char *fileName)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
Image image = { imgData, renderWidth, renderHeight, 1, UNCOMPRESSED_R8G8B8A8 };
ExportImage(image, fileName);
free(imgData);
TraceLog(LOG_INFO, "Screenshot taken: %s", fileName);
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, "/");
strcat(path, fileName);
#else
strcpy(path, fileName);
#endif
ExportImage(image, path);
free(imgData);
#if defined(PLATFORM_WEB)
// Download file from MEMFS (emscripten memory filesystem)
// SaveFileFromMEMFSToDisk() function is defined in raylib/templates/web_shel/shell.html
emscripten_run_script(TextFormat("SaveFileFromMEMFSToDisk('%s','%s')", GetFileName(path), GetFileName(path)));
#endif
TraceLog(LOG_INFO, "Screenshot taken: %s", path);
}
// Check if the file exists
@ -1522,11 +1526,10 @@ bool FileExists(const char *fileName)
bool result = false;
#if defined(_WIN32)
if (_access(fileName, 0) != -1)
if (_access(fileName, 0) != -1) result = true;
#else
if (access(fileName, F_OK) != -1)
if (access(fileName, F_OK) != -1) result = true;
#endif
result = true;
return result;
}
@ -1539,7 +1542,7 @@ bool IsFileExtension(const char *fileName, const char *ext)
if ((fileExt = strrchr(fileName, '.')) != NULL)
{
#if defined(_WIN32)
#if defined(_WIN32)
result = true;
int extLen = strlen(ext);
@ -1555,9 +1558,9 @@ bool IsFileExtension(const char *fileName, const char *ext)
}
}
else result = false;
#else
#else
if (strcmp(fileExt, ext) == 0) result = true;
#endif
#endif
}
return result;
@ -1759,7 +1762,7 @@ void StorageSaveValue(int position, int value)
{
FILE *storageFile = NULL;
char path[128];
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, "/");
@ -1799,7 +1802,7 @@ int StorageLoadValue(int position)
{
int value = 0;
char path[128];
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, "/");
@ -1844,7 +1847,9 @@ void OpenURL(const char *url)
if (strchr(url, '\'') != NULL)
{
TraceLog(LOG_WARNING, "Provided URL does not seem to be valid.");
} else {
}
else
{
char *cmd = calloc(strlen(url) + 10, sizeof(char));
#if defined(_WIN32)
@ -2100,7 +2105,7 @@ int GetMouseX(void)
#if defined(PLATFORM_ANDROID)
return (int)touchPosition[0].x;
#else
return (int)(mousePosition.x*mouseScale);
return (int)((mousePosition.x + mouseOffset.x)*mouseScale.x);
#endif
}
@ -2110,7 +2115,7 @@ int GetMouseY(void)
#if defined(PLATFORM_ANDROID)
return (int)touchPosition[0].x;
#else
return (int)(mousePosition.y*mouseScale);
return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y);
#endif
}
@ -2120,27 +2125,32 @@ Vector2 GetMousePosition(void)
#if defined(PLATFORM_ANDROID)
return GetTouchPosition(0);
#else
return (Vector2){ mousePosition.x*mouseScale, mousePosition.y*mouseScale };
return (Vector2){ (mousePosition.x + mouseOffset.x)*mouseScale.x, (mousePosition.y + mouseOffset.y)*mouseScale.y };
#endif
}
// Set mouse position XY
void SetMousePosition(Vector2 position)
void SetMousePosition(int x, int y)
{
mousePosition = position;
mousePosition = (Vector2){ (float)x, (float)y };
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// NOTE: emscripten not implemented
glfwSetCursorPos(window, position.x, position.y);
glfwSetCursorPos(window, mousePosition.x, mousePosition.y);
#endif
}
// Set mouse offset
// NOTE: Useful when rendering to different size targets
void SetMouseOffset(int offsetX, int offsetY)
{
mouseOffset = (Vector2){ (float)offsetX, (float)offsetY };
}
// Set mouse scaling
// NOTE: Useful when rendering to different size targets
void SetMouseScale(float scale)
void SetMouseScale(float scaleX, float scaleY)
{
#if !defined(PLATFORM_ANDROID)
mouseScale = scale;
#endif
mouseScale = (Vector2){ scaleX, scaleY };
}
// Returns mouse wheel movement Y
@ -2278,8 +2288,8 @@ static bool InitGraphicsDevice(int width, int height)
if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GL_FALSE); // Border and buttons on Window
else glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Decorated window
if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window
else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window
// FLAG_WINDOW_TRANSPARENT not supported on HTML5 and not included in any released GLFW version yet
#if defined(GLFW_TRANSPARENT_FRAMEBUFFER)
if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
@ -2295,21 +2305,28 @@ static bool InitGraphicsDevice(int width, int height)
// Check selection OpenGL version
if (rlGetVersion() == OPENGL_21)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // Choose OpenGL minor version (just hint)
}
else if (rlGetVersion() == OPENGL_33)
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // Choose OpenGL major version (just hint)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // Choose OpenGL minor version (just hint)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above!
// Values: GLFW_OPENGL_CORE_PROFILE, GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE
#if defined(__APPLE__)
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires fordward compatibility
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); // OSX Requires fordward compatibility
#else
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE); // Fordward Compatibility Hint: Only 3.3 and above!
#endif
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); // Request OpenGL DEBUG context
//glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); // Request OpenGL DEBUG context
}
else if (rlGetVersion() == OPENGL_ES_20) // Request OpenGL ES 2.0 context
{
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API); // Alternative: GLFW_EGL_CONTEXT_API (ANGLE)
}
if (fullscreen)
@ -2402,7 +2419,9 @@ static bool InitGraphicsDevice(int width, int height)
// Try to disable GPU V-Sync by default, set framerate using SetTargetFPS()
// NOTE: V-Sync can be enabled by graphic driver configuration
#if !defined(PLATFORM_WEB)
glfwSwapInterval(0);
#endif
#if defined(PLATFORM_DESKTOP)
// Load OpenGL 3.3 extensions
@ -3138,16 +3157,6 @@ static void SwapBuffers(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
glfwSwapBuffers(window);
#if __APPLE__
// Workaround for missing/erroneous initial rendering on macOS
if (windowNeedsUpdating)
{
// Desugared version of Objective C: [glfwGetNSGLContext(window) update]
((id (*)(id, SEL))objc_msgSend)(glfwGetNSGLContext(window), sel_registerName("update"));
windowNeedsUpdating--;
}
#endif
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
@ -3173,20 +3182,25 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{
if (key == exitKey && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
glfwSetWindowShouldClose(window, GLFW_TRUE);
// NOTE: Before closing window, while loop must be left!
}
#if defined(PLATFORM_DESKTOP)
else if (key == GLFW_KEY_F12 && action == GLFW_PRESS)
{
#if defined(SUPPORT_GIF_RECORDING)
#if defined(SUPPORT_GIF_RECORDING)
if (mods == GLFW_MOD_CONTROL)
{
if (gifRecording)
{
GifEnd();
gifRecording = false;
#if defined(PLATFORM_WEB)
// Download file from MEMFS (emscripten memory filesystem)
// SaveFileFromMEMFSToDisk() function is defined in raylib/templates/web_shel/shell.html
emscripten_run_script(TextFormat("SaveFileFromMEMFSToDisk('%s','%s')", TextFormat("screenrec%03i.gif", screenshotCounter - 1), TextFormat("screenrec%03i.gif", screenshotCounter - 1)));
#endif
TraceLog(LOG_INFO, "End animated GIF recording");
}
@ -3194,25 +3208,32 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
{
gifRecording = true;
gifFramesCounter = 0;
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
strcpy(path, internalDataPath);
strcat(path, TextFormat("/screenrec%03i.gif", screenshotCounter));
#else
strcpy(path, TextFormat("/screenrec%03i.gif", screenshotCounter));
#endif
// NOTE: delay represents the time between frames in the gif, if we capture a gif frame every
// 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10.
GifBegin(FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
GifBegin(path, screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
screenshotCounter++;
TraceLog(LOG_INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter));
TraceLog(LOG_INFO, "Begin animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
}
}
else
#endif // SUPPORT_GIF_RECORDING
#if defined(SUPPORT_SCREEN_CAPTURE)
#endif // SUPPORT_GIF_RECORDING
#if defined(SUPPORT_SCREEN_CAPTURE)
{
TakeScreenshot(FormatText("screenshot%03i.png", screenshotCounter));
TakeScreenshot(TextFormat("screenshot%03i.png", screenshotCounter));
screenshotCounter++;
}
#endif // SUPPORT_SCREEN_CAPTURE
#endif // SUPPORT_SCREEN_CAPTURE
}
#endif // PLATFORM_DESKTOP
else
{
currentKeyState[key] = action;
@ -3394,11 +3415,11 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Init hi-res timer
InitTimer();
#if defined(SUPPORT_DEFAULT_FONT)
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
// NOTE: External function (defined in module: text)
LoadDefaultFont();
#endif
#endif
// TODO: GPU assets reload in case of lost focus (lost context)
// NOTE: This problem has been solved just unbinding and rebinding context from display
@ -4246,10 +4267,10 @@ static void *EventThread(void *arg)
// Screen confinement
if (mousePosition.x < 0) mousePosition.x = 0;
if (mousePosition.x > screenWidth/mouseScale) mousePosition.x = screenWidth/mouseScale;
if (mousePosition.x > screenWidth/mouseScale.x) mousePosition.x = screenWidth/mouseScale.x;
if (mousePosition.y < 0) mousePosition.y = 0;
if (mousePosition.y > screenHeight/mouseScale) mousePosition.y = screenHeight/mouseScale;
if (mousePosition.y > screenHeight/mouseScale.y) mousePosition.y = screenHeight/mouseScale.y;
// Gesture update
if (GestureNeedsUpdate)
@ -4475,7 +4496,7 @@ static void LogoAnimation(void)
DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
DrawText(TextSubtext("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
}
EndDrawing();

3
src/external/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
glfw/docs/
glfw/examples/
glfw/tests/

View file

@ -65,7 +65,7 @@ script:
sudo dpkg -i extra-cmake-modules_5.38.0a-0ubuntu1_amd64.deb;
git clone git://anongit.freedesktop.org/wayland/wayland-protocols;
pushd wayland-protocols;
git checkout 1.12 && ./autogen.sh --prefix=/usr && make && sudo make install;
git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install;
popd;
fi
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} ..

View file

@ -1,34 +0,0 @@
# FindMir
# -------
# Finds the Mir library
#
# This will will define the following variables::
#
# MIR_FOUND - the system has Mir
# MIR_INCLUDE_DIRS - the Mir include directory
# MIR_LIBRARIES - the Mir libraries
# MIR_DEFINITIONS - the Mir definitions
find_package (PkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
PATHS ${PC_MIR_INCLUDE_DIRS})
find_library(MIR_LIBRARY NAMES mirclient
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (MIR
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
if (MIR_FOUND)
set(MIR_LIBRARIES ${MIR_LIBRARY})
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
set(MIR_DEFINITIONS -DHAVE_MIR=1)
endif()
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
endif()

View file

@ -4,7 +4,7 @@ project(GLFW C)
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
@ -14,7 +14,6 @@ set(GLFW_VERSION_PATCH "0")
set(GLFW_VERSION_EXTRA "")
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
set(LIB_SUFFIX "" CACHE STRING "Takes an empty string or 64. Directory where lib will be installed: lib or lib64")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -25,6 +24,8 @@ option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
option(GLFW_INSTALL "Generate installation target" ON)
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
include(GNUInstallDirs)
if (UNIX)
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
endif()
@ -35,7 +36,6 @@ endif()
if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
endif()
if (MSVC)
@ -141,9 +141,6 @@ endif()
if (GLFW_USE_WAYLAND)
set(_GLFW_WAYLAND 1)
message(STATUS "Using Wayland for window creation")
elseif (GLFW_USE_MIR)
set(_GLFW_MIR 1)
message(STATUS "Using Mir for window creation")
elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation")
@ -262,7 +259,7 @@ if (_GLFW_WAYLAND)
find_package(Wayland REQUIRED Client Cursor Egl)
find_package(WaylandScanner REQUIRED)
find_package(WaylandProtocols 1.12 REQUIRED)
find_package(WaylandProtocols 1.15 REQUIRED)
list(APPEND glfw_PKG_DEPS "wayland-egl")
@ -273,7 +270,9 @@ if (_GLFW_WAYLAND)
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
include(CheckIncludeFiles)
include(CheckFunctionExists)
check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H)
check_function_exists(memfd_create HAVE_MEMFD_CREATE)
if (NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"))
find_package(EpollShim)
@ -284,22 +283,6 @@ if (_GLFW_WAYLAND)
endif()
endif()
#--------------------------------------------------------------------
# Use Mir for window creation
#--------------------------------------------------------------------
if (_GLFW_MIR)
find_package(Mir REQUIRED)
list(APPEND glfw_PKG_DEPS "mirclient")
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
find_package(XKBCommon REQUIRED)
list(APPEND glfw_PKG_DEPS "xkbcommon")
list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}")
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
endif()
#--------------------------------------------------------------------
# Use OSMesa for offscreen context creation
#--------------------------------------------------------------------
@ -340,7 +323,7 @@ endforeach()
#--------------------------------------------------------------------
include(CMakePackageConfigHelpers)
set(GLFW_CONFIG_PATH "lib${LIB_SUFFIX}/cmake/glfw3")
set(GLFW_CONFIG_PATH "${CMAKE_INSTALL_LIBDIR}/cmake/glfw3")
configure_package_config_file(src/glfw3Config.cmake.in
src/glfw3Config.cmake
@ -377,7 +360,7 @@ endif()
# The library is installed by src/CMakeLists.txt
#--------------------------------------------------------------------
if (GLFW_INSTALL)
install(DIRECTORY include/GLFW DESTINATION include
install(DIRECTORY include/GLFW DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h)
install(FILES "${GLFW_BINARY_DIR}/src/glfw3Config.cmake"
@ -388,7 +371,7 @@ if (GLFW_INSTALL)
EXPORT_LINK_INTERFACE_LIBRARIES
DESTINATION "${GLFW_CONFIG_PATH}")
install(FILES "${GLFW_BINARY_DIR}/src/glfw3.pc"
DESTINATION "lib${LIB_SUFFIX}/pkgconfig")
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
# Only generate this target if no higher-level project already has
if (NOT TARGET uninstall)

View file

@ -11,8 +11,8 @@ application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server
are available but not yet officially supported.
An experimental implementation for the Wayland protocol is available but not
yet officially supported.
GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html).
@ -167,6 +167,8 @@ information on what to include when reporting a bug.
(#749,#842)
- Added `GLFW_FOCUS_ON_SHOW` window hint and attribute to control input focus
on calling show window (#1189)
- Added `GLFW_SCALE_TO_MONITOR` window hint for automatic window resizing
(#676,#1115)
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
- Added `GLFW_LOCK_KEY_MODS` input mode and `GLFW_MOD_*_LOCK` mod bits (#946)
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
@ -180,6 +182,10 @@ information on what to include when reporting a bug.
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
- Added `GenerateMappings.cmake` script for updating gamepad mappings
- Export CMake `GLFW_PKG_DEPS` and `GLFW_PKG_LIBS` to parent scope for use
in client pkg-configs (#1307)
- Added a `glfw_objlib` CMake OBJECT library target for embedding into static
libraries (#1307)
- Made `glfwCreateWindowSurface` emit an error when the window has a context
(#1194,#1205)
- Deprecated window parameter of clipboard string functions
@ -195,6 +201,8 @@ information on what to include when reporting a bug.
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
- Bugfix: The scancode for synthetic key release events was always zero
- Bugfix: The generated Doxyfile did not handle paths with spaces (#1081)
- Bugfix: The gamma ramp generated by `glfwSetGamma` did not use the monitor
ramp size (#1387,#1388)
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
- [Win32] Removed XInput circular deadzone from joystick axis data (#1045)
@ -221,6 +229,10 @@ information on what to include when reporting a bug.
- [Win32] Bugfix: The HID device notification was not unregistered (#1170)
- [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED`
hint set to false (#1179,#1180)
- [Win32] Bugfix: The keypad equals key was reported as `GLFW_KEY_UNKNOWN`
(#1315,#1316)
- [Win32] Bugfix: A title bar would be drawn over undecorated windows in some
circumstances (#1383)
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
@ -235,6 +247,8 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT`
- [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8
- [X11] Bugfix: NVidia EGL would segfault if unloaded before closing the display
- [X11] Bugfix: Checking window maximized attrib could crash some WMs (#1356)
- [X11] Bugfix: Update cursor position on enter event (#1366)
- [Linux] Added workaround for missing `SYN_DROPPED` in pre-2.6.39 kernel
headers (#1196)
- [Linux] Moved to evdev for joystick input (#906,#1005)
@ -267,6 +281,9 @@ information on what to include when reporting a bug.
- [Cocoa] Bugfix: Window was resized twice when entering full screen (#1085)
- [Cocoa] Bugfix: Duplicate size events were not filtered (#1085)
- [Cocoa] Bugfix: Event polling did not initialize AppKit if necessary (#1218)
- [Cocoa] Bugfix: OpenGL rendering was not initially visible on 10.14
(#1334,#1346)
- [Cocoa] Bugfix: Caps Lock did not generate any key events (#1368,#1373)
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
- [WGL] Added support for `WGL_ARB_create_context_no_error`
- [GLX] Added support for `GLX_ARB_create_context_no_error`
@ -304,7 +321,9 @@ skills.
- David Avedissian
- Keith Bauer
- John Bartholomew
- Coşku Baş
- Niklas Behrens
- Andrew Belt
- Niklas Bergström
- Denis Bernard
- Doug Binks
@ -371,6 +390,7 @@ skills.
- Glenn Lewis
- Shane Liesegang
- Eyal Lotem
- Aaron Loucks
- Tristam MacDonald
- Hans Mackowiak
- Дмитри Малышев
@ -387,6 +407,7 @@ skills.
- Bruce Mitchener
- Jack Moffitt
- Jeff Molofee
- Alexander Monakov
- Pierre Morel
- Jon Morton
- Pierre Moulon

File diff suppressed because it is too large Load diff

View file

@ -35,12 +35,6 @@
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
#include <mir_toolkit/client_types.h>
#include "vulkan_mir.h"
#endif
#ifdef VK_USE_PLATFORM_VI_NN
#include "vulkan_vi.h"
#endif

View file

@ -269,23 +269,22 @@ extern "C" {
#define GLFW_VERSION_REVISION 0
/*! @} */
/*! @name Boolean values
* @{ */
/*! @brief One.
*
* One. Seriously. You don't _need_ to use this symbol in your code. It's
* semantic sugar for the number 1. You can also use `1` or `true` or `_True`
* or `GL_TRUE` or whatever you want.
* This is only semantic sugar for the number 1. You can instead use `1` or
* `true` or `_True` or `GL_TRUE` or anything else that is equal to one.
*
* @ingroup init
*/
#define GLFW_TRUE 1
/*! @brief Zero.
*
* Zero. Seriously. You don't _need_ to use this symbol in your code. It's
* semantic sugar for the number 0. You can also use `0` or `false` or
* `_False` or `GL_FALSE` or whatever you want.
* This is only semantic sugar for the number 0. You can instead use `0` or
* `false` or `_False` or `GL_FALSE` or anything else that is equal to zero.
*
* @ingroup init
*/
#define GLFW_FALSE 0
/*! @} */
/*! @name Key and button actions
* @{ */
@ -313,6 +312,7 @@ extern "C" {
/*! @} */
/*! @defgroup hat_state Joystick hat states
* @brief Joystick hat states.
*
* See [joystick hat input](@ref joystick_hat) for how these are used.
*
@ -973,6 +973,10 @@ extern "C" {
* [attribute](@ref GLFW_CLIENT_API_attrib).
*/
#define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window
* [window hint](@ref GLFW_SCALE_TO_MONITOR).
*/
#define GLFW_SCALE_TO_MONITOR 0x0002200C
#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
#define GLFW_COCOA_FRAME_NAME 0x00023002
@ -1056,9 +1060,20 @@ extern "C" {
/*! @addtogroup init
* @{ */
/*! @brief Joystick hat buttons init hint.
*
* Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS)
*/
#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
/*! @brief macOS specific init hint.
*
* macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES)
*/
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
/*! @brief macOS specific init hint.
*
* macOS specific [init hint](@ref GLFW_COCOA_MENUBAR)
*/
#define GLFW_COCOA_MENUBAR 0x00051002
/*! @} */
@ -1129,7 +1144,7 @@ typedef struct GLFWwindow GLFWwindow;
*
* @since Added in version 3.1.
*
* @ingroup cursor
* @ingroup input
*/
typedef struct GLFWcursor GLFWcursor;
@ -1567,6 +1582,8 @@ typedef struct GLFWgammaramp
*
* @since Added in version 2.1.
* @glfw3 Removed format and bytes-per-pixel members.
*
* @ingroup window
*/
typedef struct GLFWimage
{
@ -1589,6 +1606,8 @@ typedef struct GLFWimage
* @sa @ref glfwGetGamepadState
*
* @since Added in version 3.3.
*
* @ingroup input
*/
typedef struct GLFWgamepadstate
{
@ -2137,9 +2156,9 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
/*! @brief Generates a gamma ramp and sets it for the specified monitor.
*
* This function generates a 256-element gamma ramp from the specified exponent
* and then calls @ref glfwSetGammaRamp with it. The value must be a finite
* number greater than zero.
* This function generates an appropriately sized gamma ramp from the specified
* exponent and then calls @ref glfwSetGammaRamp with it. The value must be
* a finite number greater than zero.
*
* The software controlled gamma ramp is applied _in addition_ to the hardware
* gamma correction, which today is usually an approximation of sRGB gamma.
@ -2218,8 +2237,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark Gamma ramp sizes other than 256 are not supported by all platforms
* or graphics hardware.
* @remark The size of the specified gamma ramp should match the size of the
* current ramp for that monitor.
*
* @remark @win32 The gamma ramp size must be 256.
*
@ -3758,6 +3777,9 @@ GLFWAPI void glfwWaitEvents(void);
*
* @param[in] timeout The maximum amount of time, in seconds, to wait.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
*
* @reentrancy This function must not be called from a callback.
*
* @thread_safety This function must only be called from the main thread.
@ -4011,8 +4033,8 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
* `GLFW_RELEASE`.
*
* If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
* `GLFW_PRESS` the first time you call it for a mouse button that was pressed,
* even if that mouse button has already been released.
* 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.
*
* @param[in] window The desired window.
* @param[in] button The desired [mouse button](@ref buttons).
@ -4283,9 +4305,7 @@ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);
* The character callback behaves as system text input normally does and will
* not be called if modifier keys are held down that would prevent normal text
* input on that platform, for example a Super (Command) key on macOS or Alt key
* on Windows. There is a
* [character with modifiers callback](@ref glfwSetCharModsCallback) that
* receives these events.
* on Windows.
*
* @param[in] window The window whose callback to set.
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
@ -4581,7 +4601,7 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
* Each element in the array is one of the following values:
*
* Name | Value
* --------------------- | --------------------------------
* ---- | -----
* `GLFW_HAT_CENTERED` | 0
* `GLFW_HAT_UP` | 1
* `GLFW_HAT_RIGHT` | 2
@ -4901,6 +4921,8 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_INVALID_ENUM.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref gamepad
* @sa @ref glfwUpdateGamepadMappings
* @sa @ref glfwJoystickIsGamepad
@ -4922,8 +4944,6 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Clipboard is currently unimplemented.
*
* @pointer_lifetime The specified string is copied before this function
* returns.
*
@ -4952,8 +4972,6 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Clipboard is currently unimplemented.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the next call to @ref
* glfwGetClipboardString or @ref glfwSetClipboardString, or until the library

View file

@ -62,7 +62,6 @@ extern "C" {
* * `GLFW_EXPOSE_NATIVE_COCOA`
* * `GLFW_EXPOSE_NATIVE_X11`
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
* * `GLFW_EXPOSE_NATIVE_MIR`
*
* The available context API macros are:
* * `GLFW_EXPOSE_NATIVE_WGL`
@ -82,7 +81,7 @@ extern "C" {
* System headers and types
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_ARB_debug_output
// callback) but windows.h assumes no one will define APIENTRY before it does
@ -96,23 +95,19 @@ extern "C" {
typedef void *PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
#elif defined(GLFW_EXPOSE_NATIVE_COCOA)
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#include <ApplicationServices/ApplicationServices.h>
#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#else
// RAY: Added protection in case OBJC types defined
#if !OBJC_TYPES_DEFINED
typedef void* id;
#endif
#include <ApplicationServices/ApplicationServices.h>
typedef void* id;
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11)
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#elif defined(GLFW_EXPOSE_NATIVE_MIR)
#include <mir_toolkit/mir_client_library.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
@ -426,50 +421,6 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_MIR)
/*! @brief Returns the `MirConnection*` used by GLFW.
*
* @return The `MirConnection*` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI MirConnection* glfwGetMirDisplay(void);
/*! @brief Returns the Mir output ID of the specified monitor.
*
* @return The Mir output ID of the specified monitor, or zero if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `MirWindow*` of the specified window.
*
* @return The `MirWindow*` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW.
*

View file

@ -35,6 +35,10 @@ elseif (_GLFW_WAYLAND)
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/xdg-shell/xdg-shell.xml"
BASENAME xdg-shell)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
BASENAME xdg-decoration)
ecm_add_wayland_client_protocol(glfw_SOURCES
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/stable/viewporter/viewporter.xml"
@ -51,13 +55,6 @@ elseif (_GLFW_WAYLAND)
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
BASENAME idle-inhibit-unstable-v1)
elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
osmesa_context.h)
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c osmesa_context.c)
elseif (_GLFW_OSMESA)
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
posix_time.h posix_thread.h osmesa_context.h)
@ -104,10 +101,10 @@ set_target_properties(glfw PROPERTIES
target_compile_definitions(glfw_objlib PRIVATE _GLFW_USE_CONFIG_H)
target_include_directories(glfw_objlib PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_FULL_INCLUDEDIR}>")
target_include_directories(glfw PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_FULL_INCLUDEDIR}>")
target_include_directories(glfw_objlib PRIVATE
"${GLFW_SOURCE_DIR}/src"
"${GLFW_BINARY_DIR}/src"
@ -128,7 +125,7 @@ target_compile_options(glfw_objlib PRIVATE
if (BUILD_SHARED_LIBS)
if (WIN32)
if (MINGW)
# 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 "")
# Add a suffix to the import library to avoid naming conflicts
@ -142,7 +139,7 @@ if (BUILD_SHARED_LIBS)
target_compile_options(glfw_objlib PRIVATE "-fno-common")
set_target_properties(glfw PROPERTIES
INSTALL_NAME_DIR "lib${LIB_SUFFIX}")
INSTALL_NAME_DIR "${CMAKE_INSTALL_LIBDIR}")
elseif (UNIX)
# Hide symbols not explicitly tagged for export from the shared library
target_compile_options(glfw_objlib PRIVATE "-fvisibility=hidden")
@ -162,7 +159,7 @@ if (GLFW_INSTALL)
install(TARGETS glfw
EXPORT glfwTargets
RUNTIME DESTINATION "bin"
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
LIBRARY DESTINATION "lib${LIB_SUFFIX}")
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()

View file

@ -27,6 +27,10 @@
#include "internal.h"
#include <sys/param.h> // For MAXPATHLEN
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSEventMaskKeyUp NSKeyUpMask
#define NSEventModifierFlagCommand NSCommandKeyMask
#endif
// Change to our application bundle's resources directory, if present
//
@ -271,17 +275,21 @@ static GLFWbool initializeTIS(void)
return updateUnicodeDataNS();
}
@interface GLFWLayoutListener : NSObject
@interface GLFWHelper : NSObject
@end
@implementation GLFWLayoutListener
@implementation GLFWHelper
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
{
updateUnicodeDataNS();
}
@end
- (void)doNothing:(id)object
{
}
@end // GLFWHelper
//////////////////////////////////////////////////////////////////////////
@ -291,13 +299,31 @@ static GLFWbool initializeTIS(void)
int _glfwPlatformInit(void)
{
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
_glfw.ns.helper = [[GLFWHelper alloc] init];
[NSThread detachNewThreadSelector:@selector(doNothing:)
toTarget:_glfw.ns.helper
withObject:nil];
[NSApplication sharedApplication];
NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
{
if ([event modifierFlags] & NSEventModifierFlagCommand)
[[NSApp keyWindow] sendEvent:event];
return event;
};
_glfw.ns.keyUpMonitor =
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
handler:block];
if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory();
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
[[NSNotificationCenter defaultCenter]
addObserver:_glfw.ns.listener
addObserver:_glfw.ns.helper
selector:@selector(selectedKeyboardInputSourceChanged:)
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
@ -342,18 +368,21 @@ void _glfwPlatformTerminate(void)
_glfw.ns.delegate = nil;
}
if (_glfw.ns.listener)
if (_glfw.ns.helper)
{
[[NSNotificationCenter defaultCenter]
removeObserver:_glfw.ns.listener
removeObserver:_glfw.ns.helper
name:NSTextInputContextKeyboardSelectionDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter]
removeObserver:_glfw.ns.listener];
[_glfw.ns.listener release];
_glfw.ns.listener = nil;
removeObserver:_glfw.ns.helper];
[_glfw.ns.helper release];
_glfw.ns.helper = nil;
}
if (_glfw.ns.keyUpMonitor)
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
free(_glfw.ns.clipboardString);
_glfwTerminateNSGL();

View file

@ -467,7 +467,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
CVDisplayLinkRelease(link);
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
@ -489,6 +489,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
}
free(values);
return GLFW_TRUE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)

View file

@ -27,12 +27,10 @@
#include <stdint.h>
#include <dlfcn.h>
#include <Carbon/Carbon.h>
#if defined(__OBJC__)
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#else
#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
typedef void* id;
#endif
@ -111,7 +109,9 @@ typedef struct _GLFWlibraryNS
TISInputSourceRef inputSource;
IOHIDManagerRef hidManager;
id unicodeData;
id listener;
id helper;
id keyUpMonitor;
id nibObjects;
char keyName[64];
short int keycodes[256];

View file

@ -32,7 +32,6 @@
// Needed for _NSGetProgname
#include <crt_externs.h>
// HACK: The 10.12 SDK adds new symbols and immediately deprecates the old ones
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#define NSWindowStyleMaskClosable NSClosableWindowMask
@ -47,10 +46,9 @@
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
#define NSEventMaskAny NSAnyEventMask
#define NSEventTypeApplicationDefined NSApplicationDefined
#define NSEventTypeKeyUp NSKeyUp
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
#endif
// Returns the style mask corresponding to the window settings
//
static NSUInteger getStyleMask(_GLFWwindow* window)
@ -237,6 +235,8 @@ static NSUInteger translateKeyToModifierFlag(int key)
case GLFW_KEY_LEFT_SUPER:
case GLFW_KEY_RIGHT_SUPER:
return NSEventModifierFlagCommand;
case GLFW_KEY_CAPS_LOCK:
return NSEventModifierFlagCapsLock;
}
return 0;
@ -365,7 +365,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
// Delegate for application related notifications
//------------------------------------------------------------------------
@interface GLFWApplicationDelegate : NSObject
@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
@end
@implementation GLFWApplicationDelegate
@ -438,8 +438,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
markedText = [[NSMutableAttributedString alloc] init];
[self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObjects:
NSFilenamesPboardType, nil]];
// NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
// on 10.7 without having been deprecated yet
[self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
}
return self;
@ -472,6 +473,14 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
return YES;
}
- (void)updateLayer
{
if (window->context.client != GLFW_NO_API)
[window->context.nsgl.object update];
_glfwInputWindowDamage(window);
}
- (id)makeBackingLayer
{
if (window->ns.layer)
@ -485,6 +494,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
updateCursorImage(window);
}
- (BOOL)acceptsFirstMouse:(NSEvent *)event
{
return YES;
}
- (void)mouseDown:(NSEvent *)event
{
_glfwInputMouseClick(window,
@ -650,7 +664,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
[self interpretKeyEvents:@[event]];
}
- (void)flagsChanged:(NSEvent *)event
@ -701,45 +715,33 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
== NSDragOperationGeneric)
{
[self setNeedsDisplay:YES];
return NSDragOperationGeneric;
}
return NSDragOperationNone;
}
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
{
[self setNeedsDisplay:YES];
return YES;
// HACK: We don't know what to say here because we don't know what the
// application wants to do with the paths
return NSDragOperationGeneric;
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
NSPasteboard* pasteboard = [sender draggingPasteboard];
NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
const NSRect contentRect = [window->ns.view frame];
_glfwInputCursorPos(window,
[sender draggingLocation].x,
contentRect.size.height - [sender draggingLocation].y);
const NSUInteger count = [files count];
NSPasteboard* pasteboard = [sender draggingPasteboard];
NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
options:options];
const NSUInteger count = [urls count];
if (count)
{
NSEnumerator* e = [files objectEnumerator];
char** paths = calloc(count, sizeof(char*));
NSUInteger i;
for (i = 0; i < count; i++)
paths[i] = _glfw_strdup([[e nextObject] UTF8String]);
for (NSUInteger i = 0; i < count; i++)
paths[i] = _glfw_strdup([[urls objectAtIndex:i] fileSystemRepresentation]);
_glfwInputDrop(window, (int) count, (const char**) paths);
for (i = 0; i < count; i++)
for (NSUInteger i = 0; i < count; i++)
free(paths[i]);
free(paths);
}
@ -747,11 +749,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
return YES;
}
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
[self setNeedsDisplay:YES];
}
- (BOOL)hasMarkedText
{
return [markedText length] > 0;
@ -865,52 +862,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
@end
//------------------------------------------------------------------------
// GLFW application class
//------------------------------------------------------------------------
@interface GLFWApplication : NSApplication
{
NSArray* nibObjects;
}
@end
@implementation GLFWApplication
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
// This works around an AppKit bug, where key up events while holding
// down the command key don't get sent to the key window.
- (void)sendEvent:(NSEvent *)event
{
if ([event type] == NSEventTypeKeyUp &&
([event modifierFlags] & NSEventModifierFlagCommand))
{
[[self keyWindow] sendEvent:event];
}
else
[super sendEvent:event];
}
// No-op thread entry point
//
- (void)doNothing:(id)object
{
}
- (void)loadMainMenu
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
owner:NSApp
topLevelObjects:&nibObjects];
#else
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
#endif
}
@end
// Set up the menu bar (manually)
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
// could go away at any moment, lots of stuff that really should be
@ -1020,32 +971,9 @@ static void createMenuBar(void)
//
static GLFWbool initializeAppKit(void)
{
if (NSApp)
if (_glfw.ns.delegate)
return GLFW_TRUE;
// Implicitly create shared NSApplication instance
[GLFWApplication sharedApplication];
// Make Cocoa enter multi-threaded mode
[NSThread detachNewThreadSelector:@selector(doNothing:)
toTarget:NSApp
withObject:nil];
if (_glfw.hints.init.ns.menubar)
{
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
// Menu bar setup must go between sharedApplication above and
// finishLaunching below, in order to properly emulate the behavior
// of NSApplicationMain
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
[NSApp loadMainMenu];
else
createMenuBar();
}
// There can only be one application delegate, but we allocate it the
// first time a window is created to keep all window code in this file
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
@ -1057,13 +985,34 @@ static GLFWbool initializeAppKit(void)
}
[NSApp setDelegate:_glfw.ns.delegate];
if (_glfw.hints.init.ns.menubar)
{
// In case we are unbundled, make us a proper UI application
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
// Menu bar setup must go between sharedApplication above and
// finishLaunching below, in order to properly emulate the behavior
// of NSApplicationMain
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
owner:NSApp
topLevelObjects:&_glfw.ns.nibObjects];
#else
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
#endif
}
else
createMenuBar();
}
[NSApp run];
// Press and Hold prevents some keys from emitting repeated characters
NSDictionary* defaults =
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],
@"ApplePressAndHoldEnabled",
nil];
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
return GLFW_TRUE;
@ -1563,9 +1512,6 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
void _glfwPlatformPollEvents(void)
{
if (!initializeAppKit())
return;
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
@ -1716,9 +1662,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
NSImage* native;
NSBitmapImageRep* rep;
if (!initializeAppKit())
return GLFW_FALSE;
rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:image->width
@ -1728,7 +1671,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
bytesPerRow:image->width * 4
bitsPerPixel:32];
@ -1754,9 +1697,6 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
if (!initializeAppKit())
return GLFW_FALSE;
if (shape == GLFW_ARROW_CURSOR)
cursor->ns.object = [NSCursor arrowCursor];
else if (shape == GLFW_IBEAM_CURSOR)
@ -1795,26 +1735,24 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
void _glfwPlatformSetClipboardString(const char* string)
{
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
[pasteboard declareTypes:types owner:nil];
[pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
[pasteboard setString:[NSString stringWithUTF8String:string]
forType:NSStringPboardType];
forType:NSPasteboardTypeString];
}
const char* _glfwPlatformGetClipboardString(void)
{
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
if (![[pasteboard types] containsObject:NSStringPboardType])
if (![[pasteboard types] containsObject:NSPasteboardTypeString])
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"Cocoa: Failed to retrieve string from pasteboard");
return NULL;
}
NSString* object = [pasteboard stringForType:NSStringPboardType];
NSString* object = [pasteboard stringForType:NSPasteboardTypeString];
if (!object)
{
_glfwInputError(GLFW_PLATFORM_ERROR,

View file

@ -43,10 +43,6 @@ typedef Window EGLNativeWindowType;
#define EGLAPIENTRY
typedef struct wl_display* EGLNativeDisplayType;
typedef struct wl_egl_window* EGLNativeWindowType;
#elif defined(_GLFW_MIR)
#define EGLAPIENTRY
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
typedef MirEGLNativeWindowType EGLNativeWindowType;
#else
#error "No supported EGL platform selected"
#endif

View file

@ -1,12 +1,12 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib@LIB_SUFFIX@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
Name: GLFW
Description: A multi-platform library for OpenGL, window and input
Version: @GLFW_VERSION_FULL@
URL: http://www.glfw.org/
URL: https://www.glfw.org/
Requires.private: @GLFW_PKG_DEPS@
Libs: -L${libdir} -l@GLFW_LIB_NAME@
Libs.private: @GLFW_PKG_LIBS@

View file

@ -42,8 +42,6 @@
#cmakedefine _GLFW_COCOA
// Define this to 1 if building GLFW for Wayland
#cmakedefine _GLFW_WAYLAND
// Define this to 1 if building GLFW for Mir
#cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for OSMesa
#cmakedefine _GLFW_OSMESA
@ -57,4 +55,6 @@
// Define this to 1 if xkbcommon supports the compose key
#cmakedefine HAVE_XKBCOMMON_COMPOSE_H
// Define this to 1 if the libc supports memfd_create()
#cmakedefine HAVE_MEMFD_CREATE

View file

@ -119,6 +119,30 @@ char* _glfw_strdup(const char* source)
return result;
}
float _glfw_fminf(float a, float b)
{
if (a != a)
return b;
else if (b != b)
return a;
else if (a < b)
return a;
else
return b;
}
float _glfw_fmaxf(float a, float b)
{
if (a != a)
return b;
else if (b != b)
return a;
else if (a > b)
return a;
else
return b;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////

View file

@ -1242,7 +1242,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
if (e->type == _GLFW_JOYSTICK_AXIS)
{
const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f);
}
else if (e->type == _GLFW_JOYSTICK_HATBIT)
{

View file

@ -126,7 +126,6 @@ typedef enum VkStructureType
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
@ -188,8 +187,6 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
#include "x11_platform.h"
#elif defined(_GLFW_WAYLAND)
#include "wl_platform.h"
#elif defined(_GLFW_MIR)
#include "mir_platform.h"
#elif defined(_GLFW_OSMESA)
#include "null_platform.h"
#else
@ -268,6 +265,7 @@ struct _GLFWwndconfig
GLFWbool maximized;
GLFWbool centerCursor;
GLFWbool focusOnShow;
GLFWbool scaleToMonitor;
struct {
GLFWbool retina;
char frameName[256];
@ -562,8 +560,6 @@ struct _GLFWlibrary
GLFWbool KHR_xcb_surface;
#elif defined(_GLFW_WAYLAND)
GLFWbool KHR_wayland_surface;
#elif defined(_GLFW_MIR)
GLFWbool KHR_mir_surface;
#endif
} vk;
@ -615,7 +611,7 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale);
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwPlatformSetClipboardString(const char* string);
@ -770,4 +766,6 @@ void _glfwTerminateVulkan(void);
const char* _glfwGetVulkanResultString(VkResult result);
char* _glfw_strdup(const char* source);
float _glfw_fminf(float a, float b);
float _glfw_fmaxf(float a, float b);

View file

@ -228,7 +228,7 @@ static GLFWbool openJoystickDevice(const char* path)
return GLFW_FALSE;
}
strncpy(linjs.path, path, sizeof(linjs.path));
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
memcpy(&js->linjs, &linjs, sizeof(linjs));
pollAbsState(js);

View file

@ -1,240 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
// Create key code translation tables
//
static void createKeyTables(void)
{
int scancode;
memset(_glfw.mir.keycodes, -1, sizeof(_glfw.mir.keycodes));
memset(_glfw.mir.scancodes, -1, sizeof(_glfw.mir.scancodes));
_glfw.mir.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
_glfw.mir.keycodes[KEY_1] = GLFW_KEY_1;
_glfw.mir.keycodes[KEY_2] = GLFW_KEY_2;
_glfw.mir.keycodes[KEY_3] = GLFW_KEY_3;
_glfw.mir.keycodes[KEY_4] = GLFW_KEY_4;
_glfw.mir.keycodes[KEY_5] = GLFW_KEY_5;
_glfw.mir.keycodes[KEY_6] = GLFW_KEY_6;
_glfw.mir.keycodes[KEY_7] = GLFW_KEY_7;
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
_glfw.mir.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
_glfw.mir.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
_glfw.mir.keycodes[KEY_W] = GLFW_KEY_W;
_glfw.mir.keycodes[KEY_E] = GLFW_KEY_E;
_glfw.mir.keycodes[KEY_R] = GLFW_KEY_R;
_glfw.mir.keycodes[KEY_T] = GLFW_KEY_T;
_glfw.mir.keycodes[KEY_Y] = GLFW_KEY_Y;
_glfw.mir.keycodes[KEY_U] = GLFW_KEY_U;
_glfw.mir.keycodes[KEY_I] = GLFW_KEY_I;
_glfw.mir.keycodes[KEY_O] = GLFW_KEY_O;
_glfw.mir.keycodes[KEY_P] = GLFW_KEY_P;
_glfw.mir.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
_glfw.mir.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
_glfw.mir.keycodes[KEY_A] = GLFW_KEY_A;
_glfw.mir.keycodes[KEY_S] = GLFW_KEY_S;
_glfw.mir.keycodes[KEY_D] = GLFW_KEY_D;
_glfw.mir.keycodes[KEY_F] = GLFW_KEY_F;
_glfw.mir.keycodes[KEY_G] = GLFW_KEY_G;
_glfw.mir.keycodes[KEY_H] = GLFW_KEY_H;
_glfw.mir.keycodes[KEY_J] = GLFW_KEY_J;
_glfw.mir.keycodes[KEY_K] = GLFW_KEY_K;
_glfw.mir.keycodes[KEY_L] = GLFW_KEY_L;
_glfw.mir.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
_glfw.mir.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
_glfw.mir.keycodes[KEY_Z] = GLFW_KEY_Z;
_glfw.mir.keycodes[KEY_X] = GLFW_KEY_X;
_glfw.mir.keycodes[KEY_C] = GLFW_KEY_C;
_glfw.mir.keycodes[KEY_V] = GLFW_KEY_V;
_glfw.mir.keycodes[KEY_B] = GLFW_KEY_B;
_glfw.mir.keycodes[KEY_N] = GLFW_KEY_N;
_glfw.mir.keycodes[KEY_M] = GLFW_KEY_M;
_glfw.mir.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
_glfw.mir.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
_glfw.mir.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
_glfw.mir.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
_glfw.mir.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
_glfw.mir.keycodes[KEY_TAB] = GLFW_KEY_TAB;
_glfw.mir.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
_glfw.mir.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
_glfw.mir.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
_glfw.mir.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
_glfw.mir.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
_glfw.mir.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
_glfw.mir.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
_glfw.mir.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
_glfw.mir.keycodes[KEY_MENU] = GLFW_KEY_MENU;
_glfw.mir.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
_glfw.mir.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
_glfw.mir.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
_glfw.mir.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
_glfw.mir.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
_glfw.mir.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
_glfw.mir.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
_glfw.mir.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
_glfw.mir.keycodes[KEY_HOME] = GLFW_KEY_HOME;
_glfw.mir.keycodes[KEY_END] = GLFW_KEY_END;
_glfw.mir.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
_glfw.mir.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
_glfw.mir.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
_glfw.mir.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
_glfw.mir.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
_glfw.mir.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
_glfw.mir.keycodes[KEY_UP] = GLFW_KEY_UP;
_glfw.mir.keycodes[KEY_F1] = GLFW_KEY_F1;
_glfw.mir.keycodes[KEY_F2] = GLFW_KEY_F2;
_glfw.mir.keycodes[KEY_F3] = GLFW_KEY_F3;
_glfw.mir.keycodes[KEY_F4] = GLFW_KEY_F4;
_glfw.mir.keycodes[KEY_F5] = GLFW_KEY_F5;
_glfw.mir.keycodes[KEY_F6] = GLFW_KEY_F6;
_glfw.mir.keycodes[KEY_F7] = GLFW_KEY_F7;
_glfw.mir.keycodes[KEY_F8] = GLFW_KEY_F8;
_glfw.mir.keycodes[KEY_F9] = GLFW_KEY_F9;
_glfw.mir.keycodes[KEY_F10] = GLFW_KEY_F10;
_glfw.mir.keycodes[KEY_F11] = GLFW_KEY_F11;
_glfw.mir.keycodes[KEY_F12] = GLFW_KEY_F12;
_glfw.mir.keycodes[KEY_F13] = GLFW_KEY_F13;
_glfw.mir.keycodes[KEY_F14] = GLFW_KEY_F14;
_glfw.mir.keycodes[KEY_F15] = GLFW_KEY_F15;
_glfw.mir.keycodes[KEY_F16] = GLFW_KEY_F16;
_glfw.mir.keycodes[KEY_F17] = GLFW_KEY_F17;
_glfw.mir.keycodes[KEY_F18] = GLFW_KEY_F18;
_glfw.mir.keycodes[KEY_F19] = GLFW_KEY_F19;
_glfw.mir.keycodes[KEY_F20] = GLFW_KEY_F20;
_glfw.mir.keycodes[KEY_F21] = GLFW_KEY_F21;
_glfw.mir.keycodes[KEY_F22] = GLFW_KEY_F22;
_glfw.mir.keycodes[KEY_F23] = GLFW_KEY_F23;
_glfw.mir.keycodes[KEY_F24] = GLFW_KEY_F24;
_glfw.mir.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
_glfw.mir.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
_glfw.mir.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
_glfw.mir.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
_glfw.mir.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
_glfw.mir.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
_glfw.mir.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
_glfw.mir.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
_glfw.mir.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
_glfw.mir.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
_glfw.mir.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
_glfw.mir.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
_glfw.mir.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
_glfw.mir.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
_glfw.mir.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
_glfw.mir.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
_glfw.mir.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
for (scancode = 0; scancode < 256; scancode++)
{
if (_glfw.mir.keycodes[scancode] > 0)
_glfw.mir.scancodes[_glfw.mir.keycodes[scancode]] = scancode;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
{
int error;
_glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
if (!mir_connection_is_valid(_glfw.mir.connection))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to connect to server: %s",
mir_connection_get_error_message(_glfw.mir.connection));
return GLFW_FALSE;
}
_glfw.mir.display =
mir_connection_get_egl_native_display(_glfw.mir.connection);
createKeyTables();
if (!_glfwInitJoysticksLinux())
return GLFW_FALSE;
_glfwInitTimerPOSIX();
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
if (error)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Failed to create event mutex: %s",
strerror(error));
return GLFW_FALSE;
}
_glfwPollMonitorsMir();
return GLFW_TRUE;
}
void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
pthread_mutex_destroy(&_glfw.mir.eventMutex);
mir_connection_release(_glfw.mir.connection);
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER " Mir EGL"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#else
" gettimeofday"
#endif
" evdev"
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
}

View file

@ -1,218 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <stdlib.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Poll for changes in the set of connected monitors
//
void _glfwPollMonitorsMir(void)
{
int i;
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < numOutputs; i++)
{
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
if (enabled && state == mir_output_connection_state_connected)
{
int widthMM = mir_output_get_physical_width_mm(output);
int heightMM = mir_output_get_physical_height_mm(output);
int x = mir_output_get_position_x(output);
int y = mir_output_get_position_y(output);
int id = mir_output_get_id(output);
size_t currentMode = mir_output_get_current_mode_index(output);
const char* name = mir_output_type_name(mir_output_get_type(output));
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
widthMM,
heightMM);
monitor->mir.x = x;
monitor->mir.y = y;
monitor->mir.outputId = id;
monitor->mir.curMode = currentMode;
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
}
mir_display_config_release(displayConfig);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
{
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
if (xpos)
*xpos = monitor->mir.x;
if (ypos)
*ypos = monitor->mir.y;
}
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.f;
if (yscale)
*yscale = 1.f;
}
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
{
switch (pf)
{
case mir_pixel_format_rgb_565:
mode->redBits = 5;
mode->greenBits = 6;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_5551:
mode->redBits = 5;
mode->greenBits = 5;
mode->blueBits = 5;
break;
case mir_pixel_format_rgba_4444:
mode->redBits = 4;
mode->greenBits = 4;
mode->blueBits = 4;
break;
case mir_pixel_format_abgr_8888:
case mir_pixel_format_xbgr_8888:
case mir_pixel_format_argb_8888:
case mir_pixel_format_xrgb_8888:
case mir_pixel_format_bgr_888:
case mir_pixel_format_rgb_888:
default:
mode->redBits = 8;
mode->greenBits = 8;
mode->blueBits = 8;
break;
}
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
int i;
GLFWvidmode* modes = NULL;
MirDisplayConfig* displayConfig =
mir_connection_create_display_configuration(_glfw.mir.connection);
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
for (i = 0; i < numOutputs; i++)
{
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
int id = mir_output_get_id(output);
if (id != monitor->mir.outputId)
continue;
MirOutputConnectionState state = mir_output_get_connection_state(output);
bool enabled = mir_output_is_enabled(output);
// We must have been disconnected
if (!enabled || state != mir_output_connection_state_connected)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Monitor no longer connected");
return NULL;
}
int numModes = mir_output_get_num_modes(output);
modes = calloc(numModes, sizeof(GLFWvidmode));
for (*found = 0; *found < numModes; (*found)++)
{
const MirOutputMode* mode = mir_output_get_mode(output, *found);
int width = mir_output_mode_get_width(mode);
int height = mir_output_mode_get_height(mode);
double refreshRate = mir_output_mode_get_refresh_rate(mode);
MirPixelFormat currentFormat = mir_output_get_current_pixel_format(output);
modes[*found].width = width;
modes[*found].height = height;
modes[*found].refreshRate = refreshRate;
FillInRGBBitsFromPixelFormat(&modes[*found], currentFormat);
}
break;
}
mir_display_config_release(displayConfig);
return modes;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
*mode = monitor->modes[monitor->mir.curMode];
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(0);
return monitor->mir.outputId;
}

View file

@ -1,133 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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 <sys/queue.h>
#include <pthread.h>
#include <dlfcn.h>
#include <mir_toolkit/mir_client_library.h>
typedef VkFlags VkMirWindowCreateFlagsKHR;
typedef struct VkMirWindowCreateInfoKHR
{
VkStructureType sType;
const void* pNext;
VkMirWindowCreateFlagsKHR flags;
MirConnection* connection;
MirWindow* mirWindow;
} VkMirWindowCreateInfoKHR;
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
#include "posix_thread.h"
#include "posix_time.h"
#include "linux_joystick.h"
#include "xkb_unicode.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.nativeWindow)
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// Mir-specific Event Queue
//
typedef struct EventQueue
{
TAILQ_HEAD(, EventNode) head;
} EventQueue;
// Mir-specific per-window data
//
typedef struct _GLFWwindowMir
{
MirWindow* window;
int width;
int height;
MirEGLNativeWindowType nativeWindow;
_GLFWcursor* currentCursor;
} _GLFWwindowMir;
// Mir-specific per-monitor data
//
typedef struct _GLFWmonitorMir
{
int curMode;
int outputId;
int x;
int y;
} _GLFWmonitorMir;
// Mir-specific global data
//
typedef struct _GLFWlibraryMir
{
MirConnection* connection;
MirEGLNativeDisplayType display;
EventQueue* eventQueue;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
pthread_mutex_t eventMutex;
pthread_cond_t eventCond;
// The window whose disabled cursor mode is active
_GLFWwindow* disabledCursorWindow;
} _GLFWlibraryMir;
// Mir-specific per-cursor data
// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
//
typedef struct _GLFWcursorMir
{
MirCursorConfiguration* conf;
MirBufferStream* customCursor;
char const* cursorName; // only needed for system cursors
} _GLFWcursorMir;
extern void _glfwPollMonitorsMir(void);
extern void _glfwInitEventQueueMir(EventQueue* queue);
extern void _glfwDeleteEventQueueMir(EventQueue* queue);

View file

@ -1,975 +0,0 @@
//========================================================================
// GLFW 3.3 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// 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"
#include <linux/input.h>
#include <stdlib.h>
#include <string.h>
typedef struct EventNode
{
TAILQ_ENTRY(EventNode) entries;
const MirEvent* event;
_GLFWwindow* window;
} EventNode;
static void deleteNode(EventQueue* queue, EventNode* node)
{
mir_event_unref(node->event);
free(node);
}
static GLFWbool emptyEventQueue(EventQueue* queue)
{
return queue->head.tqh_first == NULL;
}
// TODO The mir_event_ref is not supposed to be used but ... its needed
// in this case. Need to wait until we can read from an FD set up by mir
// for single threaded event handling.
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
{
EventNode* newNode = calloc(1, sizeof(EventNode));
newNode->event = mir_event_ref(event);
newNode->window = context;
return newNode;
}
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
EventNode* newNode = newEventNode(event, context);
TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
pthread_cond_signal(&_glfw.mir.eventCond);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
}
static EventNode* dequeueEvent(EventQueue* queue)
{
EventNode* node = NULL;
pthread_mutex_lock(&_glfw.mir.eventMutex);
node = queue->head.tqh_first;
if (node)
TAILQ_REMOVE(&queue->head, node, entries);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
return node;
}
static MirPixelFormat findValidPixelFormat(void)
{
unsigned int i, validFormats, mirPixelFormats = 32;
MirPixelFormat formats[mir_pixel_formats];
mir_connection_get_available_surface_formats(_glfw.mir.connection, formats,
mirPixelFormats, &validFormats);
for (i = 0; i < validFormats; i++)
{
if (formats[i] == mir_pixel_format_abgr_8888 ||
formats[i] == mir_pixel_format_xbgr_8888 ||
formats[i] == mir_pixel_format_argb_8888 ||
formats[i] == mir_pixel_format_xrgb_8888)
{
return formats[i];
}
}
return mir_pixel_format_invalid;
}
static int mirModToGLFWMod(uint32_t mods)
{
int publicMods = 0x0;
if (mods & mir_input_event_modifier_alt)
publicMods |= GLFW_MOD_ALT;
if (mods & mir_input_event_modifier_shift)
publicMods |= GLFW_MOD_SHIFT;
if (mods & mir_input_event_modifier_ctrl)
publicMods |= GLFW_MOD_CONTROL;
if (mods & mir_input_event_modifier_meta)
publicMods |= GLFW_MOD_SUPER;
if (mods & mir_input_event_modifier_caps_lock)
publicMods |= GLFW_MOD_CAPS_LOCK;
if (mods & mir_input_event_modifier_num_lock)
publicMods |= GLFW_MOD_NUM_LOCK;
return publicMods;
}
static int toGLFWKeyCode(uint32_t key)
{
if (key < sizeof(_glfw.mir.keycodes) / sizeof(_glfw.mir.keycodes[0]))
return _glfw.mir.keycodes[key];
return GLFW_KEY_UNKNOWN;
}
static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
{
const int action = mir_keyboard_event_action (key_event);
const int scan_code = mir_keyboard_event_scan_code(key_event);
const int key_code = mir_keyboard_event_key_code (key_event);
const int modifiers = mir_keyboard_event_modifiers(key_event);
const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;
const int mods = mirModToGLFWMod(modifiers);
const long text = _glfwKeySym2Unicode(key_code);
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
_glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
if (text != -1)
_glfwInputChar(window, text, mods, plain);
}
static void handlePointerButton(_GLFWwindow* window,
int pressed,
const MirPointerEvent* pointer_event)
{
int mods = mir_pointer_event_modifiers(pointer_event);
const int publicMods = mirModToGLFWMod(mods);
MirPointerButton button = mir_pointer_button_primary;
static uint32_t oldButtonStates = 0;
uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
int publicButton = GLFW_MOUSE_BUTTON_LEFT;
// XOR our old button states our new states to figure out what was added or removed
button = newButtonStates ^ oldButtonStates;
switch (button)
{
case mir_pointer_button_primary:
publicButton = GLFW_MOUSE_BUTTON_LEFT;
break;
case mir_pointer_button_secondary:
publicButton = GLFW_MOUSE_BUTTON_RIGHT;
break;
case mir_pointer_button_tertiary:
publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
break;
case mir_pointer_button_forward:
// FIXME What is the forward button?
publicButton = GLFW_MOUSE_BUTTON_4;
break;
case mir_pointer_button_back:
// FIXME What is the back button?
publicButton = GLFW_MOUSE_BUTTON_5;
break;
default:
break;
}
oldButtonStates = newButtonStates;
_glfwInputMouseClick(window, publicButton, pressed, publicMods);
}
static void handlePointerMotion(_GLFWwindow* window,
const MirPointerEvent* pointer_event)
{
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
{
if (_glfw.mir.disabledCursorWindow != window)
return;
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
const int current_x = window->virtualCursorPosX;
const int current_y = window->virtualCursorPosY;
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
}
else
{
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
_glfwInputCursorPos(window, x, y);
}
if (hscroll != 0 || vscroll != 0)
_glfwInputScroll(window, hscroll, vscroll);
}
static void handlePointerEvent(const MirPointerEvent* pointer_event,
_GLFWwindow* window)
{
int action = mir_pointer_event_action(pointer_event);
switch (action)
{
case mir_pointer_action_button_down:
handlePointerButton(window, GLFW_PRESS, pointer_event);
break;
case mir_pointer_action_button_up:
handlePointerButton(window, GLFW_RELEASE, pointer_event);
break;
case mir_pointer_action_motion:
handlePointerMotion(window, pointer_event);
break;
case mir_pointer_action_enter:
case mir_pointer_action_leave:
break;
default:
break;
}
}
static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
{
int type = mir_input_event_get_type(input_event);
switch (type)
{
case mir_input_event_type_key:
handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
break;
case mir_input_event_type_pointer:
handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
break;
default:
break;
}
}
static void handleEvent(const MirEvent* event, _GLFWwindow* window)
{
int type = mir_event_get_type(event);
switch (type)
{
case mir_event_type_input:
handleInput(mir_event_get_input_event(event), window);
break;
default:
break;
}
}
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
{
enqueueEvent(event, context);
}
static GLFWbool createWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
MirPixelFormat pixel_format = findValidPixelFormat();
if (pixel_format == mir_pixel_format_invalid)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to find a correct pixel format");
return GLFW_FALSE;
}
spec = mir_create_normal_window_spec(_glfw.mir.connection,
window->mir.width,
window->mir.height);
mir_window_spec_set_pixel_format(spec, pixel_format);
mir_window_spec_set_buffer_usage(spec, buffer_usage);
window->mir.window = mir_create_window_sync(spec);
mir_window_spec_release(spec);
if (!mir_window_is_valid(window->mir.window))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unable to create window: %s",
mir_window_get_error_message(window->mir.window));
return GLFW_FALSE;
}
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
return GLFW_TRUE;
}
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_pointer_confinement(spec, state);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void _glfwInitEventQueueMir(EventQueue* queue)
{
TAILQ_INIT(&queue->head);
}
void _glfwDeleteEventQueueMir(EventQueue* queue)
{
if (queue)
{
EventNode* node, *node_next;
node = queue->head.tqh_first;
while (node != NULL)
{
node_next = node->entries.tqe_next;
TAILQ_REMOVE(&queue->head, node, entries);
deleteNode(queue, node);
node = node_next;
}
free(queue);
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (window->monitor)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
mir_window_set_state(window->mir.window, mir_window_state_fullscreen);
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Requested window size too large: %ix%i",
wndconfig->width, wndconfig->height);
return GLFW_FALSE;
}
}
window->mir.width = wndconfig->width;
window->mir.height = wndconfig->height;
window->mir.currentCursor = NULL;
if (!createWindow(window))
return GLFW_FALSE;
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
mir_window_get_buffer_stream(window->mir.window));
if (ctxconfig->client != GLFW_NO_API)
{
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
{
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
{
if (!_glfwInitOSMesa())
return GLFW_FALSE;
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
return GLFW_FALSE;
}
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (_glfw.mir.disabledCursorWindow == window)
_glfw.mir.disabledCursorWindow = NULL;
if (mir_window_is_valid(window->mir.window))
{
mir_window_release_sync(window->mir.window);
window->mir.window= NULL;
}
if (window->context.destroy)
window->context.destroy(window);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_name(spec, title);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_width (spec, width);
mir_window_spec_set_height(spec, height);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_max_width (spec, maxwidth);
mir_window_spec_set_max_height(spec, maxheight);
mir_window_spec_set_min_width (spec, minwidth);
mir_window_spec_set_min_height(spec, minheight);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->mir.width;
if (height)
*height = window->mir.height;
}
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.f;
if (yscale)
*yscale = 1.f;
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_minimized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_maximized);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_hidden);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
MirWindowSpec* spec;
spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_state(spec, mir_window_state_restored);
mir_window_apply_spec(window->mir.window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
}
int _glfwPlatformWindowHovered(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return GLFW_FALSE;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
{
return 1.f;
}
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
{
}
void _glfwPlatformPollEvents(void)
{
EventNode* node = NULL;
while ((node = dequeueEvent(_glfw.mir.eventQueue)))
{
handleEvent(node->event, node->window);
deleteNode(_glfw.mir.eventQueue, node);
}
}
void _glfwPlatformWaitEvents(void)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
while (emptyEventQueue(_glfw.mir.eventQueue))
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
pthread_mutex_lock(&_glfw.mir.eventMutex);
if (emptyEventQueue(_glfw.mir.eventQueue))
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += (long) timeout;
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
}
pthread_mutex_unlock(&_glfw.mir.eventMutex);
_glfwPlatformPollEvents();
}
void _glfwPlatformPostEmptyEvent(void)
{
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->mir.width;
if (height)
*height = window->mir.height;
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
MirBufferStream* stream;
int i_w = image->width;
int i_h = image->height;
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
i_w, i_h,
mir_pixel_format_argb_8888,
mir_buffer_usage_software);
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
MirGraphicsRegion region;
mir_buffer_stream_get_graphics_region(stream, &region);
unsigned char* pixels = image->pixels;
char* dest = region.vaddr;
int i;
for (i = 0; i < i_w * i_h; i++, pixels += 4)
{
unsigned int alpha = pixels[3];
*dest++ = (char)(pixels[2] * alpha / 255);
*dest++ = (char)(pixels[1] * alpha / 255);
*dest++ = (char)(pixels[0] * alpha / 255);
*dest++ = (char)alpha;
}
mir_buffer_stream_swap_buffers_sync(stream);
cursor->mir.customCursor = stream;
return GLFW_TRUE;
}
static const char* getSystemCursorName(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return mir_arrow_cursor_name;
case GLFW_IBEAM_CURSOR:
return mir_caret_cursor_name;
case GLFW_CROSSHAIR_CURSOR:
return mir_crosshair_cursor_name;
case GLFW_HAND_CURSOR:
return mir_open_hand_cursor_name;
case GLFW_HRESIZE_CURSOR:
return mir_horizontal_resize_cursor_name;
case GLFW_VRESIZE_CURSOR:
return mir_vertical_resize_cursor_name;
}
return NULL;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->mir.conf = NULL;
cursor->mir.customCursor = NULL;
cursor->mir.cursorName = getSystemCursorName(shape);
return cursor->mir.cursorName != NULL;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->mir.conf)
mir_cursor_configuration_destroy(cursor->mir.conf);
if (cursor->mir.customCursor)
mir_buffer_stream_release_sync(cursor->mir.customCursor);
}
static void setCursorNameForWindow(MirWindow* window, char const* name)
{
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
mir_window_spec_set_cursor_name(spec, name);
mir_window_apply_spec(window, spec);
mir_window_spec_release(spec);
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
if (cursor)
{
window->mir.currentCursor = cursor;
if (cursor->mir.cursorName)
{
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
}
else if (cursor->mir.conf)
{
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
}
}
else
{
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
}
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
if (mode == GLFW_CURSOR_DISABLED)
{
_glfw.mir.disabledCursorWindow = window;
setWindowConfinement(window, mir_pointer_confined_to_window);
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
else
{
// If we were disabled before lets undo that!
if (_glfw.mir.disabledCursorWindow == window)
{
_glfw.mir.disabledCursorWindow = NULL;
setWindowConfinement(window, mir_pointer_unconfined);
}
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
_glfwPlatformSetCursor(window, window->mir.currentCursor);
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
}
}
}
const char* _glfwPlatformGetScancodeName(int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return NULL;
}
int _glfwPlatformGetKeyScancode(int key)
{
return _glfw.mir.scancodes[key];
}
void _glfwPlatformSetClipboardString(const char* string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
const char* _glfwPlatformGetClipboardString(void)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
return NULL;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_mir_surface)
return;
extensions[0] = "VK_KHR_surface";
extensions[1] = "VK_KHR_mir_surface";
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
PFN_vkGetPhysicalDeviceMirPresentationSupportKHR
vkGetPhysicalDeviceMirPresentationSupportKHR =
(PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
return GLFW_FALSE;
}
return vkGetPhysicalDeviceMirPresentationSupportKHR(device,
queuefamily,
_glfw.mir.connection);
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
VkResult err;
VkMirWindowCreateInfoKHR sci;
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
if (!vkCreateMirWindowKHR)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
memset(&sci, 0, sizeof(sci));
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
sci.connection = _glfw.mir.connection;
sci.mirWindow = window->mir.window;
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
if (err)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Failed to create Vulkan surface: %s",
_glfwGetVulkanResultString(err));
}
return err;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI MirConnection* glfwGetMirDisplay(void)
{
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfw.mir.connection;
}
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return window->mir.window;
}

View file

@ -427,12 +427,12 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
{
int i;
unsigned short values[256];
unsigned int i;
unsigned short* values;
GLFWgammaramp ramp;
const GLFWgammaramp* original;
assert(handle != NULL);
assert(gamma == gamma);
assert(gamma >= 0.f);
assert(gamma > 0.f);
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT();
@ -443,18 +443,22 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
return;
}
for (i = 0; i < 256; i++)
original = glfwGetGammaRamp(handle);
if (!original)
return;
values = calloc(original->size, sizeof(unsigned short));
for (i = 0; i < original->size; i++)
{
float value;
// Calculate intensity
value = i / 255.f;
value = i / (float) (original->size - 1);
// Apply gamma curve
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
// Clamp to value range
if (value > 65535.f)
value = 65535.f;
value = _glfw_fminf(value, 65535.f);
values[i] = (unsigned short) value;
}
@ -462,9 +466,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
ramp.red = values;
ramp.green = values;
ramp.blue = values;
ramp.size = 256;
ramp.size = original->size;
glfwSetGammaRamp(handle, &ramp);
free(values);
}
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
@ -475,7 +480,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_glfwFreeGammaArrays(&monitor->currentRamp);
_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
return NULL;
return &monitor->currentRamp;
}
@ -501,7 +507,10 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
_GLFW_REQUIRE_INIT();
if (!monitor->originalRamp.size)
_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
{
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
return;
}
_glfwPlatformSetGammaRamp(monitor, ramp);
}

View file

@ -26,6 +26,10 @@
#include "internal.h"
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
#endif
static void makeContextCurrentNSGL(_GLFWwindow* window)
{
@ -49,7 +53,7 @@ static void swapIntervalNSGL(int interval)
GLint sync = interval;
[window->context.nsgl.object setValues:&sync
forParameter:NSOpenGLCPSwapInterval];
forParameter:NSOpenGLContextParameterSwapInterval];
}
static int extensionSupportedNSGL(const char* extension)
@ -299,7 +303,8 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
if (fbconfig->transparent)
{
GLint opaque = 0;
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
[window->context.nsgl.object setValues:&opaque
forParameter:NSOpenGLContextParameterSurfaceOpacity];
}
[window->context.nsgl.object setView:window->ns.view];

View file

@ -58,8 +58,9 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
return GLFW_FALSE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)

View file

@ -240,7 +240,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
if (ctxconfig->forward)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"OSMesa: Foward-compatible contexts not supported");
"OSMesa: Forward-compatible contexts not supported");
return GLFW_FALSE;
}

View file

@ -136,9 +136,6 @@ GLFWbool _glfwInitVulkan(int mode)
#elif defined(_GLFW_WAYLAND)
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
#elif defined(_GLFW_MIR)
else if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
#endif
}

View file

@ -256,12 +256,20 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
static void swapBuffersWGL(_GLFWwindow* window)
{
// HACK: Use DwmFlush when desktop composition is enabled
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
if (!window->monitor)
{
int count = abs(window->context.wgl.interval);
while (count--)
DwmFlush();
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Use DwmFlush when desktop composition is enabled
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
int count = abs(window->context.wgl.interval);
while (count--)
DwmFlush();
}
}
}
SwapBuffers(window->context.wgl.dc);
@ -273,10 +281,18 @@ static void swapIntervalWGL(int interval)
window->context.wgl.interval = interval;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (_glfwIsCompositionEnabledWin32() && !window->monitor)
interval = 0;
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
interval = 0;
}
}
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
@ -284,29 +300,17 @@ static void swapIntervalWGL(int interval)
static int extensionSupportedWGL(const char* extension)
{
const char* extensions;
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
const char* extensions = NULL;
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return GLFW_TRUE;
}
}
else if (_glfw.wgl.GetExtensionsStringEXT)
extensions = _glfw.wgl.GetExtensionsStringEXT();
return GLFW_FALSE;
if (!extensions)
return GLFW_FALSE;
return _glfwStringInExtensionString(extension, extensions);
}
static GLFWglproc getProcAddressWGL(const char* procname)

View file

@ -62,17 +62,6 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
#endif // _GLFW_BUILD_DLL
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
return VerifyVersionInfoW(&osvi, mask, cond);
}
// Load necessary libraries (DLLs)
//
static GLFWbool loadLibraries(void)
@ -100,6 +89,14 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
if (_glfw.win32.dinput8.instance)
@ -155,6 +152,13 @@ static GLFWbool loadLibraries(void)
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
}
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
if (_glfw.win32.ntdll.instance)
{
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
}
return GLFW_TRUE;
}
@ -179,6 +183,9 @@ static void freeLibraries(void)
if (_glfw.win32.shcore.instance)
FreeLibrary(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
FreeLibrary(_glfw.win32.ntdll.instance);
}
// Create key code translation tables
@ -309,6 +316,7 @@ static void createKeyTables(void)
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
_glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
@ -339,8 +347,8 @@ static HWND createHelperWindow(void)
return NULL;
}
// HACK: The first call to ShowWindow is ignored if the parent process
// passed along a STARTUPINFO, so clear that flag with a no-op call
// HACK: The command to the first ShowWindow call is ignored if the parent
// process passed along a STARTUPINFO, so clear that with a no-op call
ShowWindow(window, SW_HIDE);
// Register for HID device notifications
@ -502,6 +510,36 @@ void _glfwUpdateKeyNamesWin32(void)
}
}
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
//
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embedd a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
// Checks whether we are on at least the specified build of Windows 10
//
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
// latter lies unless the user knew to embedd a non-default manifest
// announcing support for Windows 10 via supportedOS GUID
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@ -523,7 +561,9 @@ int _glfwPlatformInit(void)
createKeyTables();
_glfwUpdateKeyNamesWin32();
if (IsWindows8Point1OrGreater())
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
else if (IsWindows8Point1OrGreater())
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
else if (IsWindowsVistaOrGreater())
SetProcessDPIAware();

View file

@ -260,6 +260,8 @@ static void closeJoystick(_GLFWjoystick* js)
IDirectInputDevice8_Release(js->win32.device);
}
free(js->win32.objects);
_glfwFreeJoystick(js);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
}

View file

@ -324,9 +324,9 @@ void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* ysc
}
if (xscale)
*xscale = xdpi / 96.f;
*xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
if (yscale)
*yscale = ydpi / 96.f;
*yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
}
@ -455,7 +455,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
&mode->blueBits);
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
HDC dc;
WORD values[768];
@ -469,6 +469,8 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
return GLFW_TRUE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)

View file

@ -98,6 +98,12 @@
#ifndef _WIN32_WINNT_WINBLUE
#define _WIN32_WINNT_WINBLUE 0x0602
#endif
#ifndef WM_GETDPISCALEDSIZE
#define WM_GETDPISCALEDSIZE 0x02e4
#endif
#ifndef USER_DEFAULT_SCREEN_DPI
#define USER_DEFAULT_SCREEN_DPI 96
#endif
#if WINVER < 0x0601
typedef struct
@ -140,20 +146,31 @@ typedef enum
} MONITOR_DPI_TYPE;
#endif /*DPI_ENUMS_DECLARED*/
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
BOOL IsWindowsVersionOrGreater(WORD major, WORD minor, WORD sp);
#define IsWindowsVistaOrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), \
LOBYTE(_WIN32_WINNT_VISTA), 0)
#define IsWindows7OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), \
LOBYTE(_WIN32_WINNT_WIN7), 0)
#define IsWindows8OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0)
#define IsWindows8Point1OrGreater() \
IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), \
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
#define IsWindowsXPOrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
LOBYTE(_WIN32_WINNT_WINXP), 0)
#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() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
LOBYTE(_WIN32_WINNT_WIN8), 0)
#define IsWindows8Point1OrGreater() \
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(14393)
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
_glfwIsWindows10BuildOrGreaterWin32(15063)
// HACK: Define macros that some xinput.h variants don't
#ifndef XINPUT_CAPS_WIRELESS
@ -206,8 +223,16 @@ typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*
// 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_SetProcessDpiAwarenessContext)(HANDLE);
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
// dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
@ -223,6 +248,10 @@ typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
// ntdll.dll function pointer typedefs
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
typedef struct VkWin32SurfaceCreateInfoKHR
@ -276,6 +305,7 @@ typedef struct _GLFWwindowWin32
GLFWbool maximized;
// Whether to enable framebuffer transparency on DWM
GLFWbool transparent;
GLFWbool scaleToMonitor;
// The last received cursor position, regardless of source
int lastCursorPosX, lastCursorPosY;
@ -300,6 +330,7 @@ typedef struct _GLFWlibraryWin32
_GLFWwindow* disabledCursorWindow;
RAWINPUT* rawInput;
int rawInputSize;
UINT mouseTrailSize;
struct {
HINSTANCE instance;
@ -322,6 +353,10 @@ typedef struct _GLFWlibraryWin32
HINSTANCE instance;
PFN_SetProcessDPIAware SetProcessDPIAware_;
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
PFN_GetDpiForWindow GetDpiForWindow_;
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
} user32;
struct {
@ -337,6 +372,11 @@ typedef struct _GLFWlibraryWin32
PFN_GetDpiForMonitor GetDpiForMonitor_;
} shcore;
struct {
HINSTANCE instance;
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
} ntdll;
} _GLFWlibraryWin32;
// Win32-specific per-monitor data
@ -392,10 +432,11 @@ typedef struct _GLFWmutexWin32
GLFWbool _glfwRegisterWindowClassWin32(void);
void _glfwUnregisterWindowClassWin32(void);
GLFWbool _glfwIsCompositionEnabledWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
void _glfwInputErrorWin32(int error, const char* description);
void _glfwUpdateKeyNamesWin32(void);

View file

@ -186,14 +186,20 @@ static HICON createIcon(const GLFWimage* image,
return handle;
}
// Translate client window size to full window size according to styles
// Translate client window size to full window size according to styles and DPI
//
static void getFullWindowSize(DWORD style, DWORD exStyle,
int clientWidth, int clientHeight,
int* fullWidth, int* fullHeight)
int* fullWidth, int* fullHeight,
UINT dpi)
{
RECT rect = { 0, 0, clientWidth, clientHeight };
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
*fullWidth = rect.right - rect.left;
*fullHeight = rect.bottom - rect.top;
}
@ -203,10 +209,14 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
int xoff, yoff;
UINT dpi = USER_DEFAULT_SCREEN_DPI;
const float ratio = (float) window->numer / (float) window->denom;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
0, 0, &xoff, &yoff, dpi);
if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
@ -337,7 +347,16 @@ static void updateWindowStyles(const _GLFWwindow* window)
style |= getWindowStyle(window);
GetClientRect(window->win32.handle, &rect);
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE,
getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
@ -351,10 +370,12 @@ static void updateWindowStyles(const _GLFWwindow* window)
//
static void updateFramebufferTransparency(const _GLFWwindow* window)
{
BOOL enabled;
if (!IsWindowsVistaOrGreater())
return;
if (_glfwIsCompositionEnabledWin32())
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
HRGN region = CreateRectRgn(0, 0, -1, -1);
DWM_BLURBEHIND bb = {0};
@ -396,29 +417,6 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
}
}
// Translates a GLFW standard cursor to a resource ID
//
static LPWSTR translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return IDC_ARROW;
case GLFW_IBEAM_CURSOR:
return IDC_IBEAM;
case GLFW_CROSSHAIR_CURSOR:
return IDC_CROSS;
case GLFW_HAND_CURSOR:
return IDC_HAND;
case GLFW_HRESIZE_CURSOR:
return IDC_SIZEWE;
case GLFW_VRESIZE_CURSOR:
return IDC_SIZENS;
}
return NULL;
}
// Retrieves and translates modifier keys
//
static int getKeyMods(void)
@ -529,7 +527,18 @@ static void fitToMonitor(_GLFWwindow* window)
static void acquireMonitor(_GLFWwindow* window)
{
if (!_glfw.win32.acquiredMonitorCount)
{
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
// HACK: When mouse trails are enabled the cursor becomes invisible when
// the OpenGL ICD switches to page flipping
if (IsWindowsXPOrGreater())
{
SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
}
}
if (!window->monitor->window)
_glfw.win32.acquiredMonitorCount++;
@ -546,8 +555,14 @@ static void releaseMonitor(_GLFWwindow* window)
_glfw.win32.acquiredMonitorCount--;
if (!_glfw.win32.acquiredMonitorCount)
{
SetThreadExecutionState(ES_CONTINUOUS);
// HACK: Restore mouse trail length saved in acquireMonitor
if (IsWindowsXPOrGreater())
SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
}
_glfwInputMonitorWindow(window->monitor, NULL);
_glfwRestoreVideoModeWin32(window->monitor);
}
@ -561,9 +576,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (!window)
{
// This is the message handling for the hidden helper window
// and for a regular window during its initial creation
switch (uMsg)
{
case WM_NCCREATE:
{
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
EnableNonClientDpiScaling(hWnd);
break;
}
case WM_DISPLAYCHANGE:
_glfwPollMonitorsWin32();
break;
@ -980,13 +1004,17 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_GETMINMAXINFO:
{
int xoff, yoff;
UINT dpi = USER_DEFAULT_SCREEN_DPI;
MINMAXINFO* mmi = (MINMAXINFO*) lParam;
if (window->monitor)
break;
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
dpi = GetDpiForWindow(window->win32.handle);
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
0, 0, &xoff, &yoff, dpi);
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
@ -1032,6 +1060,17 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return TRUE;
}
case WM_NCACTIVATE:
case WM_NCPAINT:
{
// Prevent title bar from being drawn after restoring a minimized
// undecorated window
if (!window->decorated)
return TRUE;
break;
}
case WM_DWMCOMPOSITIONCHANGED:
{
if (window->win32.transparent)
@ -1039,10 +1078,52 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0;
}
case WM_GETDPISCALEDSIZE:
{
if (window->win32.scaleToMonitor)
break;
// Adjust the window size to keep the client area size constant
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT source = {0}, target = {0};
SIZE* size = (SIZE*) lParam;
AdjustWindowRectExForDpi(&source, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
AdjustWindowRectExForDpi(&target, getWindowStyle(window),
FALSE, getWindowExStyle(window),
LOWORD(wParam));
size->cx += (target.right - target.left) -
(source.right - source.left);
size->cy += (target.bottom - target.top) -
(source.bottom - source.top);
return TRUE;
}
break;
}
case WM_DPICHANGED:
{
const float xscale = HIWORD(wParam) / 96.f;
const float yscale = LOWORD(wParam) / 96.f;
const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
// Only apply the suggested size if the OS is new enough to have
// sent a WM_GETDPISCALEDSIZE before this
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
{
RECT* suggested = (RECT*) lParam;
SetWindowPos(window->win32.handle, HWND_TOP,
suggested->left,
suggested->top,
suggested->right - suggested->left,
suggested->bottom - suggested->top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
_glfwInputWindowContentScale(window, xscale, yscale);
break;
}
@ -1129,7 +1210,8 @@ static int createNativeWindow(_GLFWwindow* window,
getFullWindowSize(style, exStyle,
wndconfig->width, wndconfig->height,
&fullWidth, &fullHeight);
&fullWidth, &fullHeight,
USER_DEFAULT_SCREEN_DPI);
}
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
@ -1168,6 +1250,40 @@ static int createNativeWindow(_GLFWwindow* window,
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
// Adjust window size to account for DPI scaling of the window frame and
// optionally DPI scaling of the client area
// This cannot be done until we know what monitor it was placed on
if (!window->monitor)
{
RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
if (wndconfig->scaleToMonitor)
{
float xscale, yscale;
_glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
rect.right = (int) (rect.right * xscale);
rect.bottom = (int) (rect.bottom * yscale);
}
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
GetDpiForWindow(window->win32.handle));
}
else
AdjustWindowRectEx(&rect, style, FALSE, exStyle);
SetWindowPos(window->win32.handle, NULL,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOZORDER);
}
DragAcceptFiles(window->win32.handle, TRUE);
if (fbconfig->transparent)
@ -1227,20 +1343,6 @@ void _glfwUnregisterWindowClassWin32(void)
UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
}
// Returns whether desktop compositing is enabled
//
GLFWbool _glfwIsCompositionEnabledWin32(void)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)))
return enabled;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@ -1378,8 +1480,19 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
RECT rect = { xpos, ypos, xpos, ypos };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
}
@ -1408,8 +1521,19 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
else
{
RECT rect = { 0, 0, width, height };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP,
0, 0, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
@ -1464,8 +1588,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
_glfwPlatformGetWindowSize(window, &width, &height);
SetRect(&rect, 0, 0, width, height);
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
if (left)
*left = -rect.left;
@ -1541,8 +1675,19 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else
{
RECT rect = { xpos, ypos, xpos + width, ypos + height };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
@ -1602,8 +1747,18 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else
after = HWND_NOTOPMOST;
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
{
AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window),
GetDpiForWindow(window->win32.handle));
}
else
{
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
}
SetWindowPos(window->win32.handle, after,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
@ -1638,7 +1793,15 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
{
return window->win32.transparent && _glfwIsCompositionEnabledWin32();
BOOL enabled;
if (!window->win32.transparent)
return GLFW_FALSE;
if (!IsWindowsVistaOrGreater())
return GLFW_FALSE;
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
@ -1845,8 +2008,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->win32.handle =
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
LPCWSTR name = NULL;
if (shape == GLFW_ARROW_CURSOR)
name = IDC_ARROW;
else if (shape == GLFW_IBEAM_CURSOR)
name = IDC_IBEAM;
else if (shape == GLFW_CROSSHAIR_CURSOR)
name = IDC_CROSS;
else if (shape == GLFW_HAND_CURSOR)
name = IDC_HAND;
else if (shape == GLFW_HRESIZE_CURSOR)
name = IDC_SIZEWE;
else if (shape == GLFW_VRESIZE_CURSOR)
name = IDC_SIZENS;
else
return GLFW_FALSE;
cursor->win32.handle = CopyCursor(LoadCursorW(NULL, name));
if (!cursor->win32.handle)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,

View file

@ -369,6 +369,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
return;

View file

@ -27,6 +27,8 @@
#include "internal.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
@ -42,7 +44,8 @@ static inline int min(int n1, int n2)
return n1 < n2 ? n1 : n2;
}
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, int* which)
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
int* which)
{
int focus;
_GLFWwindow* window = _glfw.windowListHead;
@ -96,7 +99,7 @@ static void pointerHandleEnter(void* data,
}
window->wl.decorations.focus = focus;
_glfw.wl.pointerSerial = serial;
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = window;
window->wl.hovered = GLFW_TRUE;
@ -117,26 +120,36 @@ static void pointerHandleLeave(void* data,
window->wl.hovered = GLFW_FALSE;
_glfw.wl.pointerSerial = serial;
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
}
static void setCursor(const char* name)
static void setCursor(_GLFWwindow* window, const char* name)
{
struct wl_buffer* buffer;
struct wl_cursor* cursor;
struct wl_cursor_image* image;
struct wl_surface* surface = _glfw.wl.cursorSurface;
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1;
cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
name);
if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
{
// We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size.
scale = 2;
theme = _glfw.wl.cursorThemeHiDPI;
}
cursor = wl_cursor_theme_get_cursor(theme, name);
if (!cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Standard cursor not found");
return;
}
// TODO: handle animated cursors too.
image = cursor->images[0];
if (!image)
@ -145,10 +158,11 @@ static void setCursor(const char* name)
buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
surface,
image->hotspot_x,
image->hotspot_y);
image->hotspot_x / scale,
image->hotspot_y / scale);
wl_surface_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
image->width, image->height);
@ -211,7 +225,7 @@ static void pointerHandleMotion(void* data,
default:
assert(0);
}
setCursor(cursorName);
setCursor(window, cursorName);
}
static void pointerHandleButton(void* data,
@ -295,7 +309,7 @@ static void pointerHandleButton(void* data,
if (window->wl.decorations.focus != mainWindow)
return;
_glfw.wl.pointerSerial = serial;
_glfw.wl.serial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
* codes. */
@ -464,6 +478,7 @@ static void keyboardHandleEnter(void* data,
return;
}
_glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = window;
_glfwInputWindowFocus(window, GLFW_TRUE);
}
@ -478,6 +493,7 @@ static void keyboardHandleLeave(void* data,
if (!window)
return;
_glfw.wl.serial = serial;
_glfw.wl.keyboardFocus = NULL;
_glfwInputWindowFocus(window, GLFW_FALSE);
}
@ -561,6 +577,7 @@ static void keyboardHandleKey(void* data,
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
? GLFW_PRESS : GLFW_RELEASE;
_glfw.wl.serial = serial;
_glfwInputKey(window, keyCode, key, action,
_glfw.wl.xkb.modifiers);
@ -592,6 +609,8 @@ static void keyboardHandleModifiers(void* data,
xkb_mod_mask_t mask;
unsigned int modifiers = 0;
_glfw.wl.serial = serial;
if (!_glfw.wl.xkb.keymap)
return;
@ -686,6 +705,70 @@ static const struct wl_seat_listener seatListener = {
seatHandleName,
};
static void dataOfferHandleOffer(void* data,
struct wl_data_offer* dataOffer,
const char* mimeType)
{
}
static const struct wl_data_offer_listener dataOfferListener = {
dataOfferHandleOffer,
};
static void dataDeviceHandleDataOffer(void* data,
struct wl_data_device* dataDevice,
struct wl_data_offer* id)
{
if (_glfw.wl.dataOffer)
wl_data_offer_destroy(_glfw.wl.dataOffer);
_glfw.wl.dataOffer = id;
wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
}
static void dataDeviceHandleEnter(void* data,
struct wl_data_device* dataDevice,
uint32_t serial,
struct wl_surface *surface,
wl_fixed_t x,
wl_fixed_t y,
struct wl_data_offer *id)
{
}
static void dataDeviceHandleLeave(void* data,
struct wl_data_device* dataDevice)
{
}
static void dataDeviceHandleMotion(void* data,
struct wl_data_device* dataDevice,
uint32_t time,
wl_fixed_t x,
wl_fixed_t y)
{
}
static void dataDeviceHandleDrop(void* data,
struct wl_data_device* dataDevice)
{
}
static void dataDeviceHandleSelection(void* data,
struct wl_data_device* dataDevice,
struct wl_data_offer* id)
{
}
static const struct wl_data_device_listener dataDeviceListener = {
dataDeviceHandleDataOffer,
dataDeviceHandleEnter,
dataDeviceHandleLeave,
dataDeviceHandleMotion,
dataDeviceHandleDrop,
dataDeviceHandleSelection,
};
static void wmBaseHandlePing(void* data,
struct xdg_wm_base* wmBase,
uint32_t serial)
@ -740,12 +823,28 @@ static void registryHandleGlobal(void* data,
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
}
}
else if (strcmp(interface, "wl_data_device_manager") == 0)
{
if (!_glfw.wl.dataDeviceManager)
{
_glfw.wl.dataDeviceManager =
wl_registry_bind(registry, name,
&wl_data_device_manager_interface, 1);
}
}
else if (strcmp(interface, "xdg_wm_base") == 0)
{
_glfw.wl.wmBase =
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
}
else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
{
_glfw.wl.decorationManager =
wl_registry_bind(registry, name,
&zxdg_decoration_manager_v1_interface,
1);
}
else if (strcmp(interface, "wp_viewporter") == 0)
{
_glfw.wl.viewporter =
@ -939,6 +1038,12 @@ static void createKeyTables(void)
int _glfwPlatformInit(void)
{
const char *cursorTheme;
const char *cursorSizeStr;
char *cursorSizeEnd;
long cursorSizeLong;
int cursorSize;
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
if (!_glfw.wl.cursor.handle)
{
@ -1059,15 +1164,46 @@ int _glfwPlatformInit(void)
if (_glfw.wl.pointer && _glfw.wl.shm)
{
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
cursorTheme = getenv("XCURSOR_THEME");
cursorSizeStr = getenv("XCURSOR_SIZE");
cursorSize = 32;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unable to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
}
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
{
_glfw.wl.dataDevice =
wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
_glfw.wl.seat);
wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
_glfw.wl.clipboardString = malloc(4096);
if (!_glfw.wl.clipboardString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unable to allocate clipboard memory");
return GLFW_FALSE;
}
_glfw.wl.clipboardSize = 4096;
}
return GLFW_TRUE;
@ -1103,6 +1239,8 @@ void _glfwPlatformTerminate(void)
if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
if (_glfw.wl.cursorThemeHiDPI)
wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
if (_glfw.wl.cursor.handle)
{
_glfw_dlclose(_glfw.wl.cursor.handle);
@ -1121,8 +1259,18 @@ void _glfwPlatformTerminate(void)
wl_shell_destroy(_glfw.wl.shell);
if (_glfw.wl.viewporter)
wp_viewporter_destroy(_glfw.wl.viewporter);
if (_glfw.wl.decorationManager)
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
if (_glfw.wl.wmBase)
xdg_wm_base_destroy(_glfw.wl.wmBase);
if (_glfw.wl.dataSource)
wl_data_source_destroy(_glfw.wl.dataSource);
if (_glfw.wl.dataDevice)
wl_data_device_destroy(_glfw.wl.dataDevice);
if (_glfw.wl.dataOffer)
wl_data_offer_destroy(_glfw.wl.dataOffer);
if (_glfw.wl.dataDeviceManager)
wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
if (_glfw.wl.pointer)
wl_pointer_destroy(_glfw.wl.pointer);
if (_glfw.wl.keyboard)
@ -1142,6 +1290,16 @@ void _glfwPlatformTerminate(void)
wl_display_flush(_glfw.wl.display);
wl_display_disconnect(_glfw.wl.display);
}
if (_glfw.wl.timerfd >= 0)
close(_glfw.wl.timerfd);
if (_glfw.wl.cursorTimerfd >= 0)
close(_glfw.wl.cursorTimerfd);
if (_glfw.wl.clipboardString)
free(_glfw.wl.clipboardString);
if (_glfw.wl.clipboardSendString)
free(_glfw.wl.clipboardSendString);
}
const char* _glfwPlatformGetVersionString(void)
@ -1158,4 +1316,3 @@ const char* _glfwPlatformGetVersionString(void)
#endif
;
}

View file

@ -32,16 +32,16 @@
#include <errno.h>
static void geometry(void* data,
struct wl_output* output,
int32_t x,
int32_t y,
int32_t physicalWidth,
int32_t physicalHeight,
int32_t subpixel,
const char* make,
const char* model,
int32_t transform)
static void outputHandleGeometry(void* data,
struct wl_output* output,
int32_t x,
int32_t y,
int32_t physicalWidth,
int32_t physicalHeight,
int32_t subpixel,
const char* make,
const char* model,
int32_t transform)
{
struct _GLFWmonitor *monitor = data;
char name[1024];
@ -55,12 +55,12 @@ static void geometry(void* data,
monitor->name = _glfw_strdup(name);
}
static void mode(void* data,
struct wl_output* output,
uint32_t flags,
int32_t width,
int32_t height,
int32_t refresh)
static void outputHandleMode(void* data,
struct wl_output* output,
uint32_t flags,
int32_t width,
int32_t height,
int32_t refresh)
{
struct _GLFWmonitor *monitor = data;
GLFWvidmode mode;
@ -81,16 +81,16 @@ static void mode(void* data,
monitor->wl.currentMode = monitor->modeCount - 1;
}
static void done(void* data, struct wl_output* output)
static void outputHandleDone(void* data, struct wl_output* output)
{
struct _GLFWmonitor *monitor = data;
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
}
static void scale(void* data,
struct wl_output* output,
int32_t factor)
static void outputHandleScale(void* data,
struct wl_output* output,
int32_t factor)
{
struct _GLFWmonitor *monitor = data;
@ -98,10 +98,10 @@ static void scale(void* data,
}
static const struct wl_output_listener outputListener = {
geometry,
mode,
done,
scale,
outputHandleGeometry,
outputHandleMode,
outputHandleDone,
outputHandleScale,
};
@ -180,18 +180,18 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
*mode = monitor->modes[monitor->wl.currentMode];
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp getting not supported yet");
"Wayland: Gamma ramp access it not available");
return GLFW_FALSE;
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
const GLFWgammaramp* ramp)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp setting not supported yet");
"Wayland: Gamma ramp access is not available");
}

View file

@ -57,6 +57,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "osmesa_context.h"
#include "wayland-xdg-shell-client-protocol.h"
#include "wayland-xdg-decoration-client-protocol.h"
#include "wayland-viewporter-client-protocol.h"
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
@ -185,6 +186,7 @@ typedef struct _GLFWwindowWayland
struct {
struct xdg_surface* surface;
struct xdg_toplevel* toplevel;
struct zxdg_toplevel_decoration_v1* decoration;
} xdg;
_GLFWcursor* currentCursor;
@ -210,6 +212,7 @@ typedef struct _GLFWwindowWayland
GLFWbool justCreated;
struct {
GLFWbool serverSide;
struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom;
int focus;
@ -230,7 +233,12 @@ typedef struct _GLFWlibraryWayland
struct wl_seat* seat;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
struct wl_data_device_manager* dataDeviceManager;
struct wl_data_device* dataDevice;
struct wl_data_offer* dataOffer;
struct wl_data_source* dataSource;
struct xdg_wm_base* wmBase;
struct zxdg_decoration_manager_v1* decorationManager;
struct wp_viewporter* viewporter;
struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints;
@ -240,13 +248,19 @@ typedef struct _GLFWlibraryWayland
int seatVersion;
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface;
uint32_t pointerSerial;
int cursorTimerfd;
uint32_t serial;
int32_t keyboardRepeatRate;
int32_t keyboardRepeatDelay;
int keyboardLastKey;
int keyboardLastScancode;
char* clipboardString;
size_t clipboardSize;
char* clipboardSendString;
size_t clipboardSendSize;
int timerfd;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
@ -332,10 +346,12 @@ typedef struct _GLFWmonitorWayland
//
typedef struct _GLFWcursorWayland
{
struct wl_cursor_image* image;
struct wl_cursor* cursor;
struct wl_cursor* cursorHiDPI;
struct wl_buffer* buffer;
int width, height;
int xhot, yhot;
int currentImage;
} _GLFWcursorWayland;

View file

@ -39,18 +39,18 @@
#include <poll.h>
static void handlePing(void* data,
struct wl_shell_surface* shellSurface,
uint32_t serial)
static void shellSurfaceHandlePing(void* data,
struct wl_shell_surface* shellSurface,
uint32_t serial)
{
wl_shell_surface_pong(shellSurface, serial);
}
static void handleConfigure(void* data,
struct wl_shell_surface* shellSurface,
uint32_t edges,
int32_t width,
int32_t height)
static void shellSurfaceHandleConfigure(void* data,
struct wl_shell_surface* shellSurface,
uint32_t edges,
int32_t width,
int32_t height)
{
_GLFWwindow* window = data;
float aspectRatio;
@ -94,19 +94,18 @@ static void handleConfigure(void* data,
_glfwInputWindowDamage(window);
}
static void handlePopupDone(void* data,
struct wl_shell_surface* shellSurface)
static void shellSurfaceHandlePopupDone(void* data,
struct wl_shell_surface* shellSurface)
{
}
static const struct wl_shell_surface_listener shellSurfaceListener = {
handlePing,
handleConfigure,
handlePopupDone
shellSurfaceHandlePing,
shellSurfaceHandleConfigure,
shellSurfaceHandlePopupDone
};
static int
createTmpfileCloexec(char* tmpname)
static int createTmpfileCloexec(char* tmpname)
{
int fd;
@ -137,8 +136,7 @@ createTmpfileCloexec(char* tmpname)
* is set to ENOSPC. If posix_fallocate() is not supported, program may
* receive SIGBUS on accessing mmap()'ed file contents instead.
*/
static int
createAnonymousFile(off_t size)
static int createAnonymousFile(off_t size)
{
static const char template[] = "/glfw-shared-XXXXXX";
const char* path;
@ -146,23 +144,37 @@ createAnonymousFile(off_t size)
int fd;
int ret;
path = getenv("XDG_RUNTIME_DIR");
if (!path)
#ifdef HAVE_MEMFD_CREATE
fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd >= 0)
{
errno = ENOENT;
return -1;
// We can add this seal before calling posix_fallocate(), as the file
// is currently zero-sized anyway.
//
// There is also no need to check for the return value, we couldnt do
// anything with it anyway.
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
}
else
#endif
{
path = getenv("XDG_RUNTIME_DIR");
if (!path)
{
errno = ENOENT;
return -1;
}
name = calloc(strlen(path) + sizeof(template), 1);
strcpy(name, path);
strcat(name, template);
fd = createTmpfileCloexec(name);
free(name);
if (fd < 0)
return -1;
}
name = calloc(strlen(path) + sizeof(template), 1);
strcpy(name, path);
strcat(name, template);
fd = createTmpfileCloexec(name);
free(name);
if (fd < 0)
return -1;
ret = posix_fallocate(fd, 0, size);
if (ret != 0)
{
@ -188,7 +200,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Creating a buffer file for %d B failed: %m",
length);
return GLFW_FALSE;
return NULL;
}
data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
@ -197,7 +209,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: mmap failed: %m");
close(fd);
return GLFW_FALSE;
return NULL;
}
pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
@ -262,11 +274,13 @@ static void createDecorations(_GLFWwindow* window)
const GLFWimage image = { 1, 1, data };
GLFWbool opaque = (data[3] == 255);
if (!_glfw.wl.viewporter)
if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
return;
if (!window->wl.decorations.buffer)
window->wl.decorations.buffer = createShmBuffer(&image);
if (!window->wl.decorations.buffer)
return;
createDecoration(&window->wl.decorations.top, window->wl.surface,
window->wl.decorations.buffer, opaque,
@ -307,6 +321,22 @@ static void destroyDecorations(_GLFWwindow* window)
destroyDecoration(&window->wl.decorations.bottom);
}
static void xdgDecorationHandleConfigure(void* data,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode)
{
_GLFWwindow* window = data;
window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
if (!window->wl.decorations.serverSide)
createDecorations(window);
}
static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
xdgDecorationHandleConfigure,
};
// Makes the surface considered as XRGB instead of ARGB.
static void setOpaqueRegion(_GLFWwindow* window)
{
@ -389,9 +419,9 @@ static void checkScaleChange(_GLFWwindow* window)
}
}
static void handleEnter(void *data,
struct wl_surface *surface,
struct wl_output *output)
static void surfaceHandleEnter(void *data,
struct wl_surface *surface,
struct wl_output *output)
{
_GLFWwindow* window = data;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
@ -409,9 +439,9 @@ static void handleEnter(void *data,
checkScaleChange(window);
}
static void handleLeave(void *data,
struct wl_surface *surface,
struct wl_output *output)
static void surfaceHandleLeave(void *data,
struct wl_surface *surface,
struct wl_output *output)
{
_GLFWwindow* window = data;
_GLFWmonitor* monitor = wl_output_get_user_data(output);
@ -431,8 +461,8 @@ static void handleLeave(void *data,
}
static const struct wl_surface_listener surfaceListener = {
handleEnter,
handleLeave
surfaceHandleEnter,
surfaceHandleLeave
};
static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
@ -479,13 +509,11 @@ static GLFWbool createSurface(_GLFWwindow* window,
if (!window->wl.transparent)
setOpaqueRegion(window);
if (window->decorated && !window->monitor)
createDecorations(window);
return GLFW_TRUE;
}
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, int refreshRate)
static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
int refreshRate)
{
if (window->wl.xdg.toplevel)
{
@ -502,7 +530,8 @@ static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, int refres
monitor->wl.output);
}
setIdleInhibitor(window, GLFW_TRUE);
destroyDecorations(window);
if (!window->wl.decorations.serverSide)
destroyDecorations(window);
}
static GLFWbool createShellSurface(_GLFWwindow* window)
@ -538,11 +567,13 @@ static GLFWbool createShellSurface(_GLFWwindow* window)
{
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
setIdleInhibitor(window, GLFW_FALSE);
createDecorations(window);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shellSurface);
setIdleInhibitor(window, GLFW_FALSE);
createDecorations(window);
}
wl_surface_commit(window->wl.surface);
@ -631,6 +662,27 @@ static const struct xdg_surface_listener xdgSurfaceListener = {
xdgSurfaceHandleConfigure
};
static void setXdgDecorations(_GLFWwindow* window)
{
if (_glfw.wl.decorationManager)
{
window->wl.xdg.decoration =
zxdg_decoration_manager_v1_get_toplevel_decoration(
_glfw.wl.decorationManager, window->wl.xdg.toplevel);
zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
&xdgDecorationListener,
window);
zxdg_toplevel_decoration_v1_set_mode(
window->wl.xdg.decoration,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
else
{
window->wl.decorations.serverSide = GLFW_FALSE;
createDecorations(window);
}
}
static GLFWbool createXdgSurface(_GLFWwindow* window)
{
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
@ -678,10 +730,12 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
{
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
setIdleInhibitor(window, GLFW_FALSE);
setXdgDecorations(window);
}
else
{
setIdleInhibitor(window, GLFW_FALSE);
setXdgDecorations(window);
}
wl_surface_commit(window->wl.surface);
@ -690,13 +744,75 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
return GLFW_TRUE;
}
static void
handleEvents(int timeout)
static void setCursorImage(_GLFWwindow* window,
_GLFWcursorWayland* cursorWayland)
{
struct itimerspec timer = {};
struct wl_cursor* wlCursor = cursorWayland->cursor;
struct wl_cursor_image* image;
struct wl_buffer* buffer;
struct wl_surface* surface = _glfw.wl.cursorSurface;
int scale = 1;
if (!wlCursor)
buffer = cursorWayland->buffer;
else
{
if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
{
wlCursor = cursorWayland->cursorHiDPI;
scale = 2;
}
image = wlCursor->images[cursorWayland->currentImage];
buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
timer.it_value.tv_sec = image->delay / 1000;
timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;
timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);
cursorWayland->width = image->width;
cursorWayland->height = image->height;
cursorWayland->xhot = image->hotspot_x;
cursorWayland->yhot = image->hotspot_y;
}
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
surface,
cursorWayland->xhot / scale,
cursorWayland->yhot / scale);
wl_surface_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
cursorWayland->width, cursorWayland->height);
wl_surface_commit(surface);
}
static void incrementCursorImage(_GLFWwindow* window)
{
_GLFWcursor* cursor;
if (!window || window->wl.decorations.focus != mainWindow)
return;
cursor = window->wl.currentCursor;
if (cursor && cursor->wl.cursor)
{
cursor->wl.currentImage += 1;
cursor->wl.currentImage %= cursor->wl.cursor->image_count;
setCursorImage(window, &cursor->wl);
}
}
static void handleEvents(int timeout)
{
struct wl_display* display = _glfw.wl.display;
struct pollfd fds[] = {
{ wl_display_get_fd(display), POLLIN },
{ _glfw.wl.timerfd, POLLIN },
{ _glfw.wl.cursorTimerfd, POLLIN },
};
ssize_t read_ret;
uint64_t repeats, i;
@ -719,7 +835,7 @@ handleEvents(int timeout)
return;
}
if (poll(fds, 2, timeout) > 0)
if (poll(fds, 3, timeout) > 0)
{
if (fds[0].revents & POLLIN)
{
@ -742,6 +858,15 @@ handleEvents(int timeout)
_glfw.wl.keyboardLastScancode, GLFW_REPEAT,
_glfw.wl.xkb.modifiers);
}
if (fds[2].revents & POLLIN)
{
read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
if (read_ret != 8)
return;
incrementCursorImage(_glfw.wl.pointerFocus);
}
}
else
{
@ -860,6 +985,9 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(window);
destroyDecorations(window);
if (window->wl.xdg.decoration)
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
if (window->wl.decorations.buffer)
wl_buffer_destroy(window->wl.decorations.buffer);
@ -956,13 +1084,15 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
}
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,
int numer, int denom)
{
// TODO: find out how to trigger a resize.
// The actual limits are checked in the wl_shell_surface::configure handler.
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
int* width, int* height)
{
_glfwPlatformGetWindowSize(window, width, height);
*width *= window->wl.scale;
@ -973,7 +1103,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
if (window->decorated && !window->monitor)
if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
{
if (top)
*top = _GLFW_DECORATION_TOP;
@ -1102,7 +1232,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
else if (window->wl.shellSurface)
wl_shell_surface_set_toplevel(window->wl.shellSurface);
setIdleInhibitor(window, GLFW_FALSE);
if (window->decorated)
if (!_glfw.wl.decorationManager)
createDecorations(window);
}
_glfwInputWindowMonitor(window, monitor);
@ -1236,6 +1366,9 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int xhot, int yhot)
{
cursor->wl.buffer = createShmBuffer(image);
if (!cursor->wl.buffer)
return GLFW_FALSE;
cursor->wl.width = image->width;
cursor->wl.height = image->height;
cursor->wl.xhot = xhot;
@ -1257,28 +1390,37 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
return GLFW_FALSE;
}
cursor->wl.image = standardCursor->images[0];
cursor->wl.cursor = standardCursor;
cursor->wl.currentImage = 0;
if (_glfw.wl.cursorThemeHiDPI)
{
standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
translateCursorShape(shape));
cursor->wl.cursorHiDPI = standardCursor;
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
// If it's a standard cursor we don't need to do anything here
if (cursor->wl.image)
if (cursor->wl.cursor)
return;
if (cursor->wl.buffer)
wl_buffer_destroy(cursor->wl.buffer);
}
static void handleRelativeMotion(void* data,
struct zwp_relative_pointer_v1* pointer,
uint32_t timeHi,
uint32_t timeLo,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t dxUnaccel,
wl_fixed_t dyUnaccel)
static void relativePointerHandleRelativeMotion(void* data,
struct zwp_relative_pointer_v1* pointer,
uint32_t timeHi,
uint32_t timeLo,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t dxUnaccel,
wl_fixed_t dyUnaccel)
{
_GLFWwindow* window = data;
@ -1291,11 +1433,11 @@ static void handleRelativeMotion(void* data,
}
static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
handleRelativeMotion
relativePointerHandleRelativeMotion
};
static void handleLocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
static void lockedPointerHandleLocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
{
}
@ -1315,14 +1457,14 @@ static void unlockPointer(_GLFWwindow* window)
static void lockPointer(_GLFWwindow* window);
static void handleUnlocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
static void lockedPointerHandleUnlocked(void* data,
struct zwp_locked_pointer_v1* lockedPointer)
{
}
static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
handleLocked,
handleUnlocked
lockedPointerHandleLocked,
lockedPointerHandleUnlocked
};
static void lockPointer(_GLFWwindow* window)
@ -1359,7 +1501,7 @@ static void lockPointer(_GLFWwindow* window)
window->wl.pointerLock.relativePointer = relativePointer;
window->wl.pointerLock.lockedPointer = lockedPointer;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
NULL, 0, 0);
}
@ -1370,10 +1512,8 @@ static GLFWbool isPointerLocked(_GLFWwindow* window)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
struct wl_buffer* buffer;
struct wl_cursor* defaultCursor;
struct wl_cursor_image* image;
struct wl_surface* surface = _glfw.wl.cursorSurface;
struct wl_cursor* defaultCursorHiDPI = NULL;
if (!_glfw.wl.pointer)
return;
@ -1382,7 +1522,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
// If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change
if (window != _glfw.wl.pointerFocus)
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
return;
// Unlock possible pointer lock if no longer disabled.
@ -1392,7 +1532,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
if (cursor)
image = cursor->wl.image;
setCursorImage(window, &cursor->wl);
else
{
defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
@ -1403,33 +1543,19 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
"Wayland: Standard cursor not found");
return;
}
image = defaultCursor->images[0];
}
if (image)
{
buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
surface,
image->hotspot_x,
image->hotspot_y);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
image->width, image->height);
wl_surface_commit(surface);
}
else
{
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
surface,
cursor->wl.xhot,
cursor->wl.yhot);
wl_surface_attach(surface, cursor->wl.buffer, 0, 0);
wl_surface_damage(surface, 0, 0,
cursor->wl.width, cursor->wl.height);
wl_surface_commit(surface);
if (_glfw.wl.cursorThemeHiDPI)
defaultCursorHiDPI =
wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
"left_ptr");
_GLFWcursorWayland cursorWayland = {
defaultCursor,
defaultCursorHiDPI,
NULL,
0, 0,
0, 0,
0
};
setCursorImage(window, &cursorWayland);
}
}
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
@ -1439,24 +1565,213 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
}
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
{
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
NULL, 0, 0);
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
}
}
static void dataSourceHandleTarget(void* data,
struct wl_data_source* dataSource,
const char* mimeType)
{
if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}
}
static void dataSourceHandleSend(void* data,
struct wl_data_source* dataSource,
const char* mimeType,
int fd)
{
const char* string = _glfw.wl.clipboardSendString;
size_t len = _glfw.wl.clipboardSendSize;
int ret;
if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}
if (!string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Copy requested from an invalid string");
return;
}
if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Wrong MIME type asked from clipboard");
close(fd);
return;
}
while (len > 0)
{
ret = write(fd, string, len);
if (ret == -1 && errno == EINTR)
continue;
if (ret == -1)
{
// TODO: also report errno maybe.
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Error while writing the clipboard");
close(fd);
return;
}
len -= ret;
}
close(fd);
}
static void dataSourceHandleCancelled(void* data,
struct wl_data_source* dataSource)
{
wl_data_source_destroy(dataSource);
if (_glfw.wl.dataSource != dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Unknown clipboard data source");
return;
}
_glfw.wl.dataSource = NULL;
}
static const struct wl_data_source_listener dataSourceListener = {
dataSourceHandleTarget,
dataSourceHandleSend,
dataSourceHandleCancelled,
};
void _glfwPlatformSetClipboardString(const char* string)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard setting not implemented yet");
if (_glfw.wl.dataSource)
{
wl_data_source_destroy(_glfw.wl.dataSource);
_glfw.wl.dataSource = NULL;
}
if (_glfw.wl.clipboardSendString)
{
free(_glfw.wl.clipboardSendString);
_glfw.wl.clipboardSendString = NULL;
}
_glfw.wl.clipboardSendString = strdup(string);
if (!_glfw.wl.clipboardSendString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to allocate clipboard string");
return;
}
_glfw.wl.clipboardSendSize = strlen(string);
_glfw.wl.dataSource =
wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
if (!_glfw.wl.dataSource)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to create clipboard source");
free(_glfw.wl.clipboardSendString);
return;
}
wl_data_source_add_listener(_glfw.wl.dataSource,
&dataSourceListener,
NULL);
wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
wl_data_device_set_selection(_glfw.wl.dataDevice,
_glfw.wl.dataSource,
_glfw.wl.serial);
}
static GLFWbool growClipboardString(void)
{
char* clipboard = _glfw.wl.clipboardString;
clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
if (!clipboard)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to grow clipboard string");
return GLFW_FALSE;
}
_glfw.wl.clipboardString = clipboard;
_glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
return GLFW_TRUE;
}
const char* _glfwPlatformGetClipboardString(void)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Clipboard getting not implemented yet");
return NULL;
int fds[2];
int ret;
size_t len = 0;
if (!_glfw.wl.dataOffer)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"No clipboard data has been sent yet");
return NULL;
}
ret = pipe2(fds, O_CLOEXEC);
if (ret < 0)
{
// TODO: also report errno maybe?
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to create clipboard pipe fds");
return NULL;
}
wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);
close(fds[1]);
// XXX: this is a huge hack, this function shouldnt be synchronous!
handleEvents(-1);
while (1)
{
// Grow the clipboard if we need to paste something bigger, there is no
// shrink operation yet.
if (len + 4096 > _glfw.wl.clipboardSize)
{
if (!growClipboardString())
{
close(fds[0]);
return NULL;
}
}
// Then read from the fd to the clipboard, handling all known errors.
ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);
if (ret == 0)
break;
if (ret == -1 && errno == EINTR)
continue;
if (ret == -1)
{
// TODO: also report errno maybe.
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Impossible to read from clipboard fd");
close(fds[0]);
return NULL;
}
len += ret;
}
close(fds[0]);
if (len + 1 > _glfw.wl.clipboardSize)
{
if (!growClipboardString())
return NULL;
}
_glfw.wl.clipboardString[len] = '\0';
return _glfw.wl.clipboardString;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)

View file

@ -780,8 +780,9 @@ static GLFWbool initExtensions(void)
//
static void getSystemContentScale(float* xscale, float* yscale)
{
// NOTE: Default to the display-wide DPI as we don't currently have a policy
// for which monitor a window is considered to be on
// NOTE: Fall back to the display-wide DPI instead of RandR monitor DPI if
// Xft.dpi retrieval below fails as we don't currently have an exact
// policy for which monitor a window is considered to "be on"
float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *

View file

@ -422,7 +422,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
}
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
{
@ -438,6 +438,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
XRRFreeGamma(gamma);
return GLFW_TRUE;
}
else if (_glfw.x11.vidmode.available)
{
@ -449,6 +450,13 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
XF86VidModeGetGammaRamp(_glfw.x11.display,
_glfw.x11.screen,
ramp->size, ramp->red, ramp->green, ramp->blue);
return GLFW_TRUE;
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Gamma ramp access not supported by server");
return GLFW_FALSE;
}
}
@ -481,6 +489,11 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
(unsigned short*) ramp->green,
(unsigned short*) ramp->blue);
}
else
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Gamma ramp access not supported by server");
}
}

View file

@ -175,29 +175,6 @@ static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer po
event->xproperty.atom == notification->xselection.property;
}
// Translates a GLFW standard cursor to a font cursor shape
//
static int translateCursorShape(int shape)
{
switch (shape)
{
case GLFW_ARROW_CURSOR:
return XC_left_ptr;
case GLFW_IBEAM_CURSOR:
return XC_xterm;
case GLFW_CROSSHAIR_CURSOR:
return XC_crosshair;
case GLFW_HAND_CURSOR:
return XC_hand1;
case GLFW_HRESIZE_CURSOR:
return XC_sb_h_double_arrow;
case GLFW_VRESIZE_CURSOR:
return XC_sb_v_double_arrow;
}
return 0;
}
// Translates an X event modifier state mask
//
static int translateState(int state)
@ -231,23 +208,6 @@ static int translateKey(int scancode)
return _glfw.x11.keycodes[scancode];
}
// Return the GLFW window corresponding to the specified X11 window
//
static _GLFWwindow* findWindowByHandle(Window handle)
{
_GLFWwindow* window;
if (XFindContext(_glfw.x11.display,
handle,
_glfw.x11.context,
(XPointer*) &window) != 0)
{
return NULL;
}
return window;
}
// Sends an EWMH or ICCCM event to the window manager
//
static void sendEventToWM(_GLFWwindow* window, Atom type,
@ -632,6 +592,15 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
Visual* visual, int depth)
{
int width = wndconfig->width;
int height = wndconfig->height;
if (wndconfig->scaleToMonitor)
{
width *= _glfw.x11.contentScaleX;
height *= _glfw.x11.contentScaleY;
}
// Create a colormap based on the visual used by the current context
window->x11.colormap = XCreateColormap(_glfw.x11.display,
_glfw.x11.root,
@ -657,7 +626,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
window->x11.handle = XCreateWindow(_glfw.x11.display,
_glfw.x11.root,
0, 0,
wndconfig->width, wndconfig->height,
width, height,
0, // Border width
depth, // Color depth
InputOutput,
@ -760,7 +729,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
XFree(hints);
}
updateNormalHints(window, wndconfig->width, wndconfig->height);
updateNormalHints(window, width, height);
// Set ICCCM WM_CLASS property
{
@ -1264,8 +1233,10 @@ static void processEvent(XEvent *event)
return;
}
window = findWindowByHandle(event->xany.window);
if (window == NULL)
if (XFindContext(_glfw.x11.display,
event->xany.window,
_glfw.x11.context,
(XPointer*) &window) != 0)
{
// This is an event for a window that has already been destroyed
return;
@ -1484,12 +1455,20 @@ static void processEvent(XEvent *event)
case EnterNotify:
{
// XEnterWindowEvent is XCrossingEvent
const int x = event->xcrossing.x;
const int y = event->xcrossing.y;
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
// ignore the defined cursor for hidden cursor mode
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
updateCursorImage(window);
_glfwInputCursorEnter(window, GLFW_TRUE);
_glfwInputCursorPos(window, x, y);
window->x11.lastCursorPosX = x;
window->x11.lastCursorPosY = y;
return;
}
@ -2479,6 +2458,14 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
Atom* states;
unsigned long i;
GLFWbool maximized = GLFW_FALSE;
if (!_glfw.x11.NET_WM_STATE ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
return maximized;
}
const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE,
@ -2814,8 +2801,24 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display,
translateCursorShape(shape));
int native = 0;
if (shape == GLFW_ARROW_CURSOR)
native = XC_left_ptr;
else if (shape == GLFW_IBEAM_CURSOR)
native = XC_xterm;
else if (shape == GLFW_CROSSHAIR_CURSOR)
native = XC_crosshair;
else if (shape == GLFW_HAND_CURSOR)
native = XC_hand1;
else if (shape == GLFW_HRESIZE_CURSOR)
native = XC_sb_h_double_arrow;
else if (shape == GLFW_VRESIZE_CURSOR)
native = XC_sb_v_double_arrow;
else
return GLFW_FALSE;
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
if (!cursor->x11.handle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,

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