mirror of
https://github.com/glfw/glfw.git
synced 2024-11-11 04:53:50 +00:00
783 lines
24 KiB
Plaintext
783 lines
24 KiB
Plaintext
/*!
|
||
|
||
@page input_guide Input guide
|
||
|
||
@tableofcontents
|
||
|
||
This guide introduces the input related functions of GLFW. For details on
|
||
a specific function in this category, see the @ref input. There are also guides
|
||
for the other areas of GLFW.
|
||
|
||
- @ref intro_guide
|
||
- @ref window_guide
|
||
- @ref context_guide
|
||
- @ref vulkan_guide
|
||
- @ref monitor_guide
|
||
|
||
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 events 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 any windows and is normally
|
||
done each frame after [buffer swapping](@ref buffer_swap). Even when you have
|
||
no windows, event polling needs to be done in order to receive monitor
|
||
connection events.
|
||
|
||
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 you want to wait for events but have UI elements that need periodic updates,
|
||
call @ref glfwWaitEventsTimeout.
|
||
|
||
@code
|
||
glfwWaitEventsTimeout(0.7);
|
||
@endcode
|
||
|
||
It puts the thread to sleep until at least one event has been received, or until
|
||
the specified number of seconds have elapsed. It then processes any received
|
||
events.
|
||
|
||
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
|
||
|
||
Do not assume that callbacks will _only_ be called through either of the above
|
||
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
|
||
repeats, set a key callback.
|
||
|
||
@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, for example
|
||
_E-mail_ and _Play_ keys.
|
||
|
||
The scancode is unique for every key, regardless of whether it has a key token.
|
||
Scancodes are platform-specific but consistent over time, so keys will have
|
||
different scancodes depending on the platform but they are safe to save to disk.
|
||
|
||
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).
|
||
|
||
|
||
@subsection input_char Text input
|
||
|
||
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.
|
||
|
||
@code
|
||
glfwSetCharCallback(window, character_callback);
|
||
@endcode
|
||
|
||
The callback function receives Unicode code points for key events that would
|
||
have led to regular text input and generally behaves as a standard text field on
|
||
that platform.
|
||
|
||
@code
|
||
void character_callback(GLFWwindow* window, unsigned int codepoint)
|
||
{
|
||
}
|
||
@endcode
|
||
|
||
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.
|
||
|
||
@code
|
||
glfwSetCharModsCallback(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
|
||
|
||
|
||
@subsection preedit IME support
|
||
|
||
All modern operating systems provide a
|
||
[IME](https://en.wikipedia.org/wiki/Input_method) (Input Method Editor)
|
||
mechanism to input character sets that cannot be mapped to physical keys, such
|
||
as [CJK characters](https://en.wikipedia.org/wiki/CJK_characters) (Chinese,
|
||
Japanese, Korean). Some operating systems also support speech-to-text input via
|
||
the IME mechanism.
|
||
|
||
GLFW provides IME support functions to help you implement better text input
|
||
features. You should add suitable visualization code for pre-edit text.
|
||
|
||
IME works in front of actual character input events (@ref input_char).
|
||
If your application uses text input and you want to support IME, you should
|
||
register pre-edit callback to receive pre-edit text before committed.
|
||
|
||
@code
|
||
glfwSetPreeditCallback(window, preedit_callback);
|
||
@endcode
|
||
|
||
The callback function receives the pre-edit text and block information.
|
||
|
||
@code
|
||
static void preedit_callback(GLFWwindow* window, unsigned int* codepoints, int blockCount, int* blocks, int focusedBlock)
|
||
{
|
||
}
|
||
@endcode
|
||
|
||
The codepoints parameter contains the whole pre-edit text. Each character of the
|
||
pre-edit string is a Unicode codepoint like with @ref input_char.
|
||
|
||
If you want to type the text "寿司" (sushi), usually the callback is called
|
||
several times like the following sequence:
|
||
|
||
@code
|
||
-# key event: s
|
||
-# preedit: [string: "s", block: [1], focusedBlock: 0]
|
||
-# key event: u
|
||
-# preedit: [string: "す", block: [1], focusedBlock: 0]
|
||
-# key event: s
|
||
-# preedit: [string: "すs", block: [2], focusedBlock: 0]
|
||
-# key event: h
|
||
-# preedit: [string: "すsh", block: [2], focusedBlock: 0]
|
||
-# key event: i
|
||
-# preedit: [string: "すし", block: [2], focusedBlock: 0]
|
||
-# key event: ' '
|
||
-# preedit: [string: "寿司", block: [2], focusedBlock: 0]
|
||
-# char: '寿'
|
||
-# char: '司'
|
||
-# preedit: [string: "", block: [], focusedBlock: 0]
|
||
@endcode
|
||
|
||
If pre-edit text includes several semantic blocks, pre-edit callbacks returns
|
||
several blocks after a space key pressed:
|
||
|
||
@code
|
||
-# preedit: [string: "わたしはすしをたべます", block: [11], focusedBlock: 0]
|
||
-# preedit: [string: "私は寿司を食べます", block: [2, 7], focusedBlock: 1]
|
||
@endcode
|
||
|
||
"blocks" is a list of block length. The above case, it contains the following
|
||
blocks and second block is focused.
|
||
|
||
@code
|
||
- 私は
|
||
- [寿司を食べます]
|
||
@endcode
|
||
|
||
committed text (passed via regular @ref input_char event), unfocused block,
|
||
focused block should have different text style.
|
||
|
||
GLFW provides helper function to teach suitable position of the candidate window
|
||
to window system. Window system decides the best position from text cursor
|
||
geometry (window coordinates and height). You should call this function in the
|
||
above pre-edit text callback function.
|
||
|
||
@code
|
||
int xpos, ypos, height;
|
||
glfwSetPreeditCursorPos(window, xpos, ypos, height);
|
||
glfwGetPreeditCursorPos(window, &xpos, &ypos, &height);
|
||
@endcode
|
||
|
||
Sometimes IME task is interrupted by user or application. There are several
|
||
functions to support these situation. You can receive notification about IME
|
||
status change(on/off) by using the following function:
|
||
|
||
@code
|
||
glfwSetIMEStatusCallback(window, ime_status_callback);
|
||
@endcode
|
||
|
||
The ime_status_callback has simple signature like this:
|
||
|
||
@code
|
||
static void ime_status_callback(GLFWwindow* window)
|
||
{
|
||
}
|
||
@endcode
|
||
|
||
You can implement the code that resets or commits pre-edit text when IME status
|
||
is changed and pre-edit text is not empty.
|
||
|
||
When the focus is gone from text box, you can use @ref glfwSetInputMode, @ref
|
||
glfwGetInputMode with the `GLFW_IME` mode and the @ref glfwResetPreeditText
|
||
function.
|
||
|
||
|
||
@subsection input_key_name Key names
|
||
|
||
If you wish to refer to keys by name, you can query the keyboard layout
|
||
dependent name of printable keys with @ref glfwGetKeyName.
|
||
|
||
@code
|
||
const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);
|
||
show_tutorial_hint("Press %s to move forward", key_name);
|
||
@endcode
|
||
|
||
This function can handle both [keys and scancodes](@ref input_key). If the
|
||
specified key is `GLFW_KEY_UNKNOWN` then the scancode is used, otherwise it is
|
||
ignored. This matches the behavior of the key callback, meaning the callback
|
||
arguments can always be passed unmodified to this function.
|
||
|
||
|
||
@subsection input_key_scancode Key scancodes
|
||
|
||
If you need the platform dependent scancode for a [named key](@ref keys), you
|
||
can query it with @ref glfwGetKeyScancode.
|
||
|
||
@code
|
||
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
|
||
set_key_mapping(scancode, swap_weapons);
|
||
@endcode
|
||
|
||
|
||
@section input_mouse Mouse input
|
||
|
||
Mouse input comes in many forms, including cursor motion, button presses and
|
||
scrolling offsets. The cursor appearance can also be changed, either to
|
||
a custom image or a standard cursor shape from the system theme.
|
||
|
||
|
||
@subsection cursor_pos Cursor position
|
||
|
||
If you wish to be notified when the cursor moves over the window, set a cursor
|
||
position callback.
|
||
|
||
@code
|
||
glfwSetCursorPosCallback(window, cursor_pos_callback);
|
||
@endcode
|
||
|
||
The callback functions receives the cursor position, measured in screen
|
||
coordinates but relative to the top-left corner of the window client area. 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 cursor_mode Cursor modes
|
||
|
||
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
|
||
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
|
||
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
|
||
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 via both the cursor position callback and through polling.
|
||
|
||
@note You should not implement your own version of this functionality using
|
||
other features of GLFW. It is not supported and will not work as robustly as
|
||
`GLFW_CURSOR_DISABLED`.
|
||
|
||
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 cursor_object Cursor objects
|
||
|
||
GLFW supports creating both custom and system theme cursor images, encapsulated
|
||
as @ref GLFWcursor objects. They are created with @ref glfwCreateCursor or @ref
|
||
glfwCreateStandardCursor and destroyed with @ref glfwDestroyCursor, or @ref
|
||
glfwTerminate, if any remain.
|
||
|
||
|
||
@subsubsection cursor_custom Custom cursor creation
|
||
|
||
A custom 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
|
||
|
||
If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
||
the return value.
|
||
|
||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||
per channel. The pixels are arranged canonically as sequential rows, starting
|
||
from the top-left corner.
|
||
|
||
|
||
@subsubsection cursor_standard Standard cursor creation
|
||
|
||
A cursor with a [standard shape](@ref shapes) from the current system cursor
|
||
theme can be 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 system cursor theme provides the actual image.
|
||
|
||
|
||
@subsubsection cursor_destruction Cursor destruction
|
||
|
||
When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
||
|
||
@code
|
||
glfwDestroyCursor(cursor);
|
||
@endcode
|
||
|
||
Cursor destruction always succeeds. All cursors remaining when @ref
|
||
glfwTerminate is called are destroyed as well.
|
||
|
||
|
||
@subsubsection 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 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.
|
||
|
||
|
||
@subsection cursor_enter Cursor enter/leave events
|
||
|
||
If you wish to be notified when the cursor enters or leaves the client area of
|
||
a window, set a cursor enter/leave callback.
|
||
|
||
@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
|
||
a mouse button callback.
|
||
|
||
@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 scrolling Scroll input
|
||
|
||
If you wish to be notified when the user scrolls, whether with a mouse wheel or
|
||
touchpad gesture, set a scroll callback.
|
||
|
||
@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.
|
||
|
||
|
||
@section joystick Joystick input
|
||
|
||
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 joystick_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 joystick_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 joystick_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.
|
||
|
||
|
||
@subsection joystick_event Joystick configuration changes
|
||
|
||
If you wish to be notified when a joystick is connected or disconnected, set
|
||
a joystick callback.
|
||
|
||
@code
|
||
glfwSetJoystickCallback(joystick_callback);
|
||
@endcode
|
||
|
||
The callback function receives the ID of the joystick that has been connected
|
||
and disconnected and the event that occurred.
|
||
|
||
@code
|
||
void joystick_callback(int jid, int event)
|
||
{
|
||
if (event == GLFW_CONNECTED)
|
||
{
|
||
// The joystick was connected
|
||
}
|
||
else if (event == GLFW_DISCONNECTED)
|
||
{
|
||
// The joystick was disconnected
|
||
}
|
||
}
|
||
@endcode
|
||
|
||
|
||
@section 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.
|
||
|
||
You can also access the raw timer value, measured in 1 / frequency
|
||
seconds, with @ref glfwGetTimerValue.
|
||
|
||
@code
|
||
uint64_t value = glfwGetTimerValue();
|
||
@endcode
|
||
|
||
The frequency of the raw timer varies depending on what time sources are
|
||
available on the machine. You can query its frequency, in Hz, with @ref
|
||
glfwGetTimerFrequency.
|
||
|
||
@code
|
||
uint64_t freqency = glfwGetTimerFrequency();
|
||
@endcode
|
||
|
||
|
||
@section 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* text = glfwGetClipboardString(window);
|
||
if (text)
|
||
insert_text(text);
|
||
@endcode
|
||
|
||
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
||
returned.
|
||
|
||
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 path_drop Path drop input
|
||
|
||
If you wish to receive the paths of files and/or directories dropped on
|
||
a window, set a file drop callback.
|
||
|
||
@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.
|
||
|
||
*/
|