1
0
Fork 0
mirror of https://github.com/gwm17/glfw.git synced 2024-11-22 18:28:52 -05:00

Added external documentation files.

Added initial quick tutorial, compatibility appendix, transition guide
and external main page.
This commit is contained in:
Camilla Berglund 2013-02-25 14:09:57 +01:00
parent cd78d70b25
commit fb8f3fd521
6 changed files with 629 additions and 11 deletions

View File

@ -655,7 +655,7 @@ WARN_LOGFILE = @GLFW_BINARY_DIR@/docs/warnings.txt
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = @GLFW_DOC_HEADERS@
INPUT = @GLFW_DOC_HEADERS@ @GLFW_SOURCE_DIR@/docs/
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@ -673,7 +673,7 @@ INPUT_ENCODING = UTF-8
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
# *.f90 *.f *.for *.vhd *.vhdl
FILE_PATTERNS =
FILE_PATTERNS = *.dox
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
@ -1115,7 +1115,7 @@ ECLIPSE_DOC_ID = org.doxygen.Project
# navigation tree you can set this option to NO if you already set
# GENERATE_TREEVIEW to YES.
DISABLE_INDEX = YES
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
@ -1127,7 +1127,7 @@ DISABLE_INDEX = YES
# Since the tree basically has the same information as the tab index you
# could consider to set DISABLE_INDEX to NO when enabling this option.
GENERATE_TREEVIEW = YES
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
# (range [0,1..20]) that doxygen will group on one line in the generated HTML

127
docs/compat.dox Normal file
View File

@ -0,0 +1,127 @@
/*!
@page compat Standards conformance
This chapter describes the various API extensions used by this version of GLFW.
It lists what are essentially implementation details, but which are nonetheless
vital knowledge for developers wishing to deploy their applications on machines
with varied specifications.
Note that the information in this appendix is not a part of the API
specification but merely list some of the preconditions for certain parts of the
API to function on a given machine. As such, any part of it may change in
future versions without this being considered a breaking API change.
@section compat_wm ICCCM and EWMH conformance
As GLFW uses Xlib, directly, without any intervening toolkit
library, it has sole responsibility for interacting well with the many and
varied window managers in use on Unix-like systems. In order for applications
and window managers to work well together, a number of standards and
conventions have been developed that regulate behavior outside the scope of the
X11 API; most importantly the
<a href="http://www.tronche.com/gui/x/icccm/">Inter-Client Communication Conventions Manual</a>
(ICCCM) and
<a href="http://standards.freedesktop.org/wm-spec/wm-spec-latest.html">Extended Window Manager Hints</a>
(EWMH) standards.
GLFW uses the ICCCM @c WM_DELETE_WINDOW protocol to intercept the user
attempting to close the GLFW window. If the running window manager does not
support this protocol, the close callback will never be called.
GLFW uses the EWMH @c _NET_WM_PING protocol, allowing the window manager notify
the user when the application has stopped responding, i.e. when it has ceased to
process events. If the running window manager does not support this protocol,
the user will not be notified if the application locks up.
GLFW uses the EWMH @c _NET_WM_STATE protocol to tell the window manager to make
the GLFW window fullscreen. If the running window manager does not support this
protocol, fullscreen windows may not work properly. GLFW has a fallback code
path in case this protocol is unavailable, but every window manager behaves
slightly differently in this regard.
@section compat_glx GLX extensions
The GLX API is the default API used to create OpenGL contexts on Unix-like
systems using the X Window System.
GLFW uses the @c GLXFBConfig API to enumerate and select framebuffer pixel
formats. This requires either GLX 1.3 or greater, or the @c GLX_SGIX_fbconfig
extension. Where both are available, the SGIX extension is preferred. If
neither is available, GLFW will be unable to create windows.
GLFW uses the @c GLX_MESA_swap_control, @c GLX_EXT_swap_control and @c
GLX_SGI_swap_control extensions to provide vertical retrace synchronization (or
"vsync"), in that order of preference. Where none of these extension are
available, calling @ref glfwSwapInterval will have no effect.
GLFW uses the @c GLX_ARB_multisample extension to create contexts with
multisampling anti-aliasing. Where this extension is unavailable, the @c
GLFW_SAMPLES hint will have no effect.
GLFW uses the @c GLX_ARB_create_context extension when available, even when
creating OpenGL contexts of version 2.1 and below. Where this extension is
unavailable, the @c GLFW_CONTEXT_VERSION_MAJOR and @c GLFW_CONTEXT_VERSION_MINOR
hints will only be partially supported, the @c GLFW_OPENGL_DEBUG_CONTEXT hint
will have no effect, and setting the @c GLFW_OPENGL_PROFILE or @c
GLFW_OPENGL_FORWARD_COMPAT hints to a non-zero value will cause @ref
glfwCreateWindow to fail.
GLFW uses the @c GLX_ARB_create_context_profile extension to provide support for
context profiles. Where this extension is unavailable, setting the @c
GLFW_OPENGL_PROFILE hint to anything but zero, or setting @c GLFW_CLIENT_API to
anything but @c GLFW_OPENGL_API will cause @ref glfwCreateWindow to fail.
@section compat_wgl WGL extensions
The WGL API is used to create OpenGL contexts on Microsoft Windows and other
implementations of the Win32 API, such as Wine.
GLFW uses either the @c WGL_EXT_extension_string or the @c
WGL_ARB_extension_string extension to check for the presence of all other WGL
extensions listed below. If both are available, the EXT one is preferred. If
neither is available, no other extensions are used and many GLFW features
related to context creation will have no effect or cause errors when used.
GLFW uses the @c WGL_EXT_swap_control extension to provide vertical retrace
synchronization (or "vsync"). Where this extension is unavailable, calling @ref
glfwSwapInterval will have no effect.
GLFW uses the @c WGL_ARB_pixel_format and @c WGL_ARB_multisample extensions to
create contexts with multisampling anti-aliasing. Where these extensions are
unavailable, the @c GLFW_SAMPLES hint will have no effect.
GLFW uses the @c WGL_ARB_create_context extension when available, even when
creating OpenGL contexts of version 2.1 and below. Where this extension is
unavailable, the @c GLFW_CONTEXT_VERSION_MAJOR and @c GLFW_CONTEXT_VERSION_MINOR
hints will only be partially supported, the @c GLFW_OPENGL_DEBUG_CONTEXT hint
will have no effect, and setting the @c GLFW_OPENGL_PROFILE or @c
GLFW_OPENGL_FORWARD_COMPAT hints to a non-zero value will cause @ref
glfwCreateWindow to fail.
GLFW uses the @c WGL_ARB_create_context_profile extension to provide support for
context profiles. Where this extension is unavailable, setting the @c
GLFW_OPENGL_PROFILE hint to anything but zero will cause @ref glfwCreateWindow
to fail.
@section cmopat_osx OpenGL 3.2 on Mac OS X
Support for OpenGL 3.0 and above was introduced with Mac OS X 10.7, and even
then only forward-compatible OpenGL 3.2 core profile contexts are supported.
There is also still no mechanism for requesting debug contexts. Versions of
Mac OS X earlier than 10.7 support at most OpenGL version 2.1.
Because of this, on Mac OS X 10.7, the @c GLFW_CONTEXT_VERSION_MAJOR and
@c GLFW_CONTEXT_VERSION_MINOR hints will fail if given a version above 3.2, the
@c GLFW_OPENGL_FORWARD_COMPAT is required for creating OpenGL 3.2 contexts, the
@c GLFW_OPENGL_DEBUG_CONTEXT hint is ignored and setting the @c
GLFW_OPENGL_PROFILE hint to anything except @c GLFW_OPENGL_CORE_PROFILE will
cause @ref glfwCreateWindow to fail.
Also, on Mac OS X 10.6 and below, the @c GLFW_CONTEXT_VERSION_MAJOR and @c
GLFW_CONTEXT_VERSION_MINOR hints will fail if given a version above 2.1, the @c
GLFW_OPENGL_DEBUG_CONTEXT hint will have no effect, and setting the @c
GLFW_OPENGL_PROFILE or @c GLFW_OPENGL_FORWARD_COMPAT hints to a non-zero value
will cause @ref glfwCreateWindow to fail.
*/

16
docs/main.dox Normal file
View File

@ -0,0 +1,16 @@
/*!
@mainpage notitle
@section main_intro Introduction
GLFW is a free, Open Source, multi-platform library for opening a window,
creating an OpenGL context and managing input. It is easy to integrate into
existing applications and does not lay claim to the main loop.
@link quick Quick introduction @endlink is a short tutorial for people new to GLFW.
@link moving Moving from GLFW 2 to 3 @endlink explains what has changed and how
to update existing code to use the GLFW 3 API.
*/

280
docs/moving.dox Normal file
View File

@ -0,0 +1,280 @@
/*!
@page moving Moving from GLFW 2 to 3
This is a guide for people moving from GLFW 2 to 3. It describes API @em
changes, but does @em not include entirely new features unless they are required
when moving an existing code base onto the new API. One example of this is the
new multi-monitor support, which you are now required to use to create
fullscreen windows.
@section moving_names Library and header names
The GLFW 3 header is named @ref glfw3.h, to avoid collisions with the GLFW 2 @c
glfw.h header, in case they are both installed. Similarly, the GLFW 3 library
is named @c glfw3, except when it's installed as a shared library on
Unix-like systems, where it uses the
<a href="https://en.wikipedia.org/wiki/soname">soname</a> @c libglfw.so.3 .
@section moving_threads Removal of threading functions
The threading functions have been removed. However, GLFW 3 has better support
for use from multiple threads than GLFW 2 had. Contexts can be made current on
and used from secondary threads, and the documentation explicitly states which
functions may and may not be used from secondary threads.
@section moving_image Removal of image and texture loading
The image and texture loading support has been removed.
@section moving_window_handles Window handles
Because GLFW 3 supports multiple windows, window handle parameters have been
added to all window-related functions and callbacks. Window handles are of the
@c GLFWwindow* type, i.e. a pointer to an opaque struct.
@section moving_monitor Multi-monitor support
GLFW 3 provides support for multiple monitors, adding the @c GLFWmonitor* handle
type and a set of related functions. To request a fullscreen mode window, you
need to specify which monitor you wish the window to use. There is @ref
glfwGetPrimaryMonitor that provides something similar to the earlier behaviour.
@section moving_window_close Window closing
Window closing is now just an event like any other. GLFW 3 windows won't
disappear from underfoot even when no close callback is set. You can query
whether the user has requested that the window be closed using the @c
GLFW_CLOSE_REQUESTED window parameter, or by setting a close callback. The
return value of the close callback becomes the new value of the window
parameter.
@section moving_context Explicit context management
Each GLFW 3 window has its own OpenGL context and only you, the user, can know
which context should be current on which thread at any given time. Therefore,
GLFW 3 makes no assumptions about when you want a certain context current,
leaving that decision to you.
This means that you need to call @ref glfwMakeContextCurrent after creating
a window but before calling any OpenGL functions.
@section moving_keys Physical key input
GLFW 3 uses the physical key locations named after the symbols they generate
using the US keyboard layout, instead of layout-dependent characters like in
GLFW 2. This means that (for example) @c GLFW_KEY_BACKSLASH is always a single
key and is the same key in the same place regardless of what keyboard layouts
the users of your program has.
GLFW 3 has key tokens for all keys, so instead of trying to remember whether to
check for @c 'a' or @c 'A', you now check for @c GLFW_KEY_A.
The key input facility was never meant for text input, although using it that
way worked slightly better in GLFW 2. If you were using it to input text, you
should be using the character callback instead, on both GLFW 2 and 3. This will
give you the characters being input, as opposed to the keys being pressed.
@section moving_video_modes Video mode enumeration
Video mode enumeration is now per-monitor. The @c glfwGetDesktopMode function
has been replaced by @ref glfwGetVideoMode, which returns the current mode of
a monitor. The @ref glfwGetVideoMode function now returns all available modes
for a monitor instead of requiring you to guess how large an array you need.
@section moving_glu GLU header inclusion
Unlike GLFW 2, GLFW 3 doesn't include the GLU header by default, but you can
make it do so by defining @c GLFW_INCLUDE_GLU before including the GLFW
3 header.
@section moving_cursor Cursor positioning
GLFW 3 only allows you to position the cursor within a window (using @ref
glfwSetCursorPos) when that window is active. Unless the window is active, the
function fails silently.
@section moving_renamed Symbol name changes
@subsection moving_renamed_functions Renamed functions
<table>
<tr>
<td>GLFW 2</td>
<td>GLFW 3</td>
<td>Notes</td>
</tr>
<tr>
<td>@c glfwOpenWindow</td>
<td>@ref glfwCreateWindow</td>
<td>All channel bit depths are now hints<br />The defaults are 24-bit color
and depth buffers<br />Accepts initial window title, optional monitor to go
fullscreen on and optional context to share objects with</td>
</tr>
<tr>
<td>@c glfwCloseWindow</td>
<td>@ref glfwDestroyWindow</td>
<td></td>
</tr>
<tr>
<td>@c glfwOpenWindowHint</td>
<td>@ref glfwWindowHint</td>
<td>Now also accepts @c GLFW_RED_BITS, @c GLFW_GREEN_BITS, @c
GLFW_BLUE_BITS, @c GLFW_ALPHA_BITS, @c GLFW_DEPTH_BITS and @c
GLFW_STENCIL_BITS</td>
</tr>
<tr>
<td>@c glfwEnable</td>
<td>@ref glfwSetInputMode</td>
<td></td>
</tr>
<tr>
<td>@c glfwDisable</td>
<td>@ref glfwSetInputMode</td>
<td></td>
</tr>
<tr>
<td>@c glfwGetMousePos</td>
<td>@ref glfwGetCursorPos</td>
<td></td>
</tr>
<tr>
<td>@c glfwSetMousePos</td>
<td>@ref glfwSetCursorPos</td>
<td></td>
</tr>
<tr>
<td>@c glfwSetMousePosCallback</td>
<td>@ref glfwSetCursorPosCallback</td>
<td></td>
</tr>
<tr>
<td>@c glfwSetMouseWheelCallback</td>
<td>@ref glfwSetScrollCallback</td>
<td>Accepts two-dimensional scroll offsets as doubles</td>
</tr>
<tr>
<td>@c glfwGetJoystickPos</td>
<td>@ref glfwGetJoystickAxes</td>
<td></td>
</tr>
<tr>
<td>@c glfwGetGLVersion</td>
<td>@ref glfwGetWindowParam</td>
<td>Use @c GLFW_OPENGL_VERSION_MAJOR, @c GLFW_OPENGL_VERSION_MINOR and @c
GLFW_OPENGL_REVISION</td>
</tr>
<tr>
<td>@c glfwGetDesktopMode</td>
<td>@ref glfwGetVideoMode</td>
<td>Returns the current mode of a monitor</td>
</tr>
</table>
@subsection moving_renamed_tokens Renamed tokens
<table>
<tr>
<td>GLFW 2</td>
<td>GLFW 3</td>
<td>Notes</td>
</tr>
<tr>
<td>@c GLFW_OPENGL_VERSION_MAJOR</td>
<td>@c GLFW_CONTEXT_VERSION_MAJOR</td>
<td>Renamed as it applies to OpenGL ES as well</td>
</tr>
<tr>
<td>@c GLFW_OPENGL_VERSION_MINOR</td>
<td>@c GLFW_CONTEXT_VERSION_MINOR</td>
<td>Renamed as it applies to OpenGL ES as well</td>
</tr>
<tr>
<td>@c GLFW_FSAA_SAMPLES</td>
<td>@c GLFW_SAMPLES</td>
<td>Renamed to match the OpenGL API</td>
</tr>
<tr>
<td>@c GLFW_ACTIVE</td>
<td>@c GLFW_FOCUSED</td>
<td>Renamed to match the window focus callback</td>
</tr>
<tr>
<td>@c GLFW_WINDOW_NO_RESIZE</td>
<td>@c GLFW_RESIZABLE</td>
<td>The default has been inverted</td>
</tr>
<tr>
<td>@c GLFW_MOUSE_CURSOR</td>
<td>@c GLFW_CURSOR_MODE</td>
<td>Used with @c glfwSetInputMode<br />Accepts @c GLFW_CURSOR_NORMAL, @c
GLFW_CURSOR_HIDDEN and @c GLFW_CURSOR_CAPTURED</td>
</tr>
<tr>
<td>@c GLFW_KEY_ESC</td>
<td>@c GLFW_KEY_ESCAPE</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_DEL</td>
<td>@c GLFW_KEY_DELETE</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_PAGEUP</td>
<td>@c GLFW_KEY_PAGE_UP</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_PAGEDOWN</td>
<td>@c GLFW_KEY_PAGE_DOWN</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_KP_NUM_LOCK</td>
<td>@c GLFW_KEY_NUM_LOCK</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_LCTRL</td>
<td>@c GLFW_KEY_LEFT_CONTROL</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_LSHIFT</td>
<td>@c GLFW_KEY_LEFT_SHIFT</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_LALT</td>
<td>@c GLFW_KEY_LEFT_ALT</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_LSUPER</td>
<td>@c GLFW_KEY_LEFT_SUPER</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_RCTRL</td>
<td>@c GLFW_KEY_RIGHT_CONTROL</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_RSHIFT</td>
<td>@c GLFW_KEY_RIGHT_SHIFT</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_RALT</td>
<td>@c GLFW_KEY_RIGHT_ALT</td>
<td></td>
</tr>
<tr>
<td>@c GLFW_KEY_RSUPER</td>
<td>@c GLFW_KEY_RIGHT_SUPER</td>
<td></td>
</tr>
</table>
*/

200
docs/quick.dox Normal file
View File

@ -0,0 +1,200 @@
/*!
@page quick Getting started
@section quick_start Introduction
In this guide you will learn how to write simple OpenGL applications using
GLFW 3. We start by initializing GLFW, then we create a window and read some
user keyboard input.
@section quick_include Including the GLFW header
The first thing you have to do when using GLFW is including the GLFW header.
@code
#include <GL/glfw3.h>
@endcode
This header defines all the constants, types and function prototypes of the
GLFW API. It also includes the OpenGL header provided by your development
environment and defines all the necessary constants and types for it to work on
that particular platform.
Starting with version 3.0, the GLU header @c glu.h is no longer included by
default. If you wish to include it, define @c GLFW_INCLUDE_GLU before the
inclusion of the GLFW header.
@section quick_init_term Initializing and terminating GLFW
Before you can use most GLFW functions, the library must be initialized. This
is done with @ref glfwInit, which returns non-zero if successful, or zero if an
error occurred.
@code
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
@endcode
When you are done using GLFW, typically at the very end of the program, you need
to call @ref glfwTerminate.
@code
glfwTerminate();
@endcode
This destroys any remaining windows and releases any other resources allocated by
GLFW. After this call, you must call @ref glfwInit again before using any GLFW
functions that require it.
@section quick_create_window Creating a window and context
The window (and its context) is created with @ref glfwCreateWindow, which
returns a handle to the created window. For example, this creates an 640 by 480
pixels windowed mode window:
@code
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
@endcode
If window creation fails, @c NULL will be returned, so you need to check whether
it did.
@code
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
@endcode
This handle is then passed to all window related functions, and is provided to
you along with input events, so you know which window received the input.
To create a fullscreen window, you need to specify which monitor the window
should use. In most cases, the user's primary monitor is a good choice. You
can get this with @ref glfwGetPrimaryMonitor. To make the above window
fullscreen, just pass along the monitor handle:
@code
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", glfwGetPrimaryMonitor(), NULL);
@endcode
Fullscreen windows cover the entire screen, have no border or decorations, and
change the monitor's resolution to the one most closely matching the requested
window size.
When you are done with the window, destroy it with the @ref glfwDestroyWindow
function.
@code
glfwDestroyWindow(window);
@endcode
Once this function is called, no more events will be delivered for that window
and its handle becomes invalid.
@section quick_window_attribs Retrieving window attributes
Each window provides a number of attributes that can be queried with @ref
glfwGetWindowParam. Some are related to the window itself and others to the
OpenGL context. For example, to find out if the user is attempting to close the
window, either by pressing the close widget in the title bar or using a key
combination like Alt+F4, check the @c GLFW_SHOULD_CLOSE attribute.
@code
while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE))
{
// Keep running
}
@endcode
@section quick_swap_buffers Swapping buffers
GLFW windows always use double-buffering. That means that you have two
rendering buffers; a front buffer and a back buffer. The front buffer is the
one being displayed and the back buffer the one you render to.
When the entire frame has been rendered, it is time to swap the back and the
front buffers in order to display the rendered frame, and begin rendering a new
frame. This is done with @ref glfwSwapBuffers.
@code
glfwSwapBuffers(window);
@endcode
@section quick_process_events Processing events
GLFW needs to communicate regularly with the window system in order to receive
events, like the ones controlling the attribute @c GLFW_SHOULD_CLOSE mentioned
above. Event processing must be done regularly and is normally done each frame
before rendering but after buffer swap.
There are two ways to process events. @ref glfwPollEvents processes only those
events that have already been received and then returns immediately. This is
the best choice when rendering continually, like most games do.
@code
glfwPollEvents();
@endcode
If instead you only need to update your rendering once you have received new
input, @ref glfwWaitEvents is a better choice. It will wait until at least one
event has been received and then process all received events before returning.
@code
glfwWaitEvents();
@endcode
@section quick_example Putting it together: A minimal GLFW application
Now that you know how to initialize GLFW, create a window and poll for
keyboard input, it's possible to create a simple program.
@code
#include <GL/glfw3.h>
#include <stdlib.h>
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
{
exit(EXIT_FAILURE);
}
window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
while (!glfwGetWindowParam(window, GLFW_SHOULD_CLOSE))
{
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
@endcode
This program creates a 640 by 480 pixels window and runs a loop clearing the
screen and processing events until the user closes the window.
*/

View File

@ -39,13 +39,6 @@ extern "C" {
* Doxygen documentation
*************************************************************************/
/*! @mainpage notitle
*
* @section intro Introduction
*
* This is the reference documentation for the GLFW library.
*/
/*! @defgroup clipboard Clipboard support
*/
/*! @defgroup context Context handling
@ -1409,6 +1402,7 @@ GLFWAPI void glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyf
* @ingroup window
*
* @note This function may only be called from the main thread.
* @note This function may not be called from a callback.
*
* @note This function may not be called from a callback.
*
@ -1420,6 +1414,7 @@ GLFWAPI void glfwPollEvents(void);
* @ingroup window
*
* @note This function may only be called from the main thread.
* @note This function may not be called from a callback.
*
* @note This function may not be called from a callback.
*