Compare commits

..

2 Commits

Author SHA1 Message Date
Camilla Löwy 413ba1dceb Wayland: Fix EGL buffer swap blocking indefinitely
This re-implements the wait for a surface frame that previously happened
inside EGL, so that we can add a reasonable timeout.  That allows
applications to make progress despite the window being suspended.

This initial implementation still has a race between glfwHideWindow and
glfwSwapBuffers when rendering on a separate thread.

Related to #1350
Related to #2582
Related to #2640
Related to #2719
Related to #2723
Related to #2800
2026-02-20 16:28:19 +01:00
Camilla Löwy e59b5e1fda Fix cleanup on success in threaded rendering test 2026-02-18 19:13:16 +01:00
35 changed files with 401 additions and 516 deletions
-2
View File
@@ -3,5 +3,3 @@
.gitattributes export-ignore
.travis.yml export-ignore
.appveyor.yml export-ignore
.mailmap export-ignore
.github export-ignore
+8 -8
View File
@@ -17,7 +17,7 @@ jobs:
CC: clang
CFLAGS: -Werror
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
@@ -57,7 +57,7 @@ jobs:
MACOSX_DEPLOYMENT_TARGET: 10.11
CMAKE_OSX_ARCHITECTURES: x86_64;arm64
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Configure Null shared library
run: cmake -B build-null-shared -D GLFW_BUILD_COCOA=OFF -D BUILD_SHARED_LIBS=ON
@@ -74,27 +74,27 @@ jobs:
- name: Build Cocoa shared library
run: cmake --build build-cocoa-shared --parallel
build-windows-msvc:
name: Windows (MSVC)
build-windows-vs2022:
name: Windows (VS2022)
runs-on: windows-latest
timeout-minutes: 4
env:
CFLAGS: /WX
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4
- name: Configure Win32 shared x86 library
run: cmake -B build-win32-shared-x86 -A Win32 -D BUILD_SHARED_LIBS=ON
run: cmake -B build-win32-shared-x86 -G "Visual Studio 17 2022" -A Win32 -D BUILD_SHARED_LIBS=ON
- name: Build Win32 shared x86 library
run: cmake --build build-win32-shared-x86 --parallel
- name: Configure Win32 static x64 library
run: cmake -B build-win32-static-x64 -A x64
run: cmake -B build-win32-static-x64 -G "Visual Studio 17 2022" -A x64
- name: Build Win32 static x64 library
run: cmake --build build-win32-static-x64 --parallel
- name: Configure Win32 shared x64 library
run: cmake -B build-win32-shared-x64 -A x64 -D BUILD_SHARED_LIBS=ON
run: cmake -B build-win32-shared-x64 -G "Visual Studio 17 2022" -A x64 -D BUILD_SHARED_LIBS=ON
- name: Build Win32 shared x64 library
run: cmake --build build-win32-shared-x64 --parallel
+1 -1
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16...3.28 FATAL_ERROR)
project(GLFW VERSION 3.5.1 LANGUAGES C HOMEPAGE_URL "https://www.glfw.org/")
project(GLFW VERSION 3.5.0 LANGUAGES C HOMEPAGE_URL "https://www.glfw.org/")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
-10
View File
@@ -6,12 +6,10 @@ excludes other invaluable contributions like language bindings and text and
video tutorials.
- Bobyshev Alexander
- Alzathar
- Laurent Aphecetche
- Matt Arsenault
- Takuro Ashie
- ashishgamedev
- avagordon01
- David Avedissian
- Luca Bacci
- Keith Bauer
@@ -57,9 +55,7 @@ video tutorials.
- Bill Currie
- Jason Daly
- danhambleton
- danijel1023
- Jarrod Davis
- Aaron Day
- decce
- Olivier Delannoy
- Paul R. Deppe
@@ -79,7 +75,6 @@ video tutorials.
- Nikita Fediuchin
- Felipe Ferreira
- Michael Fogleman
- Folling
- forworldm
- Jason Francis
- Gerald Franz
@@ -100,7 +95,6 @@ video tutorials.
- Andrew Gutekanst
- Stephen Gutekanst
- Jonathan Hale
- halx99
- Daniel Hauser
- hdf89shfdfs
- Moritz Heinemann
@@ -167,7 +161,6 @@ video tutorials.
- Bryce Mehring
- Jonathan Mercier
- Marcel Metz
- Lucas Michaudel
- Liam Middlebrook
- mightgoyardstill
- Mihail
@@ -184,7 +177,6 @@ video tutorials.
- Jon Morton
- Pierre Moulon
- Martins Mozeiko
- Tomáš Mráz
- Pascal Muetschard
- James Murphy
- Julian Møller
@@ -231,7 +223,6 @@ video tutorials.
- Philip Rideout
- Eddie Ringle
- Max Risuhin
- road2react
- Joe Roback
- Jorge Rodriguez
- Jari Ronkainen
@@ -239,7 +230,6 @@ video tutorials.
- Ed Ropple
- Aleksey Rybalkin
- Mikko Rytkönen
- saikyun
- Riku Salminen
- Yoshinori Sano
- Brandon Schaefer
+1 -14
View File
@@ -118,10 +118,6 @@ guide](https://github.com/glfw/glfw/blob/master/docs/CONTRIBUTING.md) for
information on what to include when reporting a bug.
## Changelog since 3.5
None.
## Changelog since 3.4
- Added `GLFW_UNLIMITED_MOUSE_BUTTONS` input mode that allows mouse buttons beyond
@@ -131,11 +127,8 @@ None.
- Updated minimum CMake version to 3.16 (#2541)
- Removed support for building with original MinGW (#2540)
- [Win32] Removed support for Windows XP and Vista (#2505)
- [Win32] Bugfix: Media keys were reported with a scancode of 256 (#1768,#2417,#2625)
- [Cocoa] Added `QuartzCore` framework as link-time dependency
- [Cocoa] Removed support for OS X 10.10 Yosemite and earlier (#2506)
- [Cocoa] Bugfix: Cmd+Period, Ctrl+Tab and Ctrl+Esc key events were not emitted
(#1362,#2278)
- [Wayland] Bugfix: The fractional scaling related objects were not destroyed
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
@@ -159,14 +152,8 @@ None.
- [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination
- [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494)
- [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes
- [Wayland] Bugfix: Mouse wheel scroll distance was incorrect on some compositors
- [Wayland] Bugfix: `glfwSwapBuffers` would halt with nonzero swap interval when window
was suspended (#1350,#2582,#2640,#2719,#2723,#2800,#2827)
- [Wayland] Bugfix: `glfwPostEmptyEvent` would leak a callback proxy (#2836)
- [Wayland] Bugfix: `glfwHideWindow` did not always send its request immediately
- [Wayland] Bugfix: Some event types were not always processed by `glfwPollEvents` or
`glfwWait*Events` (#2793,#2795)
- [Wayland] Bugfix: Scaled framebuffer size was sometimes incorect (#2713,#2810)
was suspended (#1350,#2582,#2640,#2719,#2723,#2800)
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
-8
View File
@@ -3,14 +3,6 @@
[TOC]
## Why was there no 3.5.0 release?
Due to a misconfigured tool, an incorrect `3.5.0` tag was briefly made available in the
main Git repository. Thanks to the manual intervention of many packaging volunteers this
has been almost entirely rolled back. To make sure the first actual release of GLFW 3.5
replaces the incorrect tag everywhere, the first release is named 3.5.1.
## New features {#features}
### Unlimited mouse buttons {#unlimited_mouse_buttons}
+1 -9
View File
@@ -298,7 +298,7 @@ extern "C" {
* release is made that does not contain any API changes.
* @ingroup init
*/
#define GLFW_VERSION_REVISION 1
#define GLFW_VERSION_REVISION 0
/*! @} */
/*! @brief One.
@@ -1344,10 +1344,6 @@ extern "C" {
#define GLFW_PLATFORM_NULL 0x00060005
/*! @} */
/* Reserved platform define for external Emscripten ports: 0x00060006
* See https://github.com/pongasoft/emscripten-glfw
*/
#define GLFW_DONT_CARE -1
@@ -6174,10 +6170,6 @@ GLFWAPI GLFWwindow* glfwGetCurrentContext(void);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
*
* @remark __Wayland:__ When the swap interval is greater than zero and the
* window is not in view, this function may take a few extra milliseconds to
* return.
*
* @remark __EGL:__ The context of the specified window must be current on the
* calling thread.
*
+5 -10
View File
@@ -10,7 +10,7 @@ add_library(glfw ${GLFW_LIBRARY_TYPE}
# The time, thread and module code is shared between all backends on a given OS,
# including the null backend, which still needs those bits to be functional
if (APPLE)
target_sources(glfw PRIVATE macos_time.h macos_time.c posix_thread.h
target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h
posix_module.c posix_thread.c)
elseif (WIN32)
target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c
@@ -46,7 +46,7 @@ endif()
if (GLFW_BUILD_X11)
target_compile_definitions(glfw PRIVATE _GLFW_X11)
target_sources(glfw PRIVATE x11_platform.h x11_init.c
target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c
x11_monitor.c x11_window.c xkb_unicode.c
glx_context.c)
endif()
@@ -145,11 +145,11 @@ endif()
if (GLFW_BUILD_COCOA)
target_link_libraries(glfw PRIVATE "-framework Cocoa"
"-framework IOKit"
"-framework CoreFoundation"
"-framework QuartzCore")
list(APPEND glfw_PKG_LIBS "-framework Cocoa"
"-framework IOKit"
"-framework QuartzCore")
set(glfw_PKG_DEPS "")
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore")
endif()
if (GLFW_BUILD_WAYLAND)
@@ -234,11 +234,6 @@ if (UNIX AND NOT APPLE)
endif()
endif()
if (APPLE)
target_link_libraries(glfw PRIVATE "-framework CoreFoundation")
list(APPEND glfw_PKG_LIBS "-framework CoreFoundation")
endif()
if (WIN32)
if (GLFW_USE_HYBRID_HPG)
target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG)
+36 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -450,6 +450,41 @@ static GLFWbool initializeTIS(void)
@end // GLFWApplicationDelegate
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwLoadLocalVulkanLoaderCocoa(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
+3 -1
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -291,6 +291,8 @@ void _glfwRestoreVideoModeCocoa(_GLFWmonitor* monitor);
float _glfwTransformYCocoa(float y);
void* _glfwLoadLocalVulkanLoaderCocoa(void);
GLFWbool _glfwInitNSGL(void);
void _glfwTerminateNSGL(void);
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+4 -4
View File
@@ -26,7 +26,7 @@
#include "internal.h"
#if defined(GLFW_BUILD_MACOS_TIMER)
#if defined(GLFW_BUILD_COCOA_TIMER)
#include <mach/mach_time.h>
@@ -40,7 +40,7 @@ void _glfwPlatformInitTimer(void)
mach_timebase_info_data_t info;
mach_timebase_info(&info);
_glfw.timer.macos.frequency = (info.denom * 1e9) / info.numer;
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
}
uint64_t _glfwPlatformGetTimerValue(void)
@@ -50,8 +50,8 @@ uint64_t _glfwPlatformGetTimerValue(void)
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return _glfw.timer.macos.frequency;
return _glfw.timer.ns.frequency;
}
#endif // GLFW_BUILD_MACOS_TIMER
#endif // GLFW_BUILD_COCOA_TIMER
+4 -4
View File
@@ -24,12 +24,12 @@
//
//========================================================================
#define GLFW_MACOS_LIBRARY_TIMER_STATE _GLFWtimerMacOS macos;
#define GLFW_COCOA_LIBRARY_TIMER_STATE _GLFWtimerNS ns;
// macOS-specific global timer data
// Cocoa-specific global timer data
//
typedef struct _GLFWtimerMacOS
typedef struct _GLFWtimerNS
{
uint64_t frequency;
} _GLFWtimerMacOS;
} _GLFWtimerNS;
+1 -29
View File
@@ -1,5 +1,5 @@
//========================================================================
// GLFW 3.5 Cocoa - www.glfw.org
// GLFW 3.5 macOS - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
//
@@ -599,34 +599,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
}
- (BOOL)performKeyEquivalent:(NSEvent *)event
{
// HACK: Some key combinations are consumed before reaching keyDown:
// so we claim those events and emit them here
const int key = translateKey([event keyCode]);
const int mods = translateFlags([event modifierFlags]);
if (mods & GLFW_MOD_CONTROL)
{
if (key == GLFW_KEY_TAB || key == GLFW_KEY_ESCAPE)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
if (mods & GLFW_MOD_SUPER)
{
if (key == GLFW_KEY_PERIOD)
{
_glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
return YES;
}
}
return [super performKeyEquivalent:event];
}
- (void)scrollWheel:(NSEvent *)event
{
double deltaX = [event scrollingDeltaX];
+1 -1
View File
@@ -195,7 +195,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
{
current = alternatives + i;
if (desired->stereo && !current->stereo)
if (desired->stereo > 0 && current->stereo == 0)
{
// Stereo is a hard constraint
continue;
+1 -2
View File
@@ -32,7 +32,6 @@
#include <stdlib.h>
#include <assert.h>
// Return a description of the specified EGL error
//
static const char* getEGLErrorString(EGLint error)
@@ -675,7 +674,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.egl.KHR_create_context_no_error)
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
SET_ATTRIB(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
}
if (mask)
+15 -13
View File
@@ -119,7 +119,9 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
u->stereo = getGLXFBConfigAttrib(n, GLX_STEREO);
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = GLFW_TRUE;
if (_glfw.glx.ARB_multisample)
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
@@ -365,7 +367,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalEXT");
if (_glfw.glx.SwapIntervalEXT)
_glfw.glx.EXT_swap_control = true;
_glfw.glx.EXT_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_SGI_swap_control"))
@@ -374,7 +376,7 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalSGI");
if (_glfw.glx.SwapIntervalSGI)
_glfw.glx.SGI_swap_control = true;
_glfw.glx.SGI_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_MESA_swap_control"))
@@ -383,17 +385,17 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXSwapIntervalMESA");
if (_glfw.glx.SwapIntervalMESA)
_glfw.glx.MESA_swap_control = true;
_glfw.glx.MESA_swap_control = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_ARB_multisample"))
_glfw.glx.ARB_multisample = true;
_glfw.glx.ARB_multisample = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
_glfw.glx.ARB_framebuffer_sRGB = true;
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
_glfw.glx.EXT_framebuffer_sRGB = true;
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context"))
{
@@ -401,23 +403,23 @@ GLFWbool _glfwInitGLX(void)
getProcAddressGLX("glXCreateContextAttribsARB");
if (_glfw.glx.CreateContextAttribsARB)
_glfw.glx.ARB_create_context = true;
_glfw.glx.ARB_create_context = GLFW_TRUE;
}
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
_glfw.glx.ARB_create_context_robustness = true;
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
_glfw.glx.ARB_create_context_profile = true;
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = true;
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
_glfw.glx.ARB_create_context_no_error = true;
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = true;
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
return GLFW_TRUE;
}
+4 -4
View File
@@ -49,18 +49,18 @@ static GLFWerrorfun _glfwErrorCallback;
static GLFWallocator _glfwInitAllocator;
static _GLFWinitconfig _glfwInitHints =
{
.hatButtons = true,
.hatButtons = GLFW_TRUE,
.angleType = GLFW_ANGLE_PLATFORM_TYPE_NONE,
.platformID = GLFW_ANY_PLATFORM,
.vulkanLoader = NULL,
.ns =
{
.menubar = true,
.chdir = true
.menubar = GLFW_TRUE,
.chdir = GLFW_TRUE
},
.x11 =
{
.xcbVulkanSurface = true,
.xcbVulkanSurface = GLFW_TRUE,
},
.wl =
{
+11 -7
View File
@@ -333,8 +333,10 @@ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
{
assert(window != NULL);
assert(isfinite(xoffset));
assert(isfinite(yoffset));
assert(xoffset > -FLT_MAX);
assert(xoffset < FLT_MAX);
assert(yoffset > -FLT_MAX);
assert(yoffset < FLT_MAX);
if (window->callbacks.scroll)
window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
@@ -373,8 +375,10 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
{
assert(window != NULL);
assert(isfinite(xpos));
assert(isfinite(ypos));
assert(xpos > -FLT_MAX);
assert(xpos < FLT_MAX);
assert(ypos > -FLT_MAX);
assert(ypos < FLT_MAX);
if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
return;
@@ -432,7 +436,6 @@ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
assert(js != NULL);
assert(axis >= 0);
assert(axis < js->axisCount);
assert(isfinite(value));
js->axes[axis] = value;
}
@@ -815,7 +818,8 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (!isfinite(xpos) || !isfinite(ypos))
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid cursor position %f %f",
@@ -1495,7 +1499,7 @@ GLFWAPI void glfwSetTime(double time)
{
_GLFW_REQUIRE_INIT();
if (!isfinite(time) || time < 0.0 || time > 18446744073.0)
if (time != time || time < 0.0 || time > 18446744073.0)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
return;
+50 -50
View File
@@ -375,16 +375,16 @@ struct _GLFWerror
//
struct _GLFWinitconfig
{
bool hatButtons;
GLFWbool hatButtons;
int angleType;
int platformID;
PFN_vkGetInstanceProcAddr vulkanLoader;
struct {
bool menubar;
bool chdir;
GLFWbool menubar;
GLFWbool chdir;
} ns;
struct {
bool xcbVulkanSurface;
GLFWbool xcbVulkanSurface;
} x11;
struct {
int libdecorMode;
@@ -403,18 +403,18 @@ struct _GLFWwndconfig
int ypos;
int width;
int height;
bool resizable;
bool visible;
bool decorated;
bool focused;
bool autoIconify;
bool floating;
bool maximized;
bool centerCursor;
bool focusOnShow;
bool mousePassthrough;
bool scaleToMonitor;
bool scaleFramebuffer;
GLFWbool resizable;
GLFWbool visible;
GLFWbool decorated;
GLFWbool focused;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool maximized;
GLFWbool centerCursor;
GLFWbool focusOnShow;
GLFWbool mousePassthrough;
GLFWbool scaleToMonitor;
GLFWbool scaleFramebuffer;
struct {
char frameName[256];
} ns;
@@ -423,8 +423,8 @@ struct _GLFWwndconfig
char instanceName[256];
} x11;
struct {
bool keymenu;
bool showDefault;
GLFWbool keymenu;
GLFWbool showDefault;
} win32;
struct {
char appId[256];
@@ -443,15 +443,15 @@ struct _GLFWctxconfig
int source;
int major;
int minor;
bool forward;
bool debug;
bool noerror;
GLFWbool forward;
GLFWbool debug;
GLFWbool noerror;
int profile;
int robustness;
int release;
_GLFWwindow* share;
struct {
bool offline;
GLFWbool offline;
} nsgl;
};
@@ -476,11 +476,11 @@ struct _GLFWfbconfig
int accumBlueBits;
int accumAlphaBits;
int auxBuffers;
bool stereo;
GLFWbool stereo;
int samples;
bool sRGB;
bool doublebuffer;
bool transparent;
GLFWbool sRGB;
GLFWbool doublebuffer;
GLFWbool transparent;
uintptr_t handle;
};
@@ -807,22 +807,22 @@ struct _GLFWlibrary
EGLint major, minor;
GLFWbool prefix;
bool KHR_create_context;
bool KHR_create_context_no_error;
bool KHR_gl_colorspace;
bool KHR_get_all_proc_addresses;
bool KHR_context_flush_control;
bool EXT_client_extensions;
bool EXT_platform_base;
bool EXT_platform_x11;
bool EXT_platform_wayland;
bool EXT_present_opaque;
bool ANGLE_platform_angle;
bool ANGLE_platform_angle_opengl;
bool ANGLE_platform_angle_d3d;
bool ANGLE_platform_angle_vulkan;
bool ANGLE_platform_angle_metal;
bool MESA_platform_surfaceless;
GLFWbool KHR_create_context;
GLFWbool KHR_create_context_no_error;
GLFWbool KHR_gl_colorspace;
GLFWbool KHR_get_all_proc_addresses;
GLFWbool KHR_context_flush_control;
GLFWbool EXT_client_extensions;
GLFWbool EXT_platform_base;
GLFWbool EXT_platform_x11;
GLFWbool EXT_platform_wayland;
GLFWbool EXT_present_opaque;
GLFWbool ANGLE_platform_angle;
GLFWbool ANGLE_platform_angle_opengl;
GLFWbool ANGLE_platform_angle_d3d;
GLFWbool ANGLE_platform_angle_vulkan;
GLFWbool ANGLE_platform_angle_metal;
GLFWbool MESA_platform_surfaceless;
void* handle;
@@ -866,14 +866,14 @@ struct _GLFWlibrary
void* handle;
char* extensions[2];
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
bool KHR_surface;
bool KHR_win32_surface;
bool MVK_macos_surface;
bool EXT_metal_surface;
bool KHR_xlib_surface;
bool KHR_xcb_surface;
bool KHR_wayland_surface;
bool EXT_headless_surface;
GLFWbool KHR_surface;
GLFWbool KHR_win32_surface;
GLFWbool MVK_macos_surface;
GLFWbool EXT_metal_surface;
GLFWbool KHR_xlib_surface;
GLFWbool KHR_xcb_surface;
GLFWbool KHR_wayland_surface;
GLFWbool EXT_headless_surface;
} vk;
struct {
+2 -3
View File
@@ -467,15 +467,14 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
unsigned short* values;
GLFWgammaramp ramp;
const GLFWgammaramp* original;
assert(gamma > 0.f);
assert(isfinite(gamma));
assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT();
assert(handle != NULL);
if (!isfinite(gamma) || gamma <= 0.f)
if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return;
+5 -6
View File
@@ -28,7 +28,7 @@
#if defined(GLFW_BUILD_WIN32_TIMER) || \
defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_MACOS_TIMER) || \
defined(GLFW_BUILD_COCOA_TIMER) || \
defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \
@@ -184,7 +184,7 @@
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__)
#define GLFW_BUILD_MACOS_TIMER
#define GLFW_BUILD_COCOA_TIMER
#else
#define GLFW_BUILD_POSIX_TIMER
#endif
@@ -192,9 +192,9 @@
#if defined(GLFW_BUILD_WIN32_TIMER)
#include "win32_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_WIN32_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_MACOS_TIMER)
#include "macos_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_MACOS_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_COCOA_TIMER)
#include "cocoa_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_COCOA_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
@@ -207,7 +207,6 @@
#endif
#if defined(_GLFW_WAYLAND) || defined(_GLFW_X11)
#include "posix_poll.h"
#define GLFW_BUILD_POSIX_POLL
#endif
+11 -44
View File
@@ -34,40 +34,6 @@
#define _GLFW_FIND_LOADER 1
#define _GLFW_REQUIRE_LOADER 2
#if defined(__APPLE__)
#include <CoreFoundation/CoreFoundation.h>
static void* loadLocalVulkanLoaderMacOS(void)
{
CFBundleRef bundle = CFBundleGetMainBundle();
if (!bundle)
return NULL;
CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
if (!frameworksUrl)
return NULL;
CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
if (!loaderUrl)
{
CFRelease(frameworksUrl);
return NULL;
}
char path[PATH_MAX];
void* handle = NULL;
if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
handle = _glfwPlatformLoadModule(path);
CFRelease(loaderUrl);
CFRelease(frameworksUrl);
return handle;
}
#endif // __APPLE__
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -91,10 +57,11 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
#elif defined(_WIN32)
_glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
#elif defined(__APPLE__)
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = loadLocalVulkanLoaderMacOS();
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
#elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else
@@ -163,21 +130,21 @@ GLFWbool _glfwInitVulkan(int mode)
for (i = 0; i < count; i++)
{
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
_glfw.vk.KHR_surface = true;
_glfw.vk.KHR_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
_glfw.vk.KHR_win32_surface = true;
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
_glfw.vk.MVK_macos_surface = true;
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
_glfw.vk.EXT_metal_surface = true;
_glfw.vk.EXT_metal_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
_glfw.vk.KHR_xlib_surface = true;
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
_glfw.vk.KHR_xcb_surface = true;
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
_glfw.vk.KHR_wayland_surface = true;
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0)
_glfw.vk.EXT_headless_surface = true;
_glfw.vk.EXT_headless_surface = GLFW_TRUE;
}
_glfw_free(ep);
+14 -6
View File
@@ -186,22 +186,28 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = FIND_ATTRIB_VALUE(WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = FIND_ATTRIB_VALUE(WGL_AUX_BUFFERS_ARB);
u->stereo = FIND_ATTRIB_VALUE(WGL_STEREO_ARB);
if (FIND_ATTRIB_VALUE(WGL_STEREO_ARB))
u->stereo = GLFW_TRUE;
if (_glfw.wgl.ARB_multisample)
u->samples = FIND_ATTRIB_VALUE(WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
u->sRGB = FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (FIND_ATTRIB_VALUE(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = GLFW_TRUE;
}
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (FIND_ATTRIB_VALUE(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
u->sRGB = true;
u->sRGB = GLFW_TRUE;
}
}
}
@@ -255,7 +261,9 @@ static int choosePixelFormatWGL(_GLFWwindow* window,
u->accumAlphaBits = pfd.cAccumAlphaBits;
u->auxBuffers = pfd.cAuxBuffers;
u->stereo = (pfd.dwFlags & PFD_STEREO);
if (pfd.dwFlags & PFD_STEREO)
u->stereo = GLFW_TRUE;
}
u->handle = pixelFormat;
@@ -656,7 +664,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
SET_ATTRIB(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
}
// NOTE: Only request an explicitly versioned context when necessary, as
+12 -12
View File
@@ -336,18 +336,18 @@ typedef struct _GLFWlibraryWGL
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool EXT_swap_control;
bool EXT_colorspace;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_pixel_format;
bool ARB_create_context;
bool ARB_create_context_profile;
bool EXT_create_context_es2_profile;
bool ARB_create_context_robustness;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
GLFWbool EXT_swap_control;
GLFWbool EXT_colorspace;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_pixel_format;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryWGL;
// Win32-specific per-window data
+4 -5
View File
@@ -711,12 +711,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
const int mods = getKeyMods();
scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
if (!(scancode & 0xff))
if (!scancode)
{
// NOTE: Both media keys and the synthetic key messages from Windows
// Clipboard History are reported with a scancode of zero
// HACK: Map the virtual key to a scancode but preserve extended bit
scancode |= MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
// NOTE: Some synthetic key messages have a scancode of zero
// HACK: Map the virtual key back to a usable scancode
scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
}
// HACK: Alt+PrtSc has a different scancode than just PrtSc
+39 -38
View File
@@ -32,7 +32,7 @@
#include <string.h>
#include <stdlib.h>
#include <float.h>
#include <math.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW event API //////
@@ -135,9 +135,9 @@ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscal
{
assert(window != NULL);
assert(xscale > 0.f);
assert(isfinite(xscale));
assert(xscale < FLT_MAX);
assert(yscale > 0.f);
assert(isfinite(yscale));
assert(yscale < FLT_MAX);
if (window->callbacks.scale)
window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
@@ -265,16 +265,16 @@ void glfwDefaultWindowHints(void)
// The default is a focused, visible, resizable window with decorations
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
_glfw.hints.window.resizable = true;
_glfw.hints.window.visible = true;
_glfw.hints.window.decorated = true;
_glfw.hints.window.focused = true;
_glfw.hints.window.autoIconify = true;
_glfw.hints.window.centerCursor = true;
_glfw.hints.window.focusOnShow = true;
_glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE;
_glfw.hints.window.focusOnShow = GLFW_TRUE;
_glfw.hints.window.xpos = GLFW_ANY_POSITION;
_glfw.hints.window.ypos = GLFW_ANY_POSITION;
_glfw.hints.window.scaleFramebuffer = true;
_glfw.hints.window.scaleFramebuffer = GLFW_TRUE;
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
// double buffered
@@ -285,7 +285,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.framebuffer.alphaBits = 8;
_glfw.hints.framebuffer.depthBits = 24;
_glfw.hints.framebuffer.stencilBits = 8;
_glfw.hints.framebuffer.doublebuffer = true;
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
// The default is to select the highest available refresh rate
_glfw.hints.refreshRate = GLFW_DONT_CARE;
@@ -331,40 +331,40 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.framebuffer.auxBuffers = value;
return;
case GLFW_STEREO:
_glfw.hints.framebuffer.stereo = value;
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_DOUBLEBUFFER:
_glfw.hints.framebuffer.doublebuffer = value;
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_TRANSPARENT_FRAMEBUFFER:
_glfw.hints.framebuffer.transparent = value;
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SAMPLES:
_glfw.hints.framebuffer.samples = value;
return;
case GLFW_SRGB_CAPABLE:
_glfw.hints.framebuffer.sRGB = value;
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_RESIZABLE:
_glfw.hints.window.resizable = value;
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_DECORATED:
_glfw.hints.window.decorated = value;
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUSED:
_glfw.hints.window.focused = value;
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_AUTO_ICONIFY:
_glfw.hints.window.autoIconify = value;
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FLOATING:
_glfw.hints.window.floating = value;
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_MAXIMIZED:
_glfw.hints.window.maximized = value;
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_VISIBLE:
_glfw.hints.window.visible = value;
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_POSITION_X:
_glfw.hints.window.xpos = value;
@@ -373,29 +373,29 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.window.ypos = value;
return;
case GLFW_WIN32_KEYBOARD_MENU:
_glfw.hints.window.win32.keymenu = value;
_glfw.hints.window.win32.keymenu = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_WIN32_SHOWDEFAULT:
_glfw.hints.window.win32.showDefault = value;
_glfw.hints.window.win32.showDefault = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value;
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_TO_MONITOR:
_glfw.hints.window.scaleToMonitor = value;
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_SCALE_FRAMEBUFFER:
case GLFW_COCOA_RETINA_FRAMEBUFFER:
_glfw.hints.window.scaleFramebuffer = value;
_glfw.hints.window.scaleFramebuffer = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CENTER_CURSOR:
_glfw.hints.window.centerCursor = value;
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUS_ON_SHOW:
_glfw.hints.window.focusOnShow = value;
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_MOUSE_PASSTHROUGH:
_glfw.hints.window.mousePassthrough = value;
_glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CLIENT_API:
_glfw.hints.context.client = value;
@@ -413,13 +413,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
_glfw.hints.context.robustness = value;
return;
case GLFW_OPENGL_FORWARD_COMPAT:
_glfw.hints.context.forward = value;
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CONTEXT_DEBUG:
_glfw.hints.context.debug = value;
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_CONTEXT_NO_ERROR:
_glfw.hints.context.noerror = value;
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_OPENGL_PROFILE:
_glfw.hints.context.profile = value;
@@ -776,7 +776,7 @@ GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
{
assert(isfinite(opacity));
assert(opacity == opacity);
assert(opacity >= 0.f);
assert(opacity <= 1.f);
@@ -785,7 +785,7 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
_GLFWwindow* window = (_GLFWwindow*) handle;
assert(window != NULL);
if (!isfinite(opacity) || opacity < 0.f || opacity > 1.f)
if (opacity != opacity || opacity < 0.f || opacity > 1.f)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
return;
@@ -1178,10 +1178,11 @@ GLFWAPI void glfwWaitEvents(void)
GLFWAPI void glfwWaitEventsTimeout(double timeout)
{
_GLFW_REQUIRE_INIT();
assert(isfinite(timeout));
assert(timeout == timeout);
assert(timeout >= 0.0);
assert(timeout <= DBL_MAX);
if (!isfinite(timeout) || timeout < 0.0)
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
{
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
return;
+9 -7
View File
@@ -135,7 +135,7 @@ static void registryHandleGlobal(void* userData,
{
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(8, version));
_glfw_min(5, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
}
}
@@ -244,7 +244,10 @@ static void libdecorReadyCallback(void* userData,
uint32_t time)
{
_glfw.wl.libdecor.ready = GLFW_TRUE;
wl_callback_destroy(callback);
assert(_glfw.wl.libdecor.callback == callback);
wl_callback_destroy(_glfw.wl.libdecor.callback);
_glfw.wl.libdecor.callback = NULL;
}
static const struct wl_callback_listener libdecorReadyListener =
@@ -798,8 +801,6 @@ int _glfwInitWayland(void)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
_glfw.wl.libdecor.libdecor_frame_is_visible_ = (PFN_libdecor_frame_is_visible)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_is_visible");
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
_glfwPlatformGetModuleSymbol(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
@@ -831,7 +832,6 @@ int _glfwInitWayland(void)
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
!_glfw.wl.libdecor.libdecor_frame_is_visible_ ||
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
@@ -881,8 +881,10 @@ int _glfwInitWayland(void)
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
// Create sync point to "know" when libdecor is ready for use
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &libdecorReadyListener, NULL);
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(_glfw.wl.libdecor.callback,
&libdecorReadyListener,
NULL);
}
}
+4 -5
View File
@@ -42,6 +42,8 @@ typedef struct VkWaylandSurfaceCreateInfoKHR
typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
#include "posix_poll.h"
typedef int (* PFN_wl_display_flush)(struct wl_display* display);
typedef void (* PFN_wl_display_cancel_read)(struct wl_display* display);
typedef int (* PFN_wl_display_dispatch_pending)(struct wl_display* display);
@@ -311,7 +313,6 @@ typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
typedef bool (* PFN_libdecor_frame_is_visible)(struct libdecor_frame*);
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
@@ -337,7 +338,6 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
#define libdecor_frame_is_visible _glfw.wl.libdecor.libdecor_frame_is_visible_
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
@@ -377,6 +377,7 @@ typedef struct _GLFWwindowWayland
GLFWbool transparent;
GLFWbool scaleFramebuffer;
struct wl_surface* surface;
struct wl_callback* callback;
struct {
struct wl_event_queue* queue;
@@ -497,8 +498,6 @@ typedef struct _GLFWlibraryWayland
double pointerY;
double scrollX;
double scrollY;
double discreteX;
double discreteY;
int button;
int action;
} pending;
@@ -596,6 +595,7 @@ typedef struct _GLFWlibraryWayland
struct {
void* handle;
struct libdecor* context;
struct wl_callback* callback;
GLFWbool ready;
PFN_libdecor_new libdecor_new_;
PFN_libdecor_unref libdecor_unref_;
@@ -617,7 +617,6 @@ typedef struct _GLFWlibraryWayland
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
PFN_libdecor_frame_is_visible libdecor_frame_is_visible_;
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
+74 -116
View File
@@ -24,9 +24,7 @@
//
//========================================================================
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#define _GNU_SOURCE
#include "internal.h"
@@ -57,11 +55,10 @@
#define GLFW_BORDER_SIZE 4
#define GLFW_CAPTION_HEIGHT 24
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
#define GLFW_PENDING_DISCRETE 16
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
static int createTmpfileCloexec(char* tmpname)
{
@@ -201,16 +198,6 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
return buffer;
}
static void callbackHandleDone(void* userData, struct wl_callback* callback, uint32_t data)
{
wl_callback_destroy(callback);
}
static const struct wl_callback_listener noopCallbackListener =
{
callbackHandleDone
};
static void createFallbackEdge(_GLFWwindow* window,
_GLFWfallbackEdgeWayland* edge,
struct wl_surface* parent,
@@ -478,9 +465,8 @@ static void resizeFramebuffer(_GLFWwindow* window)
{
if (window->wl.fractionalScale)
{
// Round halfway away from zero per fractional-scale-v1 protocol spec
window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator + 60) / 120;
window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator + 60) / 120;
window->wl.fbWidth = (window->wl.width * window->wl.scalingNumerator) / 120;
window->wl.fbHeight = (window->wl.height * window->wl.scalingNumerator) / 120;
}
else
{
@@ -897,10 +883,6 @@ void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
libdecor_frame_commit(frame, frameState, config);
libdecor_state_free(frameState);
// NOTE: Frame visibility must only be set after a frame state has been committed
if (window->decorated != libdecor_frame_is_visible(window->wl.libdecor.frame))
libdecor_frame_set_visibility(window->wl.libdecor.frame, window->decorated);
if (window->wl.activated != activated)
{
window->wl.activated = activated;
@@ -982,39 +964,36 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
return GLFW_FALSE;
}
struct libdecor_state* frameState =
libdecor_state_new(window->wl.width, window->wl.height);
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
libdecor_state_free(frameState);
if (strlen(window->wl.appId))
libdecor_frame_set_app_id(window->wl.libdecor.frame, window->wl.appId);
libdecor_frame_set_title(window->wl.libdecor.frame, window->title);
if (window->resizable)
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
}
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->minwidth,
window->minheight);
}
else
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->maxwidth,
window->maxheight);
}
if (!window->resizable)
{
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
LIBDECOR_ACTION_RESIZE);
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
window->wl.width,
window->wl.height);
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
window->wl.width,
window->wl.height);
}
if (window->monitor)
@@ -1025,11 +1004,12 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
}
else
{
// Frame visibility is applied in libdecorFrameHandleConfigure
if (window->wl.maximized)
libdecor_frame_set_maximized(window->wl.libdecor.frame);
if (!window->decorated)
libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
setIdleInhibitor(window, GLFW_FALSE);
}
@@ -1382,27 +1362,24 @@ static void handleEvents(double* timeout)
#endif
GLFWbool event = GLFW_FALSE;
enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD };
enum { DISPLAY_FD, KEYREPEAT_FD, CURSOR_FD, LIBDECOR_FD };
struct pollfd fds[] =
{
[DISPLAY_FD] = { wl_display_get_fd(_glfw.wl.display), POLLIN },
[KEYREPEAT_FD] = { _glfw.wl.keyRepeatTimerfd, POLLIN },
[CURSOR_FD] = { _glfw.wl.cursorTimerfd, POLLIN }
[CURSOR_FD] = { _glfw.wl.cursorTimerfd, POLLIN },
[LIBDECOR_FD] = { -1, POLLIN }
};
if (_glfw.wl.libdecor.context)
fds[LIBDECOR_FD].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
while (!event)
{
if (_glfw.wl.libdecor.context)
{
// Dispatch unconditionally because it also processes non-Wayland events
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
}
while (wl_display_prepare_read(_glfw.wl.display) != 0)
{
if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
event = GLFW_TRUE;
return;
}
// If an error other than EAGAIN happens, we have likely been disconnected
@@ -1421,11 +1398,6 @@ static void handleEvents(double* timeout)
return;
}
double immediate = 0.0;
if (event)
timeout = &immediate;
if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout))
{
wl_display_cancel_read(_glfw.wl.display);
@@ -1472,6 +1444,12 @@ static void handleEvents(double* timeout)
if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
incrementCursorImage();
}
if (fds[LIBDECOR_FD].revents & POLLIN)
{
if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
event = GLFW_TRUE;
}
}
}
@@ -1762,9 +1740,7 @@ static void pointerHandleFrame(void* userData, struct wl_pointer* pointer)
if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON)
processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action);
if (_glfw.wl.pending.events & GLFW_PENDING_DISCRETE)
processPointerScroll(_glfw.wl.pending.discreteX, _glfw.wl.pending.discreteY);
else if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY);
memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending));
@@ -1790,21 +1766,6 @@ static void pointerHandleAxisDiscrete(void* userData,
{
}
static void pointerHandleAxisValue120(void* data,
struct wl_pointer* pointer,
uint32_t axis,
int32_t value120)
{
if (!_glfw.wl.pointerSurface)
return;
_glfw.wl.pending.events |= GLFW_PENDING_DISCRETE;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.discreteX = -(value120 / 120.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.discreteY = -(value120 / 120.0);
}
static const struct wl_pointer_listener pointerListener =
{
pointerHandleEnter,
@@ -1815,8 +1776,7 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleFrame,
pointerHandleAxisSource,
pointerHandleAxisStop,
pointerHandleAxisDiscrete,
pointerHandleAxisValue120
pointerHandleAxisDiscrete
};
static void keyboardHandleKeymap(void* userData,
@@ -1839,7 +1799,7 @@ static void keyboardHandleKeymap(void* userData,
return;
}
mapStr = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (mapStr == MAP_FAILED)
{
close(fd);
@@ -2341,37 +2301,41 @@ void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device)
GLFWbool _glfwWaitForEGLFrameWayland(_GLFWwindow* window)
{
double timeout = 0.02;
while (window->wl.egl.callback)
for (int i = 0; i < window->wl.egl.interval; i++)
{
if (wl_display_prepare_read_queue(_glfw.wl.display, window->wl.egl.queue) != 0)
double timeout = 0.02;
while (window->wl.egl.callback)
{
while (wl_display_prepare_read_queue(_glfw.wl.display, window->wl.egl.queue) != 0)
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
if (!flushDisplay())
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLIN };
if (!_glfwPollPOSIX(&fd, 1, &timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
continue;
}
if (!flushDisplay())
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
window->wl.egl.callback = wl_surface_frame(window->wl.egl.wrapper);
wl_callback_add_listener(window->wl.egl.callback, &frameCallbackListener, window);
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLIN };
if (!_glfwPollPOSIX(&fd, 1, &timeout))
{
wl_display_cancel_read(_glfw.wl.display);
return GLFW_FALSE;
}
wl_display_read_events(_glfw.wl.display);
wl_display_dispatch_queue_pending(_glfw.wl.display, window->wl.egl.queue);
// Commit the old buffer for every frame but the last one so we get new callbacks
if (i + 1 < window->wl.egl.interval)
wl_surface_commit(window->wl.surface);
}
window->wl.egl.callback = wl_surface_frame(window->wl.egl.wrapper);
wl_callback_add_listener(window->wl.egl.callback, &frameCallbackListener, window);
// If the window is hidden when the wait is over then don't swap
return window->wl.visible;
}
@@ -2422,8 +2386,6 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window,
wl_proxy_set_queue((struct wl_proxy*) window->wl.egl.wrapper,
window->wl.egl.queue);
window->wl.egl.interval = 1;
if (!_glfwInitEGL())
return GLFW_FALSE;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
@@ -2737,8 +2699,6 @@ void _glfwHideWindowWayland(_GLFWwindow* window)
wl_surface_attach(window->wl.surface, NULL, 0, 0);
wl_surface_commit(window->wl.surface);
flushDisplay();
}
}
@@ -2953,9 +2913,7 @@ void _glfwWaitEventsTimeoutWayland(double timeout)
void _glfwPostEmptyEventWayland(void)
{
struct wl_callback* callback = wl_display_sync(_glfw.wl.display);
wl_callback_add_listener(callback, &noopCallbackListener, NULL);
wl_display_sync(_glfw.wl.display);
flushDisplay();
}
+15 -15
View File
@@ -452,6 +452,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(V
typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
#include "xkb_unicode.h"
#include "posix_poll.h"
#define GLFW_X11_WINDOW_STATE _GLFWwindowX11 x11;
#define GLFW_X11_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11;
#define GLFW_X11_MONITOR_STATE _GLFWmonitorX11 x11;
@@ -460,7 +463,6 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(Vk
#define GLFW_GLX_CONTEXT_STATE _GLFWcontextGLX glx;
#define GLFW_GLX_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
#define GLFW_INVALID_CODEPOINT 0xffffffffu
// GLX-specific per-context data
//
@@ -503,18 +505,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool SGI_swap_control;
bool EXT_swap_control;
bool MESA_swap_control;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_create_context;
bool ARB_create_context_profile;
bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
GLFWbool SGI_swap_control;
GLFWbool EXT_swap_control;
GLFWbool MESA_swap_control;
GLFWbool ARB_multisample;
GLFWbool ARB_framebuffer_sRGB;
GLFWbool EXT_framebuffer_sRGB;
GLFWbool ARB_create_context;
GLFWbool ARB_create_context_profile;
GLFWbool ARB_create_context_robustness;
GLFWbool EXT_create_context_es2_profile;
GLFWbool ARB_create_context_no_error;
GLFWbool ARB_context_flush_control;
} _GLFWlibraryGLX;
// X11-specific per-window data
@@ -983,8 +985,6 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
unsigned char** value);
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym);
void _glfwGrabErrorHandlerX11(void);
void _glfwReleaseErrorHandlerX11(void);
void _glfwInputErrorX11(int error, const char* message);
+2 -2
View File
@@ -1308,7 +1308,7 @@ static void processEvent(XEvent *event)
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint != GLFW_INVALID_CODEPOINT)
_glfwInputChar(window, codepoint, mods, plain);
}
@@ -2944,7 +2944,7 @@ const char* _glfwGetScancodeNameX11(int scancode)
if (keysym == NoSymbol)
return NULL;
const uint32_t codepoint = _glfwKeySym2UnicodeX11(keysym);
const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
if (codepoint == GLFW_INVALID_CODEPOINT)
return NULL;
+3 -3
View File
@@ -27,7 +27,7 @@
#include "internal.h"
#if defined(_GLFW_X11)
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
/*
* Marcus: This code was originally written by Markus G. Kuhn.
@@ -906,7 +906,7 @@ static const struct codepair {
// Convert XKB KeySym to Unicode
//
uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
uint32_t _glfwKeySym2Unicode(unsigned int keysym)
{
int min = 0;
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
@@ -939,5 +939,5 @@ uint32_t _glfwKeySym2UnicodeX11(unsigned int keysym)
return GLFW_INVALID_CODEPOINT;
}
#endif // _GLFW_X11
#endif // _GLFW_WAYLAND or _GLFW_X11
+30
View File
@@ -0,0 +1,30 @@
//========================================================================
// GLFW 3.5 Linux - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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.
//
//========================================================================
#define GLFW_INVALID_CODEPOINT 0xffffffffu
uint32_t _glfwKeySym2Unicode(unsigned int keysym);
+30 -75
View File
@@ -23,10 +23,7 @@
//
//========================================================================
//
// This test is intended to verify that the posting of empty events works.
// Background colors are produced on a secondary thread, which then wakes
// the main thread with glfwPostEmptyEvent when a new one is available.
// This allows the main thread to wait for events unconditionally.
// This test is intended to verify that posting of empty events works
//
//========================================================================
@@ -40,53 +37,25 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct State
{
mtx_t lock;
bool running;
bool needs_update;
int width;
int height;
float r, g, b;
};
static volatile int running = GLFW_TRUE;
static void error_callback(int error, const char* description)
{
fprintf(stderr, "Error: %s\n", description);
}
static void generate_color(struct State* state)
{
const float r = (float) rand() / (float) RAND_MAX;
const float g = (float) rand() / (float) RAND_MAX;
const float b = (float) rand() / (float) RAND_MAX;
const float l = sqrtf(r * r + g * g + b * b);
mtx_lock(&state->lock);
state->r = r / l;
state->g = g / l;
state->b = b / l;
state->needs_update = true;
mtx_unlock(&state->lock);
}
static int thread_main(void* data)
{
struct State* const state = data;
struct timespec time;
srand((unsigned int) time(NULL));
while (state->running)
while (running)
{
generate_color(state);
glfwPostEmptyEvent();
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
time.tv_sec += 1;
thrd_sleep(&time, NULL);
glfwPostEmptyEvent();
}
return 0;
@@ -95,38 +64,28 @@ static int thread_main(void* data)
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
static void framebuffer_size_callback(GLFWwindow* window, int width, int height)
static float nrand(void)
{
struct State* const state = glfwGetWindowUserPointer(window);
mtx_lock(&state->lock);
state->width = width;
state->height = height;
state->needs_update = true;
mtx_unlock(&state->lock);
return (float) rand() / (float) RAND_MAX;
}
int main(void)
{
struct State state = { .running = true };
int result;
thrd_t thread;
GLFWwindow* window;
if (mtx_init(&state.lock, mtx_plain) != thrd_success)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
generate_color(&state);
srand((unsigned int) time(NULL));
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
GLFWwindow* window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
window = glfwCreateWindow(640, 480, "Empty Event Test", NULL, NULL);
if (!window)
{
glfwTerminate();
@@ -136,13 +95,8 @@ int main(void)
glfwMakeContextCurrent(window);
gladLoadGL(glfwGetProcAddress);
glfwSetKeyCallback(window, key_callback);
glfwSetWindowUserPointer(window, &state);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwGetFramebufferSize(window, &state.width, &state.height);
thrd_t color_thread;
if (thrd_create(&color_thread, thread_main, &state) != thrd_success)
if (thrd_create(&thread, thread_main, NULL) != thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
@@ -150,27 +104,28 @@ int main(void)
exit(EXIT_FAILURE);
}
while (!glfwWindowShouldClose(window))
while (running)
{
if (state.needs_update)
{
mtx_lock(&state.lock);
glViewport(0, 0, state.width, state.height);
glClearColor(state.r, state.g, state.b, 1.f);
state.needs_update = false;
mtx_unlock(&state.lock);
int width, height;
float r = nrand(), g = nrand(), b = nrand();
float l = (float) sqrt(r * r + g * g + b * b);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
}
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(r / l, g / l, b / l, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwWaitEvents();
if (glfwWindowShouldClose(window))
running = GLFW_FALSE;
}
glfwHideWindow(window);
state.running = false;
thrd_join(color_thread, NULL);
mtx_destroy(&state.lock);
thrd_join(thread, &result);
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);