mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +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
|
||||
|
||||
- Added `glfwGetError` function for querying the last error code (#970)
|
||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
||||
scancodes for keys (#830)
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
|
@ -30,6 +30,7 @@ successfully initialized, and only from the main thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
- @ref glfwGetError
|
||||
- @ref glfwSetErrorCallback
|
||||
- @ref glfwInitHint
|
||||
- @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
|
||||
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
|
||||
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
|
||||
called regardless of whether GLFW is initialized.
|
||||
The last error code for the calling thread can be queried at any time with @ref
|
||||
glfwGetError.
|
||||
|
||||
@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
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@ -150,24 +167,23 @@ void error_callback(int error, const char* description)
|
||||
}
|
||||
@endcode
|
||||
|
||||
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.
|
||||
The error callback is called after the error code is set, so calling @ref
|
||||
glfwGetError from within the error callback returns the same value as the
|
||||
callback argument.
|
||||
|
||||
Reported errors are never fatal. As long as GLFW was successfully initialized,
|
||||
it will remain initialized and in a safe state until terminated regardless of
|
||||
how many errors occur. If an error occurs during initialization that causes
|
||||
@ref glfwInit to fail, any part of the library that was initialized will be
|
||||
safely terminated.
|
||||
__Reported errors are never fatal.__ As long as GLFW was successfully
|
||||
initialized, it will remain initialized and in a safe state until terminated
|
||||
regardless of how many errors occur. If an error occurs during initialization
|
||||
that causes @ref glfwInit to fail, any part of the library that was initialized
|
||||
will be safely terminated.
|
||||
|
||||
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
|
||||
more specific error descriptions but means you must make a copy if you want to
|
||||
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 that
|
||||
same call may in future versions generate a different error or become valid.
|
||||
Do not rely on a currently invalid call to generate a specific error, as in the
|
||||
future that same call may generate a different error or become valid.
|
||||
|
||||
|
||||
@section coordinate_systems Coordinate systems
|
||||
|
@ -4,6 +4,15 @@
|
||||
|
||||
@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
|
||||
|
||||
GLFW now supports window maximization notifications with @ref
|
||||
|
@ -546,6 +546,13 @@ extern "C" {
|
||||
*
|
||||
* @ingroup init
|
||||
* @{ */
|
||||
/*! @brief No error has occurred.
|
||||
*
|
||||
* No error has occurred.
|
||||
*
|
||||
* @analysis Yay.
|
||||
*/
|
||||
#define GLFW_NO_ERROR 0
|
||||
/*! @brief GLFW has not been initialized.
|
||||
*
|
||||
* 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);
|
||||
|
||||
/*! @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.
|
||||
*
|
||||
* This function sets the error callback, which is called with an error code
|
||||
* 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
|
||||
* are using GLFW from multiple threads, your error callback needs to be
|
||||
* written accordingly.
|
||||
@ -1634,6 +1668,7 @@ GLFWAPI const char* glfwGetVersionString(void);
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
* @sa @ref error_handling
|
||||
* @sa @ref glfwGetError
|
||||
*
|
||||
* @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
|
||||
// after termination
|
||||
//
|
||||
static int _glfwErrorCode;
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
@ -113,7 +114,11 @@ static void terminate(void)
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
if (_glfwPlatformIsValidTls(&_glfw.error))
|
||||
_glfwErrorCode = (int) (intptr_t) _glfwPlatformGetTls(&_glfw.error);
|
||||
|
||||
_glfwPlatformDestroyTls(&_glfw.context);
|
||||
_glfwPlatformDestroyTls(&_glfw.error);
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
}
|
||||
@ -125,6 +130,11 @@ static void terminate(void)
|
||||
|
||||
void _glfwInputError(int error, const char* format, ...)
|
||||
{
|
||||
if (_glfw.initialized)
|
||||
_glfwPlatformSetTls(&_glfw.error, (void*) (intptr_t) error);
|
||||
else
|
||||
_glfwErrorCode = error;
|
||||
|
||||
if (_glfwErrorCallback)
|
||||
{
|
||||
char buffer[8192];
|
||||
@ -164,15 +174,19 @@ GLFWAPI int glfwInit(void)
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfw.hints.init = _glfwInitHints;
|
||||
|
||||
if (!_glfwPlatformCreateTls(&_glfw.context))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
terminate();
|
||||
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.timer.offset = _glfwPlatformGetTimerValue();
|
||||
|
||||
@ -223,6 +237,24 @@ GLFWAPI const char* glfwGetVersionString(void)
|
||||
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)
|
||||
{
|
||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||
|
@ -517,6 +517,7 @@ struct _GLFWlibrary
|
||||
|
||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
_GLFWtls error;
|
||||
_GLFWtls context;
|
||||
|
||||
struct {
|
||||
@ -653,6 +654,7 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||
GLFWbool _glfwPlatformIsValidTls(_GLFWtls* tls);
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
@ -52,7 +52,6 @@ GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_TRUE);
|
||||
if (tls->posix.allocated)
|
||||
pthread_key_delete(tls->posix.key);
|
||||
memset(tls, 0, sizeof(_GLFWtls));
|
||||
@ -70,3 +69,8 @@ void _glfwPlatformSetTls(_GLFWtls* tls, void* 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)
|
||||
{
|
||||
assert(tls->win32.allocated == GLFW_TRUE);
|
||||
if (tls->win32.allocated)
|
||||
TlsFree(tls->win32.index);
|
||||
memset(tls, 0, sizeof(_GLFWtls));
|
||||
@ -70,3 +69,8 @@ void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||
TlsSetValue(tls->win32.index, value);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsValidTls(_GLFWtls* tls)
|
||||
{
|
||||
return tls->win32.allocated;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user