mirror of
https://github.com/glfw/glfw.git
synced 2024-11-29 13:32:01 +00:00
Add glfwGetError
Related to #970. If you have opinions on the design or implementation of this function, please come join us in #970 before it is frozen for release.
This commit is contained in:
parent
16ddfafeaa
commit
6350641f0a
@ -122,6 +122,7 @@ information on what to include when reporting a bug.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
- Added `glfwGetError` function for querying the last error code (#970)
|
||||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
||||||
scancodes for keys (#830)
|
scancodes for keys (#830)
|
||||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||||
|
@ -30,6 +30,7 @@ successfully initialized, and only from the main thread.
|
|||||||
|
|
||||||
- @ref glfwGetVersion
|
- @ref glfwGetVersion
|
||||||
- @ref glfwGetVersionString
|
- @ref glfwGetVersionString
|
||||||
|
- @ref glfwGetError
|
||||||
- @ref glfwSetErrorCallback
|
- @ref glfwSetErrorCallback
|
||||||
- @ref glfwInitHint
|
- @ref glfwInitHint
|
||||||
- @ref glfwInit
|
- @ref glfwInit
|
||||||
@ -131,9 +132,25 @@ not very helpful when trying to figure out _why_ the error occurred. Other
|
|||||||
functions have no return value reserved for errors, so error notification needs
|
functions have no return value reserved for errors, so error notification needs
|
||||||
a separate channel. Finally, far from all GLFW functions have return values.
|
a separate channel. Finally, far from all GLFW functions have return values.
|
||||||
|
|
||||||
This is where the error callback comes in. This callback is called whenever an
|
The last error code for the calling thread can be queried at any time with @ref
|
||||||
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
|
glfwGetError.
|
||||||
called regardless of whether GLFW is initialized.
|
|
||||||
|
@code
|
||||||
|
int error = glfwGetError();
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
If no error has occurred since the last call, @ref GLFW_NO_ERROR is returned.
|
||||||
|
The error is cleared before the function returns.
|
||||||
|
|
||||||
|
The error code indicates the general category of the error. Some error codes,
|
||||||
|
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
||||||
|
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
||||||
|
|
||||||
|
GLFW usually has much more information about the error than its general category
|
||||||
|
at the point where it occurred. This is where the error callback comes in.
|
||||||
|
This callback is called whenever an error occurs. It is set with @ref
|
||||||
|
glfwSetErrorCallback, a function that may be called regardless of whether GLFW
|
||||||
|
is initialized.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
glfwSetErrorCallback(error_callback);
|
glfwSetErrorCallback(error_callback);
|
||||||
@ -150,24 +167,23 @@ void error_callback(int error, const char* description)
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The error code indicates the general category of the error. Some error codes,
|
The error callback is called after the error code is set, so calling @ref
|
||||||
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
glfwGetError from within the error callback returns the same value as the
|
||||||
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
callback argument.
|
||||||
|
|
||||||
Reported errors are never fatal. As long as GLFW was successfully initialized,
|
__Reported errors are never fatal.__ As long as GLFW was successfully
|
||||||
it will remain initialized and in a safe state until terminated regardless of
|
initialized, it will remain initialized and in a safe state until terminated
|
||||||
how many errors occur. If an error occurs during initialization that causes
|
regardless of how many errors occur. If an error occurs during initialization
|
||||||
@ref glfwInit to fail, any part of the library that was initialized will be
|
that causes @ref glfwInit to fail, any part of the library that was initialized
|
||||||
safely terminated.
|
will be safely terminated.
|
||||||
|
|
||||||
The description string is only valid until the error callback returns, as it may
|
The description string is only valid until the error callback returns, as it may
|
||||||
have been generated specifically for that error. This lets GLFW provide much
|
have been generated specifically for that error. This lets GLFW provide much
|
||||||
more specific error descriptions but means you must make a copy if you want to
|
more specific error descriptions but means you must make a copy if you want to
|
||||||
keep the description string.
|
keep the description string.
|
||||||
|
|
||||||
@note Relying on erroneous behavior is not forward compatible. In other words,
|
Do not rely on a currently invalid call to generate a specific error, as in the
|
||||||
do not rely on a currently invalid call to generate a specific error, as that
|
future that same call may generate a different error or become valid.
|
||||||
same call may in future versions generate a different error or become valid.
|
|
||||||
|
|
||||||
|
|
||||||
@section coordinate_systems Coordinate systems
|
@section coordinate_systems Coordinate systems
|
||||||
|
@ -4,6 +4,15 @@
|
|||||||
|
|
||||||
@section news_33 New features in 3.3
|
@section news_33 New features in 3.3
|
||||||
|
|
||||||
|
|
||||||
|
@subsection news_33_geterror Error query
|
||||||
|
|
||||||
|
GLFW now supports querying the last error code for the calling thread with @ref
|
||||||
|
glfwGetError.
|
||||||
|
|
||||||
|
@see @ref error_handling
|
||||||
|
|
||||||
|
|
||||||
@subsection news_33_maximize Window maximization callback
|
@subsection news_33_maximize Window maximization callback
|
||||||
|
|
||||||
GLFW now supports window maximization notifications with @ref
|
GLFW now supports window maximization notifications with @ref
|
||||||
|
@ -546,6 +546,13 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @ingroup init
|
* @ingroup init
|
||||||
* @{ */
|
* @{ */
|
||||||
|
/*! @brief No error has occurred.
|
||||||
|
*
|
||||||
|
* No error has occurred.
|
||||||
|
*
|
||||||
|
* @analysis Yay.
|
||||||
|
*/
|
||||||
|
#define GLFW_NO_ERROR 0
|
||||||
/*! @brief GLFW has not been initialized.
|
/*! @brief GLFW has not been initialized.
|
||||||
*
|
*
|
||||||
* This occurs if a GLFW function was called that must not be called unless the
|
* This occurs if a GLFW function was called that must not be called unless the
|
||||||
@ -1607,11 +1614,38 @@ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI const char* glfwGetVersionString(void);
|
GLFWAPI const char* glfwGetVersionString(void);
|
||||||
|
|
||||||
|
/*! @brief Returns and clears the last error for the calling thread.
|
||||||
|
*
|
||||||
|
* This function returns and clears the [error code](@ref error) of the last
|
||||||
|
* error that occurred on the calling thread. If no error has occurred since
|
||||||
|
* the last call, it returns @ref GLFW_NO_ERROR.
|
||||||
|
*
|
||||||
|
* @return The last error code for the calling thread, or @ref GLFW_NO_ERROR.
|
||||||
|
*
|
||||||
|
* @errors None.
|
||||||
|
*
|
||||||
|
* @remark This function may be called before @ref glfwInit.
|
||||||
|
*
|
||||||
|
* @thread_safety This function may be called from any thread.
|
||||||
|
*
|
||||||
|
* @sa @ref error_handling
|
||||||
|
* @sa @ref glfwSetErrorCallback
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup init
|
||||||
|
*/
|
||||||
|
GLFWAPI int glfwGetError(void);
|
||||||
|
|
||||||
/*! @brief Sets the error callback.
|
/*! @brief Sets the error callback.
|
||||||
*
|
*
|
||||||
* This function sets the error callback, which is called with an error code
|
* This function sets the error callback, which is called with an error code
|
||||||
* and a human-readable description each time a GLFW error occurs.
|
* and a human-readable description each time a GLFW error occurs.
|
||||||
*
|
*
|
||||||
|
* The error code is set before the callback is called. Calling @ref
|
||||||
|
* glfwGetError from the error callback will return the same value as the error
|
||||||
|
* code argument.
|
||||||
|
*
|
||||||
* The error callback is called on the thread where the error occurred. If you
|
* The error callback is called on the thread where the error occurred. If you
|
||||||
* are using GLFW from multiple threads, your error callback needs to be
|
* are using GLFW from multiple threads, your error callback needs to be
|
||||||
* written accordingly.
|
* written accordingly.
|
||||||
@ -1634,6 +1668,7 @@ GLFWAPI const char* glfwGetVersionString(void);
|
|||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref error_handling
|
* @sa @ref error_handling
|
||||||
|
* @sa @ref glfwGetError
|
||||||
*
|
*
|
||||||
* @since Added in version 3.0.
|
* @since Added in version 3.0.
|
||||||
*
|
*
|
||||||
|
38
src/init.c
38
src/init.c
@ -43,6 +43,7 @@ _GLFWlibrary _glfw = { GLFW_FALSE };
|
|||||||
// These are outside of _glfw so they can be used before initialization and
|
// These are outside of _glfw so they can be used before initialization and
|
||||||
// after termination
|
// after termination
|
||||||
//
|
//
|
||||||
|
static int _glfwErrorCode;
|
||||||
static GLFWerrorfun _glfwErrorCallback;
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
static _GLFWinitconfig _glfwInitHints =
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
{
|
{
|
||||||
@ -113,7 +114,11 @@ static void terminate(void)
|
|||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
_glfwPlatformTerminate();
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
|
if (_glfwPlatformIsValidTls(&_glfw.error))
|
||||||
|
_glfwErrorCode = (int) (intptr_t) _glfwPlatformGetTls(&_glfw.error);
|
||||||
|
|
||||||
_glfwPlatformDestroyTls(&_glfw.context);
|
_glfwPlatformDestroyTls(&_glfw.context);
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.error);
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
}
|
}
|
||||||
@ -125,6 +130,11 @@ static void terminate(void)
|
|||||||
|
|
||||||
void _glfwInputError(int error, const char* format, ...)
|
void _glfwInputError(int error, const char* format, ...)
|
||||||
{
|
{
|
||||||
|
if (_glfw.initialized)
|
||||||
|
_glfwPlatformSetTls(&_glfw.error, (void*) (intptr_t) error);
|
||||||
|
else
|
||||||
|
_glfwErrorCode = error;
|
||||||
|
|
||||||
if (_glfwErrorCallback)
|
if (_glfwErrorCallback)
|
||||||
{
|
{
|
||||||
char buffer[8192];
|
char buffer[8192];
|
||||||
@ -164,15 +174,19 @@ GLFWAPI int glfwInit(void)
|
|||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
_glfw.hints.init = _glfwInitHints;
|
_glfw.hints.init = _glfwInitHints;
|
||||||
|
|
||||||
if (!_glfwPlatformCreateTls(&_glfw.context))
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwPlatformInit())
|
if (!_glfwPlatformInit())
|
||||||
{
|
{
|
||||||
terminate();
|
terminate();
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_glfwPlatformCreateTls(&_glfw.error))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwPlatformCreateTls(&_glfw.context))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
_glfwPlatformSetTls(&_glfw.error, (void*) (intptr_t) _glfwErrorCode);
|
||||||
|
|
||||||
_glfw.initialized = GLFW_TRUE;
|
_glfw.initialized = GLFW_TRUE;
|
||||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
@ -223,6 +237,24 @@ GLFWAPI const char* glfwGetVersionString(void)
|
|||||||
return _glfwPlatformGetVersionString();
|
return _glfwPlatformGetVersionString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI int glfwGetError(void)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (_glfw.initialized)
|
||||||
|
{
|
||||||
|
error = (int) (intptr_t) _glfwPlatformGetTls(&_glfw.error);
|
||||||
|
_glfwPlatformSetTls(&_glfw.error, (intptr_t) GLFW_NO_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = _glfwErrorCode;
|
||||||
|
_glfwErrorCode = GLFW_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||||
{
|
{
|
||||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||||
|
@ -517,6 +517,7 @@ struct _GLFWlibrary
|
|||||||
|
|
||||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
|
_GLFWtls error;
|
||||||
_GLFWtls context;
|
_GLFWtls context;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -653,6 +654,7 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
|||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||||
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||||
|
GLFWbool _glfwPlatformIsValidTls(_GLFWtls* tls);
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
|||||||
|
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
assert(tls->posix.allocated == GLFW_TRUE);
|
|
||||||
if (tls->posix.allocated)
|
if (tls->posix.allocated)
|
||||||
pthread_key_delete(tls->posix.key);
|
pthread_key_delete(tls->posix.key);
|
||||||
memset(tls, 0, sizeof(_GLFWtls));
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
@ -70,3 +69,8 @@ void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
|||||||
pthread_setspecific(tls->posix.key, value);
|
pthread_setspecific(tls->posix.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformIsValidTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
return tls->posix.allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
|||||||
|
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
assert(tls->win32.allocated == GLFW_TRUE);
|
|
||||||
if (tls->win32.allocated)
|
if (tls->win32.allocated)
|
||||||
TlsFree(tls->win32.index);
|
TlsFree(tls->win32.index);
|
||||||
memset(tls, 0, sizeof(_GLFWtls));
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
@ -70,3 +69,8 @@ void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
|||||||
TlsSetValue(tls->win32.index, value);
|
TlsSetValue(tls->win32.index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformIsValidTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
return tls->win32.allocated;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user