glfw/docs/input.dox

590 lines
18 KiB
Plaintext
Raw Normal View History

2014-04-23 13:30:11 +02:00
/*!
2014-09-18 15:03:29 +02:00
@page input Input guide
2014-04-23 13:30:11 +02:00
@tableofcontents
2014-09-18 15:03:29 +02:00
This guide introduces the input related functions of GLFW. There are also
guides for the other areas of GLFW.
- @ref intro
- @ref window
- @ref context
- @ref monitor
GLFW provides many kinds of input. While some can only be polled, like time, or
only received via callbacks, like scrolling, there are those that provide both
callbacks and polling. Where a callback is provided, that is the recommended
way to receive that kind of input. The more you can use callbacks the less time
your users' machines will need to spend polling.
All input callbacks receive a window handle. By using the
[window user pointer](@ref window_userptr), you can access non-global structures
or objects from your callbacks.
To get a better feel for how the various events callbacks behave, run the
`events` test program. It register every callback supported by GLFW and prints
out all arguments provided for every event, along with time and sequence
information.
@section input_event Event processing
GLFW needs to communicate regularly with the window system both in order to
receive events and to show that the application hasn't locked up. Event
processing must be done regularly while you have visible windows and is normally
done each frame after [buffer swapping](@ref window_swap).
There are two functions for processing pending events. @ref glfwPollEvents,
processes only those events that have already been received and then returns
immediately.
@code
glfwPollEvents();
@endcode
This is the best choice when rendering continually, like most games do.
If you only need to update the contents of the window when you receive new
input, @ref glfwWaitEvents is a better choice.
@code
glfwWaitEvents();
@endcode
It puts the thread to sleep until at least one event has been received and then
processes all received events. This saves a great deal of CPU cycles and is
useful for, for example, editing tools. There must be at least one GLFW window
for this function to sleep.
If the main thread is sleeping in @ref glfwWaitEvents, you can wake it from
another thread by posting an empty event to the event queue with @ref
glfwPostEmptyEvent.
@code
glfwPostEmptyEvent();
@endcode
2014-10-02 17:35:10 +02:00
Do not assume that callbacks will _only_ be called through either of the above
2014-09-18 15:03:29 +02:00
functions. While it is necessary to process events in the event queue, some
window systems will send some events directly to the application, which in turn
causes callbacks to be called outside of regular event processing.
@section input_keyboard Keyboard input
GLFW divides keyboard input into two categories; key events and character
events. Key events relate to actual physical keyboard keys, whereas character
events relate to the Unicode code points generated by pressing some of them.
Keys and characters do not map 1:1. A single key press may produce several
characters, and a single character may require several keys to produce. This
may not be the case on your machine, but your users are likely not all using the
same keyboard layout, input method or even operating system as you.
@subsection input_key Key input
If you wish to be notified when a physical key is pressed or released or when it
2014-10-02 17:35:10 +02:00
repeats, set a key callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetKeyCallback(window, key_callback);
@endcode
The callback function receives the [keyboard key](@ref keys), platform-specific
scancode, key action and [modifier bits](@ref mods).
@code
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_E && action == GLFW_PRESS)
activate_airship();
}
@endcode
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. The key
will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it. These keys still
have unique, if platform-specific scancodes.
The scancode is unique for every key but is platform-specific, so a scancode
will map to different keys on different platforms.
2014-10-02 17:35:10 +02:00
The key will be `GLFW_KEY_UNKNOWN` for special keys like _E-mail_ or _Play_ that
2014-09-18 15:03:29 +02:00
don't have a key token. Those keys will still have unique, if platform-specific
scancodes.
Key states for [named keys](@ref keys) are also saved in per-window state arrays
that can be polled with @ref glfwGetKey.
@code
int state = glfwGetKey(window, GLFW_KEY_E);
if (state == GLFW_PRESS)
activate_airship();
@endcode
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
This function only returns cached key event state. It does not poll the
system for the current state of the key.
Whenever you poll state, you risk missing the state change you are looking for.
If a pressed key is released again before you poll its state, you will have
missed the key press. The recommended solution for this is to use a
key callback, but there is also the `GLFW_STICKY_KEYS` input mode.
@code
glfwSetInputMode(window, GLFW_STICKY_KEYS, 1);
@endcode
When sticky keys mode is enabled, the pollable state of a key will remain
`GLFW_PRESS` until the state of that key is polled with @ref glfwGetKey. Once
it has been polled, if a key release event had been processed in the meantime,
the state will reset to `GLFW_RELEASE`, otherwise it will remain `GLFW_PRESS`.
The `GLFW_KEY_LAST` constant holds the highest value of any
[named key](@ref keys).
2014-10-07 23:37:59 +02:00
@subsection input_char Text input
2014-09-18 15:03:29 +02:00
2014-10-07 23:37:59 +02:00
GLFW supports text input in the form of a stream of
[Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the
operating system text input system. Unlike key input, text input obeys keyboard
layouts and modifier keys and supports composing characters using
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
encode the code points into
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
you can treat the code point argument as native endian
[UTF-32](https://en.wikipedia.org/wiki/UTF-32).
There are two callbacks for receiving Unicode code points. If you wish to
offer regular text input, set a character callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetCharCallback(window, character_callback);
@endcode
The callback function receives Unicode code points for key events that would
2014-10-07 23:37:59 +02:00
have led to regular text input and generally behaves as a standard text field on
that platform.
2014-09-18 15:03:29 +02:00
@code
void character_callback(GLFWwindow* window, unsigned int codepoint)
{
}
@endcode
2014-10-07 23:37:59 +02:00
If you wish to receive even those Unicode code points generated with modifier
key combinations that a plain text field would ignore, or just want to know
exactly what modifier keys were used, set a character with modifiers callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetCharCallback(window, charmods_callback);
@endcode
The callback function receives Unicode code points and
[modifier bits](@ref mods).
@code
void charmods_callback(GLFWwindow* window, unsigned int codepoint, int mods)
{
}
@endcode
2014-04-23 13:30:11 +02:00
@section input_mouse Mouse input
2014-09-18 15:03:29 +02:00
Mouse input comes in many forms, including of mouse motion and button presses,
system cursor appearance and behavior, and two-dimensional scrolling. All of
these are supported by GLFW.
@subsection input_cursor_pos Cursor position
If you wish to be notified when the system cursor moves over the window, set
2014-10-02 17:35:10 +02:00
a cursor position callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetCursorPosCallback(window, cursor_pos_callback);
@endcode
The callback functions receives the cursor position. On platforms that provide
it, the full sub-pixel cursor position is passed on.
@code
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
}
@endcode
The cursor position is also saved per-window and can be polled with @ref
glfwGetCursorPos.
@code
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
@endcode
@subsection input_cursor_mode Cursor modes
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
mouse motion input. By default, the `GLFW_CURSOR_NORMAL` cursor mode is used,
meaning the regular arrow cursor or a [custom cursor](@ref input_cursor) is used
and cursor motion is not limited.
If you wish to implement mouse motion based camera controls or other input
schemes that require unlimited mouse movement, set the cursor mode to
`GLFW_CURSOR_DISABLED`.
@code
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
@endcode
This will hide the cursor and lock it to the specified window. GLFW will then
take care of all the details of cursor re-centering and offset calculation and
providing the application with a virtual cursor position. This virtual position
is provided normally, both via the cursor position callback and via position
polling.
@note You should not implement your own version of this functionality using
other features of GLFW. It will not work as robustly as `GLFW_CURSOR_DISABLED`,
as those features are not intended for this purpose.
If you just wish the cursor to become hidden when it is over a window, set
the cursor mode to `GLFW_CURSOR_HIDDEN`.
@code
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
@endcode
This mode puts no limit on the motion of the cursor.
To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL`
cursor mode.
@code
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
@endcode
@subsection input_cursor Cursor objects
GLFW supports creating custom system cursor images, encapsulated as @ref
GLFWcursor objects. They are created with @ref glfwCreateCursor and destroyed
with @ref glfwDestroyCursor (or @ref glfwTerminate, if any remain).
@subsubsection input_cursor_creation Cursor creation
A cursor is created with @ref glfwCreateCursor, which returns a handle to the
created cursor object. For example, this creates a 16x16 white square cursor
with the hot-spot in the upper-left corner:
@code
unsigned char pixels[16 * 16 * 4];
memset(pixels, 0xff, sizeof(pixels));
GLFWimage image;
image.width = 16;
image.height = 16;
image.pixels = pixels;
GLFWcursor* cursor = glfwCreateCursor(&image, 0, 0);
@endcode
2014-10-02 17:35:10 +02:00
If cursor creation fails, `NULL` will be returned, so it is necessary to check
the return value.
2014-09-18 15:03:29 +02:00
The image data is 32-bit RGBA, i.e. eight bits per channel. The pixels are
arranged canonically as sequental rows, starting from the top-left corner.
@subsubsection input_cursor_destruction Cursor destruction
When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
@code
glfwDestroyCursor(cursor);
@endcode
2014-10-02 17:35:10 +02:00
Cursor destruction always succeeds. All cursors remaining when @ref
2014-09-18 15:03:29 +02:00
glfwTerminate is called are destroyed as well.
@subsubsection input_cursor_set Cursor setting
A cursor can be set as current for a window with @ref glfwSetCursor.
@code
glfwSetCursor(window, cursor);
@endcode
Once set, the cursor image will be used as long as the system cursor is over the
client area of the window and the [cursor mode](@ref input_cursor_mode) is set
to `GLFW_CURSOR_NORMAL`.
A single cursor may be set for any number of windows.
To remove a cursor from a window, set the cursor of that window to `NULL`.
@code
glfwSetCursor(window, NULL);
@endcode
When a cursor is destroyed, it is removed from any window where it is set. This
does not affect the cursor modes of those windows.
@subsubsection input_cursor_standard Standard cursor shapes
Cursor objects with platform-specific variants of the
[standard shapes](@ref shapes) can be created with @ref
glfwCreateStandardCursor.
@code
GLFWcursor* cursor = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR);
@endcode
These cursor objects behave in the exact same way as those created with @ref
glfwCreateCursor except that the platform provides the cursor image data.
2014-09-18 15:03:29 +02:00
@subsection input_cursor_enter Cursor enter/leave events
If you wish to be notified when the cursor enters or leaves the client area of
2014-10-02 17:35:10 +02:00
a window, set a cursor enter/leave callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetCursorEnterCallback(window, cursor_enter_callback);
@endcode
The callback function receives the new classification of the cursor.
@code
void cursor_enter_callback(GLFWwindow* window, int entered)
{
if (entered)
{
// The cursor entered the client area of the window
}
else
{
// The cursor left the client area of the window
}
}
@endcode
@subsection input_mouse_button Mouse button input
If you wish to be notified when a mouse button is pressed or released, set
2014-10-02 17:35:10 +02:00
a mouse button callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetMouseButtonCallback(window, mouse_button_callback);
@endcode
The callback function receives the [mouse button](@ref buttons), button action
and [modifier bits](@ref mods).
@code
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
popup_menu();
}
@endcode
The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
Mouse button states for [named buttons](@ref buttons) are also saved in
per-window state arrays that can be polled with @ref glfwGetMouseButton.
@code
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS)
upgrade_cow();
@endcode
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
This function only returns cached mouse button event state. It does not poll
the system for the current state of the mouse button.
Whenever you poll state, you risk missing the state change you are looking for.
If a pressed mouse button is released again before you poll its state, you will have
missed the button press. The recommended solution for this is to use a
mouse button callback, but there is also the `GLFW_STICKY_MOUSE_BUTTONS`
input mode.
@code
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, 1);
@endcode
When sticky mouse buttons mode is enabled, the pollable state of a mouse button
will remain `GLFW_PRESS` until the state of that button is polled with @ref
glfwGetMouseButton. Once it has been polled, if a mouse button release event
had been processed in the meantime, the state will reset to `GLFW_RELEASE`,
otherwise it will remain `GLFW_PRESS`.
The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
[named button](@ref buttons).
@subsection input_scroll Scroll input
If you wish to be notified when the user scrolls, whether with a mouse wheel or
2014-10-02 17:35:10 +02:00
touchpad gesture, set a scroll callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetScrollCallback(window, scroll_callback);
@endcode
The callback function receives two-dimensional scroll offsets.
@code
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
}
@endcode
A simple mouse wheel, being vertical, provides offsets along the Y-axis.
2014-04-23 13:30:11 +02:00
@section input_joy Joystick input
2014-09-18 15:03:29 +02:00
The joystick functions expose connected joysticks and controllers, with both
referred to as joysticks. It supports up to sixteen joysticks, ranging from
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to `GLFW_JOYSTICK_LAST`. You can test
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
@code
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
@endcode
When GLFW is initialized, detected joysticks are added to to the beginning of
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
keeps its assigned index until it is disconnected, so as joysticks are connected
and disconnected, they will become spread out.
Joystick state is updated as needed when a joystick function is called and does
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
to be called.
@subsection input_joy_axis Joystick axis states
The positions of all axes of a joystick are returned by @ref
glfwGetJoystickAxes. See the reference documentation for the lifetime of the
returned array.
@code
int count;
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
@endcode
Each element in the returned array is a value between -1.0 and 1.0.
@subsection input_joy_button Joystick button states
The states of all buttons of a joystick are returned by @ref
glfwGetJoystickButtons. See the reference documentation for the lifetime of the
returned array.
@code
int count;
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
@endcode
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
@subsection input_joy_name Joystick name
The human-readable, UTF-8 encoded name of a joystick is returned by @ref
glfwGetJoystickName. See the reference documentation for the lifetime of the
returned string.
@code
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
@endcode
Joystick names are not guaranteed to be unique. Two joysticks of the same model
and make may have the same name. Only the [joystick token](@ref joysticks) is
guaranteed to be unique, and only until that joystick is disconnected.
@section input_time Time input
GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime.
@code
double seconds = glfwGetTime();
@endcode
It returns the number of seconds since the timer was started when the library
was initialized with @ref glfwInit. The platform-specific time sources used
usually have micro- or nanosecond resolution.
You can modify the reference time with @ref glfwSetTime.
@code
glfwSetTime(4.0);
@endcode
This sets the timer to the specified time, in seconds.
@section input_clipboard Clipboard input and output
If the system clipboard contains a UTF-8 encoded string or if it can be
converted to one, you can retrieve it with @ref glfwGetClipboardString. See the
reference documentation for the lifetime of the returned string.
@code
const char* clipboard = glfwGetClipboardString(window);
@endcode
The contents of the system clipboard can be set to a UTF-8 encoded string with
@ref glfwSetClipboardString.
@code
glfwSetClipboardString(window, "A string with words in it");
@endcode
The clipboard functions take a window handle argument because some window
systems require a window to communicate with the system clipboard. Any valid
window may be used.
@section input_drop Path drop input
If you wish to receive the paths of files and/or directories dropped on
2014-10-02 17:35:10 +02:00
a window, set a file drop callback.
2014-09-18 15:03:29 +02:00
@code
glfwSetDropCallback(window, drop_callback);
@endcode
The callback function receives an array of paths encoded as UTF-8.
@code
void drop_callback(GLFWwindow* window, int count, const char** paths)
{
int i;
for (i = 0; i < count; i++)
handle_dropped_file(paths[i]);
}
@endcode
The path array and its strings are only valid until the file drop callback
returns, as they may have been generated specifically for that event. You need
to make a deep copy of the array if you want to keep the paths.
2014-04-23 13:30:11 +02:00
*/