2024-02-13 19:45:29 +00:00
|
|
|
|
# Input guide {#input_guide}
|
2017-11-17 03:34:18 +00:00
|
|
|
|
|
2024-02-13 21:42:49 +00:00
|
|
|
|
[TOC]
|
2014-04-23 11:30:11 +00:00
|
|
|
|
|
2016-02-19 09:29:13 +00:00
|
|
|
|
This guide introduces the input related functions of GLFW. For details on
|
2016-08-11 17:04:21 +00:00
|
|
|
|
a specific function in this category, see the @ref input. There are also guides
|
|
|
|
|
for the other areas of GLFW.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-02-19 09:29:13 +00:00
|
|
|
|
- @ref intro_guide
|
|
|
|
|
- @ref window_guide
|
|
|
|
|
- @ref context_guide
|
2016-08-11 17:04:21 +00:00
|
|
|
|
- @ref vulkan_guide
|
2016-02-19 09:29:13 +00:00
|
|
|
|
- @ref monitor_guide
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
GLFW provides many kinds of input. While some can only be polled, like time, or
|
2016-12-06 22:26:53 +00:00
|
|
|
|
only received via callbacks, like scrolling, many provide both callbacks and
|
|
|
|
|
polling. Callbacks are more work to use than polling but is less CPU intensive
|
|
|
|
|
and guarantees that you do not miss state changes.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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
|
2022-07-28 13:56:18 +00:00
|
|
|
|
`events` test program. It registers every callback supported by GLFW and prints
|
2014-09-18 13:03:29 +00:00
|
|
|
|
out all arguments provided for every event, along with time and sequence
|
|
|
|
|
information.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Event processing {#events}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
GLFW needs to poll the window system for events both to provide input to the
|
|
|
|
|
application and to prove to the window system that the application hasn't locked
|
2016-12-09 00:21:50 +00:00
|
|
|
|
up. Event processing 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 and joystick connection
|
|
|
|
|
events.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
There are three functions for processing pending events. @ref glfwPollEvents,
|
2014-09-18 13:03:29 +00:00
|
|
|
|
processes only those events that have already been received and then returns
|
|
|
|
|
immediately.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwPollEvents();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
This is the best choice when rendering continuously, like most games do.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
If you only need to update the contents of the window when you receive new
|
|
|
|
|
input, @ref glfwWaitEvents is a better choice.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwWaitEvents();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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
|
2019-01-15 18:28:17 +00:00
|
|
|
|
useful for, for example, editing tools.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
If you want to wait for events but have UI elements or other tasks that need
|
|
|
|
|
periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
|
2016-02-02 20:11:16 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2016-02-02 20:11:16 +00:00
|
|
|
|
glfwWaitEventsTimeout(0.7);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2016-02-02 20:11:16 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwPostEmptyEvent();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
Do not assume that callbacks will _only_ be called in response to the above
|
|
|
|
|
functions. While it is necessary to process events in one or more of the ways
|
|
|
|
|
above, window systems that require GLFW to register callbacks of its own can
|
|
|
|
|
pass events to GLFW in response to many window system function calls. GLFW will
|
|
|
|
|
pass those events on to the application callbacks before returning.
|
|
|
|
|
|
|
|
|
|
For example, on Windows the system function that @ref glfwSetWindowSize is
|
|
|
|
|
implemented with will send window size events directly to the event callback
|
|
|
|
|
that every window has and that GLFW implements for its windows. If you have set
|
|
|
|
|
a [window size callback](@ref window_size) GLFW will call it in turn with the
|
|
|
|
|
new size before everything returns back out of the @ref glfwSetWindowSize call.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Keyboard input {#input_keyboard}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
GLFW divides keyboard input into two categories; key events and character
|
|
|
|
|
events. Key events relate to actual physical keyboard keys, whereas character
|
2023-12-04 19:06:10 +00:00
|
|
|
|
events relate to the text that is generated by pressing some of them.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Key input {#input_key}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
If you wish to be notified when a physical key is pressed or released or when it
|
2014-10-02 15:35:10 +00:00
|
|
|
|
repeats, set a key callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetKeyCallback(window, key_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives the [keyboard key](@ref keys), platform-specific
|
|
|
|
|
scancode, key action and [modifier bits](@ref mods).
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
|
|
|
|
{
|
|
|
|
|
if (key == GLFW_KEY_E && action == GLFW_PRESS)
|
|
|
|
|
activate_airship();
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2022-06-28 21:19:30 +00:00
|
|
|
|
The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`. Events with
|
|
|
|
|
`GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press. Most
|
|
|
|
|
keys will also emit events with `GLFW_REPEAT` actions while a key is held down.
|
|
|
|
|
|
2023-12-04 19:06:10 +00:00
|
|
|
|
Note that many keyboards have a limit on how many keys being simultaneous held
|
|
|
|
|
down that they can detect. This limit is called
|
|
|
|
|
[key rollover](https://en.wikipedia.org/wiki/Key_rollover).
|
|
|
|
|
|
2022-06-28 21:19:30 +00:00
|
|
|
|
Key events with `GLFW_REPEAT` actions are intended for text input. They are
|
|
|
|
|
emitted at the rate set in the user's keyboard settings. At most one key is
|
|
|
|
|
repeated even if several keys are held down. `GLFW_REPEAT` actions should not
|
|
|
|
|
be relied on to know which keys are being held down or to drive animation.
|
|
|
|
|
Instead you should either save the state of relevant keys based on `GLFW_PRESS`
|
|
|
|
|
and `GLFW_RELEASE` actions, or call @ref glfwGetKey, which provides basic cached
|
|
|
|
|
key state.
|
|
|
|
|
|
|
|
|
|
The key will be one of the existing [key tokens](@ref keys), or
|
|
|
|
|
`GLFW_KEY_UNKNOWN` if GLFW lacks a token for it, for example _E-mail_ and _Play_
|
|
|
|
|
keys.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2015-04-10 11:31:47 +00:00
|
|
|
|
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.
|
2023-12-04 19:06:10 +00:00
|
|
|
|
You can query the scancode for any [key token](@ref keys) supported on the
|
|
|
|
|
current platform with @ref glfwGetKeyScancode.
|
2016-12-06 22:26:53 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2016-12-06 22:26:53 +00:00
|
|
|
|
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
|
|
|
|
|
set_key_mapping(scancode, swap_weapons);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2023-12-04 19:06:10 +00:00
|
|
|
|
The last reported state for every physical key with a [key token](@ref keys) is
|
|
|
|
|
also saved in per-window state arrays that can be polled with @ref glfwGetKey.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
int state = glfwGetKey(window, GLFW_KEY_E);
|
|
|
|
|
if (state == GLFW_PRESS)
|
2017-02-13 14:36:06 +00:00
|
|
|
|
{
|
2014-09-18 13:03:29 +00:00
|
|
|
|
activate_airship();
|
2017-02-13 14:36:06 +00:00
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
|
|
|
|
|
|
|
|
|
This function only returns cached key event state. It does not poll the
|
2023-12-04 19:06:10 +00:00
|
|
|
|
system for the current state of the physical key. It also does not provide any
|
|
|
|
|
key repeat information.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
@anchor GLFW_STICKY_KEYS
|
2014-09-18 13:03:29 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2018-10-22 14:15:11 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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`.
|
|
|
|
|
|
2017-11-29 19:42:37 +00:00
|
|
|
|
@anchor GLFW_LOCK_KEY_MODS
|
|
|
|
|
If you wish to know what the state of the Caps Lock and Num Lock keys was when
|
|
|
|
|
input events were generated, set the `GLFW_LOCK_KEY_MODS` input mode.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2018-10-22 14:15:11 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_LOCK_KEY_MODS, GLFW_TRUE);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-11-29 19:42:37 +00:00
|
|
|
|
|
|
|
|
|
When this input mode is enabled, any callback that receives
|
|
|
|
|
[modifier bits](@ref mods) will have the @ref GLFW_MOD_CAPS_LOCK bit set if Caps
|
|
|
|
|
Lock was on when the event occurred and the @ref GLFW_MOD_NUM_LOCK bit set if
|
|
|
|
|
Num Lock was on.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The `GLFW_KEY_LAST` constant holds the highest value of any
|
2023-12-04 19:06:10 +00:00
|
|
|
|
[key token](@ref keys).
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Text input {#input_char}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2014-10-07 21:37:59 +00: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
|
2023-12-04 19:06:10 +00:00
|
|
|
|
operating system text input system. Unlike key input, text input is affected by
|
|
|
|
|
keyboard layouts and modifier keys and supports composing characters using
|
2014-10-07 21:37:59 +00:00
|
|
|
|
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
2017-07-09 23:28:44 +00:00
|
|
|
|
encode the code points into UTF-8 or any other encoding you prefer.
|
2014-10-07 21:37:59 +00:00
|
|
|
|
|
|
|
|
|
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
|
2017-07-09 23:28:44 +00:00
|
|
|
|
you can treat the code point argument as native endian UTF-32.
|
2014-10-07 21:37:59 +00:00
|
|
|
|
|
2017-11-29 20:03:38 +00:00
|
|
|
|
If you wish to offer regular text input, set a character callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetCharCallback(window, character_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives Unicode code points for key events that would
|
2014-10-07 21:37:59 +00:00
|
|
|
|
have led to regular text input and generally behaves as a standard text field on
|
|
|
|
|
that platform.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void character_callback(GLFWwindow* window, unsigned int codepoint)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2022-05-20 09:25:16 +00:00
|
|
|
|
@subsection preedit IME Support
|
|
|
|
|
|
|
|
|
|
All desktop operating systems support IME (Input Method Editor) to input characters
|
|
|
|
|
that are not mapped with physical keys. IME have been popular among Eeastern Asian people.
|
|
|
|
|
And some operating systems start supporting voice input via IME mechanism.
|
|
|
|
|
|
|
|
|
|
GLFW provides IME support functions to help
|
|
|
|
|
you implement better text input features. You should add suitable visualization code for
|
|
|
|
|
preedit 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 preedit callback to receive preedit text before committed.
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
glfwSetPreeditCallback(window, preedit_callback);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The callback function receives chunk of text and focused block information.
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
static void preedit_callback(GLFWwindow* window, int strLength, unsigned int* string, int blockLength, int* blocks, int focusedBlock) {
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
strLength and string parameter reprsent whole preedit text. Each character of the preedit string is a codepoint like @ref input_char.
|
|
|
|
|
|
|
|
|
|
If you want to type the text "寿司(sushi)", Usually the callback is called several times like the following sequence:
|
|
|
|
|
|
|
|
|
|
-# 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]
|
|
|
|
|
|
|
|
|
|
If preedit text includes several semantic blocks, preedit callbacks returns several blocks after a space key pressed:
|
|
|
|
|
|
|
|
|
|
-# preedit: [string: "わたしはすしをたべます", block: [11], focusedBlock: 0]
|
|
|
|
|
-# preedit: [string: "私は寿司を食べます", block: [2, 7], focusedBlock: 1]
|
|
|
|
|
|
|
|
|
|
"blocks" is a list of block length. The above case, it contains the following blocks and second block is focused.
|
|
|
|
|
|
|
|
|
|
- 私は
|
|
|
|
|
- [寿司を食べます]
|
|
|
|
|
|
|
|
|
|
commited 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 (x, y coords and height). You should call this function
|
|
|
|
|
in the above preedit text callback function.
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
glfwSetPreeditCursorPos(window, x, y, h);
|
|
|
|
|
glfwGetPreeditCursorPos(window, &x, &y, &h);
|
|
|
|
|
@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, imestatus_callback);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
imestatus_callback has simple sigunature like this:
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
static void imestatus_callback(GLFWwindow* window) {
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
You can implement the code that resets or commits preedit text when IME status is changed and preedit text is not empty.
|
|
|
|
|
|
|
|
|
|
When the focus is gone from text box, you can use the following functions to reset IME status:
|
|
|
|
|
|
|
|
|
|
@code
|
|
|
|
|
void glfwResetPreeditText(GLFWwindow* window);
|
|
|
|
|
void glfwSetIMEStatus(GLFWwindow* window, int active)
|
|
|
|
|
int glfwGetIMEStatus(GLFWwindow* window)
|
|
|
|
|
@endcode
|
2014-04-23 11:30:11 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Key names {#input_key_name}
|
2015-07-02 12:24:50 +00:00
|
|
|
|
|
|
|
|
|
If you wish to refer to keys by name, you can query the keyboard layout
|
|
|
|
|
dependent name of printable keys with @ref glfwGetKeyName.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2015-07-02 12:24:50 +00:00
|
|
|
|
const char* key_name = glfwGetKeyName(GLFW_KEY_W, 0);
|
|
|
|
|
show_tutorial_hint("Press %s to move forward", key_name);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2015-07-02 12:24:50 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Mouse input {#input_mouse}
|
2014-04-23 11:30:11 +00:00
|
|
|
|
|
2019-02-11 18:10:20 +00:00
|
|
|
|
Mouse input comes in many forms, including mouse motion, button presses and
|
2015-01-18 00:55:25 +00:00
|
|
|
|
scrolling offsets. The cursor appearance can also be changed, either to
|
|
|
|
|
a custom image or a standard cursor shape from the system theme.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Cursor position {#cursor_pos}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2015-01-18 00:55:25 +00:00
|
|
|
|
If you wish to be notified when the cursor moves over the window, set a cursor
|
|
|
|
|
position callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2018-10-22 18:46:40 +00:00
|
|
|
|
glfwSetCursorPosCallback(window, cursor_position_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-02-17 13:52:01 +00:00
|
|
|
|
The callback functions receives the cursor position, measured in screen
|
2019-01-22 19:54:16 +00:00
|
|
|
|
coordinates but relative to the top-left corner of the window content area. On
|
2016-02-17 13:52:01 +00:00
|
|
|
|
platforms that provide it, the full sub-pixel cursor position is passed on.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The cursor position is also saved per-window and can be polled with @ref
|
|
|
|
|
glfwGetCursorPos.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
double xpos, ypos;
|
|
|
|
|
glfwGetCursorPos(window, &xpos, &ypos);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Cursor mode {#cursor_mode}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
@anchor GLFW_CURSOR
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
|
2015-01-18 00:55:25 +00:00
|
|
|
|
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.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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`.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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
|
2015-01-18 00:55:25 +00:00
|
|
|
|
is provided normally via both the cursor position callback and through polling.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
@note You should not implement your own version of this functionality using
|
2015-01-18 00:55:25 +00:00
|
|
|
|
other features of GLFW. It is not supported and will not work as robustly as
|
|
|
|
|
`GLFW_CURSOR_DISABLED`.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-10-22 14:27:17 +00:00
|
|
|
|
If you only wish the cursor to become hidden when it is over a window but still
|
|
|
|
|
want it to behave normally, set the cursor mode to `GLFW_CURSOR_HIDDEN`.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
This mode puts no limit on the motion of the cursor.
|
|
|
|
|
|
2019-12-03 16:58:20 +00:00
|
|
|
|
If you wish the cursor to be visible but confined to the content area of the
|
|
|
|
|
window, set the cursor mode to `GLFW_CURSOR_CAPTURED`.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2019-12-03 16:58:20 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_CAPTURED);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2019-12-03 16:58:20 +00:00
|
|
|
|
|
|
|
|
|
The cursor will behave normally inside the content area but will not be able to
|
|
|
|
|
leave unless the window loses focus.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
To exit out of either of these special modes, restore the `GLFW_CURSOR_NORMAL`
|
|
|
|
|
cursor mode.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-12-03 16:58:20 +00:00
|
|
|
|
If the cursor was disabled, this will move it back to its last visible position.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-02-11 18:10:20 +00:00
|
|
|
|
@anchor GLFW_RAW_MOUSE_MOTION
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Raw mouse motion {#raw_mouse_motion}
|
2019-02-11 18:10:20 +00:00
|
|
|
|
|
|
|
|
|
When the cursor is disabled, raw (unscaled and unaccelerated) mouse motion can
|
|
|
|
|
be enabled if available.
|
|
|
|
|
|
|
|
|
|
Raw mouse motion is closer to the actual motion of the mouse across a surface.
|
|
|
|
|
It is not affected by the scaling and acceleration applied to the motion of the
|
|
|
|
|
desktop cursor. That processing is suitable for a cursor while raw motion is
|
|
|
|
|
better for controlling for example a 3D camera. Because of this, raw mouse
|
|
|
|
|
motion is only provided when the cursor is disabled.
|
|
|
|
|
|
|
|
|
|
Call @ref glfwRawMouseMotionSupported to check if the current machine provides
|
|
|
|
|
raw motion and set the `GLFW_RAW_MOUSE_MOTION` input mode to enable it. It is
|
|
|
|
|
disabled by default.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2019-02-11 18:10:20 +00:00
|
|
|
|
if (glfwRawMouseMotionSupported())
|
|
|
|
|
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2019-02-11 18:10:20 +00:00
|
|
|
|
|
|
|
|
|
If supported, raw mouse motion can be enabled or disabled per-window and at any
|
|
|
|
|
time but it will only be provided when the cursor is disabled.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Cursor objects {#cursor_object}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2015-01-18 00:55:25 +00:00
|
|
|
|
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.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
#### Custom cursor creation {#cursor_custom}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2015-01-18 00:55:25 +00:00
|
|
|
|
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:
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
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);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2014-10-02 15:35:10 +00:00
|
|
|
|
If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
|
|
|
|
the return value.
|
|
|
|
|
|
2015-08-17 19:04:19 +00:00
|
|
|
|
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
2017-06-06 16:17:58 +00:00
|
|
|
|
per channel with the red channel first. The pixels are arranged canonically as
|
|
|
|
|
sequential rows, starting from the top-left corner.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
#### Standard cursor creation {#cursor_standard}
|
2015-01-18 00:55:25 +00:00
|
|
|
|
|
|
|
|
|
A cursor with a [standard shape](@ref shapes) from the current system cursor
|
2022-07-28 13:56:18 +00:00
|
|
|
|
theme can be created with @ref glfwCreateStandardCursor.
|
2015-01-18 00:55:25 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2019-05-07 18:40:37 +00:00
|
|
|
|
GLFWcursor* url_cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2015-01-18 00:55:25 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2019-05-07 18:40:37 +00:00
|
|
|
|
A few of these shapes are not available everywhere. If a shape is unavailable,
|
|
|
|
|
`NULL` is returned. See @ref glfwCreateStandardCursor for details.
|
|
|
|
|
|
2015-01-18 00:55:25 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
#### Cursor destruction {#cursor_destruction}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwDestroyCursor(cursor);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
Cursor destruction always succeeds. If the cursor is current for any window,
|
|
|
|
|
that window will revert to the default cursor. This does not affect the cursor
|
2018-08-23 07:51:01 +00:00
|
|
|
|
mode. All remaining cursors are destroyed when @ref glfwTerminate is called.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
#### Cursor setting {#cursor_set}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
A cursor can be set as current for a window with @ref glfwSetCursor.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetCursor(window, cursor);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
Once set, the cursor image will be used as long as the system cursor is over the
|
2019-01-22 19:54:16 +00:00
|
|
|
|
content area of the window and the [cursor mode](@ref cursor_mode) is set
|
2014-09-18 13:03:29 +00:00
|
|
|
|
to `GLFW_CURSOR_NORMAL`.
|
|
|
|
|
|
|
|
|
|
A single cursor may be set for any number of windows.
|
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
To revert to the default cursor, set the cursor of that window to `NULL`.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetCursor(window, NULL);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
When a cursor is destroyed, any window that has it set will revert to the
|
|
|
|
|
default cursor. This does not affect the cursor mode.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Cursor enter/leave events {#cursor_enter}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-01-22 19:54:16 +00:00
|
|
|
|
If you wish to be notified when the cursor enters or leaves the content area of
|
2014-10-02 15:35:10 +00:00
|
|
|
|
a window, set a cursor enter/leave callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetCursorEnterCallback(window, cursor_enter_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives the new classification of the cursor.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void cursor_enter_callback(GLFWwindow* window, int entered)
|
|
|
|
|
{
|
|
|
|
|
if (entered)
|
|
|
|
|
{
|
2019-01-22 19:54:16 +00:00
|
|
|
|
// The cursor entered the content area of the window
|
2014-09-18 13:03:29 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2019-01-22 19:54:16 +00:00
|
|
|
|
// The cursor left the content area of the window
|
2014-09-18 13:03:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-01-22 19:54:16 +00:00
|
|
|
|
You can query whether the cursor is currently inside the content area of the
|
2018-01-04 12:50:58 +00:00
|
|
|
|
window with the [GLFW_HOVERED](@ref GLFW_HOVERED_attrib) window attribute.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2018-01-04 12:50:58 +00:00
|
|
|
|
if (glfwGetWindowAttrib(window, GLFW_HOVERED))
|
|
|
|
|
{
|
|
|
|
|
highlight_interface();
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2018-01-04 12:50:58 +00:00
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Mouse button input {#input_mouse_button}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
If you wish to be notified when a mouse button is pressed or released, set
|
2014-10-02 15:35:10 +00:00
|
|
|
|
a mouse button callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-29 15:50:50 +00:00
|
|
|
|
@anchor GLFW_UNLIMITED_MOUSE_BUTTONS
|
|
|
|
|
To handle all mouse buttons in the callback, instead of only ones with associated
|
|
|
|
|
[button tokens](@ref buttons), set the @ref GLFW_UNLIMITED_MOUSE_BUTTONS
|
|
|
|
|
input mode.
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
glfwSetInputMode(window, GLFW_UNLIMITED_MOUSE_BUTTONS, GLFW_TRUE);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
When this input mode is enabled, GLFW doesn't limit the reported mouse buttons
|
|
|
|
|
to only those that have an associated button token, for compatibility with
|
|
|
|
|
earlier versions of GLFW, which never reported any buttons over
|
|
|
|
|
@ref GLFW_MOUSE_BUTTON_LAST, on which users could have relied on.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The callback function receives the [mouse button](@ref buttons), button action
|
|
|
|
|
and [modifier bits](@ref mods).
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
|
|
|
|
{
|
|
|
|
|
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
|
|
|
|
|
popup_menu();
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-29 15:50:50 +00:00
|
|
|
|
The mouse button is an integer that can be one of the
|
|
|
|
|
[mouse button tokens](@ref buttons) or, if the
|
|
|
|
|
@ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set, any other positive value.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
|
|
|
|
|
2024-02-29 15:50:50 +00:00
|
|
|
|
The last reported state for every [mouse button token](@ref buttons) is also
|
2023-12-04 19:06:10 +00:00
|
|
|
|
saved in per-window state arrays that can be polled with @ref
|
2024-02-29 15:50:50 +00:00
|
|
|
|
glfwGetMouseButton. This is not effected by the @ref GLFW_UNLIMITED_MOUSE_BUTTONS
|
|
|
|
|
input mode.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
|
|
|
|
if (state == GLFW_PRESS)
|
2017-02-13 14:36:06 +00:00
|
|
|
|
{
|
2014-09-18 13:03:29 +00:00
|
|
|
|
upgrade_cow();
|
2017-02-13 14:36:06 +00:00
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2017-02-20 12:45:11 +00:00
|
|
|
|
@anchor GLFW_STICKY_MOUSE_BUTTONS
|
2014-09-18 13:03:29 +00:00
|
|
|
|
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.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2018-10-22 14:15:11 +00:00
|
|
|
|
glfwSetInputMode(window, GLFW_STICKY_MOUSE_BUTTONS, GLFW_TRUE);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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
|
2024-02-29 15:50:50 +00:00
|
|
|
|
[mouse button token](@ref buttons).
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Scroll input {#scrolling}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
If you wish to be notified when the user scrolls, whether with a mouse wheel or
|
2014-10-02 15:35:10 +00:00
|
|
|
|
touchpad gesture, set a scroll callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetScrollCallback(window, scroll_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives two-dimensional scroll offsets.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
|
|
|
|
{
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-10-22 14:27:17 +00:00
|
|
|
|
A normal mouse wheel, being vertical, provides offsets along the Y-axis.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Joystick input {#joystick}
|
2014-04-23 11:30:11 +00:00
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The joystick functions expose connected joysticks and controllers, with both
|
|
|
|
|
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
2017-03-01 22:27:20 +00:00
|
|
|
|
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
|
|
|
|
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
|
|
|
|
present with @ref glfwJoystickPresent.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-12-07 15:19:57 +00:00
|
|
|
|
Each joystick has zero or more axes, zero or more buttons, zero or more hats,
|
|
|
|
|
a human-readable name, a user pointer and an SDL compatible GUID.
|
|
|
|
|
|
2020-07-12 16:31:29 +00:00
|
|
|
|
Detected joysticks are added to the beginning of the array. Once a joystick is
|
|
|
|
|
detected, it keeps its assigned ID until it is disconnected or the library is
|
|
|
|
|
terminated, so as joysticks are connected and disconnected, there may appear
|
|
|
|
|
gaps in the IDs.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2017-03-01 22:27:20 +00:00
|
|
|
|
Joystick axis, button and hat state is updated when polled and does not require
|
|
|
|
|
a window to be created or events to be processed. However, if you want joystick
|
|
|
|
|
connection and disconnection events reliably delivered to the
|
|
|
|
|
[joystick callback](@ref joystick_event) then you must
|
|
|
|
|
[process events](@ref events).
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2016-12-06 22:26:53 +00:00
|
|
|
|
To see all the properties of all connected joysticks in real-time, run the
|
|
|
|
|
`joysticks` test program.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick axis states {#joystick_axis}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The positions of all axes of a joystick are returned by @ref
|
|
|
|
|
glfwGetJoystickAxes. See the reference documentation for the lifetime of the
|
|
|
|
|
returned array.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
int count;
|
2017-03-01 22:27:20 +00:00
|
|
|
|
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
Each element in the returned array is a value between -1.0 and 1.0.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick button states {#joystick_button}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The states of all buttons of a joystick are returned by @ref
|
|
|
|
|
glfwGetJoystickButtons. See the reference documentation for the lifetime of the
|
|
|
|
|
returned array.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
int count;
|
2017-03-01 22:27:20 +00:00
|
|
|
|
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
|
|
|
|
|
2017-03-01 22:27:20 +00:00
|
|
|
|
For backward compatibility with earlier versions that did not have @ref
|
|
|
|
|
glfwGetJoystickHats, the button array by default also includes all hats. See
|
|
|
|
|
the reference documentation for @ref glfwGetJoystickButtons for details.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick hat states {#joystick_hat}
|
2017-03-01 22:27:20 +00:00
|
|
|
|
|
|
|
|
|
The states of all hats are returned by @ref glfwGetJoystickHats. See the
|
|
|
|
|
reference documentation for the lifetime of the returned array.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-03-01 22:27:20 +00:00
|
|
|
|
int count;
|
|
|
|
|
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-03-01 22:27:20 +00:00
|
|
|
|
|
|
|
|
|
Each element in the returned array is one of the following:
|
|
|
|
|
|
|
|
|
|
Name | Value
|
2018-11-11 17:49:47 +00:00
|
|
|
|
---- | -----
|
2017-03-01 22:27:20 +00:00
|
|
|
|
`GLFW_HAT_CENTERED` | 0
|
|
|
|
|
`GLFW_HAT_UP` | 1
|
|
|
|
|
`GLFW_HAT_RIGHT` | 2
|
|
|
|
|
`GLFW_HAT_DOWN` | 4
|
|
|
|
|
`GLFW_HAT_LEFT` | 8
|
|
|
|
|
`GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
|
|
|
|
|
`GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
|
|
|
|
|
`GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
|
|
|
|
|
`GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
|
|
|
|
|
|
|
|
|
|
The diagonal directions are bitwise combinations of the primary (up, right, down
|
|
|
|
|
and left) directions and you can test for these individually by ANDing it with
|
|
|
|
|
the corresponding direction.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-03-01 22:27:20 +00:00
|
|
|
|
if (hats[2] & GLFW_HAT_RIGHT)
|
|
|
|
|
{
|
|
|
|
|
// State of hat 2 could be right-up, right or right-down
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-03-01 22:27:20 +00:00
|
|
|
|
|
|
|
|
|
For backward compatibility with earlier versions that did not have @ref
|
|
|
|
|
glfwGetJoystickHats, all hats are by default also included in the button array.
|
|
|
|
|
See the reference documentation for @ref glfwGetJoystickButtons for details.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick name {#joystick_name}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The human-readable, UTF-8 encoded name of a joystick is returned by @ref
|
|
|
|
|
glfwGetJoystickName. See the reference documentation for the lifetime of the
|
2017-11-17 03:34:18 +00:00
|
|
|
|
returned string.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-03-01 22:27:20 +00:00
|
|
|
|
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
2020-07-21 16:06:13 +00:00
|
|
|
|
and make may have the same name. Only the [joystick ID](@ref joysticks) is
|
2014-09-18 13:03:29 +00:00
|
|
|
|
guaranteed to be unique, and only until that joystick is disconnected.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick user pointer {#joystick_userptr}
|
2017-12-07 15:19:57 +00:00
|
|
|
|
|
|
|
|
|
Each joystick has a user pointer that can be set with @ref
|
|
|
|
|
glfwSetJoystickUserPointer and queried with @ref glfwGetJoystickUserPointer.
|
|
|
|
|
This can be used for any purpose you need and will not be modified by GLFW. The
|
|
|
|
|
value will be kept until the joystick is disconnected or until the library is
|
|
|
|
|
terminated.
|
|
|
|
|
|
|
|
|
|
The initial value of the pointer is `NULL`.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Joystick configuration changes {#joystick_event}
|
2015-12-13 16:38:50 +00:00
|
|
|
|
|
|
|
|
|
If you wish to be notified when a joystick is connected or disconnected, set
|
|
|
|
|
a joystick callback.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2015-12-13 16:38:50 +00:00
|
|
|
|
glfwSetJoystickCallback(joystick_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2015-12-13 16:38:50 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives the ID of the joystick that has been connected
|
|
|
|
|
and disconnected and the event that occurred.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2016-10-10 01:24:07 +00:00
|
|
|
|
void joystick_callback(int jid, int event)
|
2015-12-13 16:38:50 +00:00
|
|
|
|
{
|
|
|
|
|
if (event == GLFW_CONNECTED)
|
|
|
|
|
{
|
|
|
|
|
// The joystick was connected
|
|
|
|
|
}
|
|
|
|
|
else if (event == GLFW_DISCONNECTED)
|
|
|
|
|
{
|
|
|
|
|
// The joystick was disconnected
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2015-12-13 16:38:50 +00:00
|
|
|
|
|
2017-02-01 03:55:46 +00:00
|
|
|
|
For joystick connection and disconnection events to be delivered on all
|
|
|
|
|
platforms, you need to call one of the [event processing](@ref events)
|
|
|
|
|
functions. Joystick disconnection may also be detected and the callback
|
|
|
|
|
called by joystick functions. The function will then return whatever it
|
|
|
|
|
returns for a disconnected joystick.
|
|
|
|
|
|
2017-12-07 15:19:57 +00:00
|
|
|
|
Only @ref glfwGetJoystickName and @ref glfwGetJoystickUserPointer will return
|
|
|
|
|
useful values for a disconnected joystick and only before the monitor callback
|
|
|
|
|
returns.
|
|
|
|
|
|
2015-12-13 16:38:50 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Gamepad input {#gamepad}
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
The joystick functions provide unlabeled axes, buttons and hats, with no
|
|
|
|
|
indication of where they are located on the device. Their order may also vary
|
|
|
|
|
between platforms even with the same device.
|
|
|
|
|
|
|
|
|
|
To solve this problem the SDL community crowdsourced the
|
2024-02-14 00:36:35 +00:00
|
|
|
|
[SDL_GameControllerDB][] project, a database of mappings from many different
|
|
|
|
|
devices to an Xbox-like gamepad.
|
|
|
|
|
|
|
|
|
|
[SDL_GameControllerDB]: https://github.com/gabomdq/SDL_GameControllerDB
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
GLFW supports this mapping format and contains a copy of the mappings
|
|
|
|
|
available at the time of release. See @ref gamepad_mapping for how to update
|
|
|
|
|
this at runtime. Mappings will be assigned to joysticks automatically any time
|
|
|
|
|
a joystick is connected or the mappings are updated.
|
|
|
|
|
|
|
|
|
|
You can check whether a joystick is both present and has a gamepad mapping with
|
|
|
|
|
@ref glfwJoystickIsGamepad.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-06-18 13:13:25 +00:00
|
|
|
|
if (glfwJoystickIsGamepad(GLFW_JOYSTICK_2))
|
|
|
|
|
{
|
|
|
|
|
// Use as gamepad
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
If you are only interested in gamepad input you can use this function instead of
|
|
|
|
|
@ref glfwJoystickPresent.
|
|
|
|
|
|
|
|
|
|
You can query the human-readable name provided by the gamepad mapping with @ref
|
|
|
|
|
glfwGetGamepadName. This may or may not be the same as the
|
|
|
|
|
[joystick name](@ref joystick_name).
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-06-18 13:13:25 +00:00
|
|
|
|
const char* name = glfwGetGamepadName(GLFW_JOYSTICK_7);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
To retrieve the gamepad state of a joystick, call @ref glfwGetGamepadState.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-06-18 13:13:25 +00:00
|
|
|
|
GLFWgamepadstate state;
|
|
|
|
|
|
|
|
|
|
if (glfwGetGamepadState(GLFW_JOYSTICK_3, &state))
|
|
|
|
|
{
|
|
|
|
|
if (state.buttons[GLFW_GAMEPAD_BUTTON_A])
|
|
|
|
|
{
|
|
|
|
|
input_jump();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input_speed(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]);
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
The @ref GLFWgamepadstate struct has two arrays; one for button states and one
|
|
|
|
|
for axis states. The values for each button and axis are the same as for the
|
|
|
|
|
@ref glfwGetJoystickButtons and @ref glfwGetJoystickAxes functions, i.e.
|
|
|
|
|
`GLFW_PRESS` or `GLFW_RELEASE` for buttons and -1.0 to 1.0 inclusive for axes.
|
|
|
|
|
|
|
|
|
|
The sizes of the arrays and the positions within each array are fixed.
|
|
|
|
|
|
|
|
|
|
The [button indices](@ref gamepad_buttons) are `GLFW_GAMEPAD_BUTTON_A`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_B`, `GLFW_GAMEPAD_BUTTON_X`, `GLFW_GAMEPAD_BUTTON_Y`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_LEFT_BUMPER`, `GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_BACK`, `GLFW_GAMEPAD_BUTTON_START`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_GUIDE`, `GLFW_GAMEPAD_BUTTON_LEFT_THUMB`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_RIGHT_THUMB`, `GLFW_GAMEPAD_BUTTON_DPAD_UP`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_DPAD_RIGHT`, `GLFW_GAMEPAD_BUTTON_DPAD_DOWN` and
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_DPAD_LEFT`.
|
|
|
|
|
|
|
|
|
|
For those who prefer, there are also the `GLFW_GAMEPAD_BUTTON_CROSS`,
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_CIRCLE`, `GLFW_GAMEPAD_BUTTON_SQUARE` and
|
|
|
|
|
`GLFW_GAMEPAD_BUTTON_TRIANGLE` aliases for the A, B, X and Y button indices.
|
|
|
|
|
|
|
|
|
|
The [axis indices](@ref gamepad_axes) are `GLFW_GAMEPAD_AXIS_LEFT_X`,
|
|
|
|
|
`GLFW_GAMEPAD_AXIS_LEFT_Y`, `GLFW_GAMEPAD_AXIS_RIGHT_X`,
|
|
|
|
|
`GLFW_GAMEPAD_AXIS_RIGHT_Y`, `GLFW_GAMEPAD_AXIS_LEFT_TRIGGER` and
|
|
|
|
|
`GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER`.
|
|
|
|
|
|
|
|
|
|
The `GLFW_GAMEPAD_BUTTON_LAST` and `GLFW_GAMEPAD_AXIS_LAST` constants equal
|
|
|
|
|
the largest available index for each array.
|
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
### Gamepad mappings {#gamepad_mapping}
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
2024-02-14 00:36:35 +00:00
|
|
|
|
GLFW contains a copy of the mappings available in [SDL_GameControllerDB][] at
|
|
|
|
|
the time of release. Newer ones can be added at runtime with @ref
|
2017-07-09 19:55:06 +00:00
|
|
|
|
glfwUpdateGamepadMappings.
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2019-04-01 16:36:30 +00:00
|
|
|
|
const char* mappings = load_file_contents("game/data/gamecontrollerdb.txt");
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
glfwUpdateGamepadMappings(mappings);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
2017-07-09 19:55:06 +00:00
|
|
|
|
This function supports everything from single lines up to and including the
|
|
|
|
|
unmodified contents of the whole `gamecontrollerdb.txt` file.
|
|
|
|
|
|
2021-06-28 21:52:07 +00:00
|
|
|
|
If you are compiling GLFW from source with CMake you can update the built-in mappings by
|
|
|
|
|
building the _update_mappings_ target. This runs the `GenerateMappings.cmake` CMake
|
|
|
|
|
script, which downloads `gamecontrollerdb.txt` and regenerates the `mappings.h` header
|
|
|
|
|
file.
|
|
|
|
|
|
2017-06-18 13:13:25 +00:00
|
|
|
|
Below is a description of the mapping format. Please keep in mind that __this
|
|
|
|
|
description is not authoritative__. The format is defined by the SDL and
|
|
|
|
|
SDL_GameControllerDB projects and their documentation and code takes precedence.
|
|
|
|
|
|
|
|
|
|
Each mapping is a single line of comma-separated values describing the GUID,
|
|
|
|
|
name and layout of the gamepad. Lines that do not begin with a hexadecimal
|
|
|
|
|
digit are ignored.
|
|
|
|
|
|
|
|
|
|
The first value is always the gamepad GUID, a 32 character long hexadecimal
|
|
|
|
|
string that typically identifies its make, model, revision and the type of
|
|
|
|
|
connection to the computer. When this information is not available, the GUID is
|
|
|
|
|
generated using the gamepad name. GLFW uses the SDL 2.0.5+ GUID format but can
|
|
|
|
|
convert from the older formats.
|
|
|
|
|
|
|
|
|
|
The second value is always the human-readable name of the gamepad.
|
|
|
|
|
|
|
|
|
|
All subsequent values are in the form `<field>:<value>` and describe the layout
|
|
|
|
|
of the mapping. These fields may not all be present and may occur in any order.
|
|
|
|
|
|
2022-03-13 14:18:39 +00:00
|
|
|
|
The button fields are `a`, `b`, `x`, `y`, `back`, `start`, `guide`, `dpup`,
|
2017-06-18 13:13:25 +00:00
|
|
|
|
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
|
|
|
|
`rightstick`.
|
|
|
|
|
|
|
|
|
|
The axis fields are `leftx`, `lefty`, `rightx`, `righty`, `lefttrigger` and
|
|
|
|
|
`righttrigger`.
|
|
|
|
|
|
|
|
|
|
The value of an axis or button field can be a joystick button, a joystick axis,
|
|
|
|
|
a hat bitmask or empty. Joystick buttons are specified as `bN`, for example
|
|
|
|
|
`b2` for the third button. Joystick axes are specified as `aN`, for example
|
|
|
|
|
`a7` for the eighth button. Joystick hat bit masks are specified as `hN.N`, for
|
|
|
|
|
example `h0.8` for left on the first hat. More than one bit may be set in the
|
|
|
|
|
mask.
|
|
|
|
|
|
2018-02-13 16:07:46 +00:00
|
|
|
|
Before an axis there may be a `+` or `-` range modifier, for example `+a3` for
|
|
|
|
|
the positive half of the fourth axis. This restricts input to only the positive
|
|
|
|
|
or negative halves of the joystick axis. After an axis or half-axis there may
|
|
|
|
|
be the `~` inversion modifier, for example `a2~` or `-a7~`. This negates the
|
|
|
|
|
values of the gamepad axis.
|
|
|
|
|
|
2017-06-18 13:13:25 +00:00
|
|
|
|
The hat bit mask match the [hat states](@ref hat_state) in the joystick
|
|
|
|
|
functions.
|
|
|
|
|
|
|
|
|
|
There is also the special `platform` field that specifies which platform the
|
|
|
|
|
mapping is valid for. Possible values are `Windows`, `Mac OS X` and `Linux`.
|
|
|
|
|
|
2017-07-09 19:55:06 +00:00
|
|
|
|
Below is an example of what a gamepad mapping might look like. It is the
|
|
|
|
|
one built into GLFW for Xbox controllers accessed via the XInput API on Windows.
|
|
|
|
|
This example has been broken into several lines to fit on the page, but real
|
|
|
|
|
gamepad mappings must be a single line.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-07-09 19:55:06 +00:00
|
|
|
|
78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,
|
|
|
|
|
b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,
|
|
|
|
|
rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,
|
|
|
|
|
righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2017-07-09 19:55:06 +00:00
|
|
|
|
|
2018-02-13 16:07:46 +00:00
|
|
|
|
@note GLFW does not yet support the output range and modifiers `+` and `-` that
|
|
|
|
|
were recently added to SDL. The input modifiers `+`, `-` and `~` are supported
|
|
|
|
|
and described above.
|
2017-06-18 13:13:25 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Time input {#time}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
GLFW provides high-resolution time input, in seconds, with @ref glfwGetTime.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
double seconds = glfwGetTime();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-05-20 15:13:09 +00:00
|
|
|
|
It returns the number of seconds since the library was initialized with @ref
|
|
|
|
|
glfwInit. The platform-specific time sources used typically have micro- or
|
|
|
|
|
nanosecond resolution.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-05-20 15:13:09 +00:00
|
|
|
|
You can modify the base time with @ref glfwSetTime.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetTime(4.0);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-05-20 15:13:09 +00:00
|
|
|
|
This sets the time to the specified time, in seconds, and it continues to count
|
|
|
|
|
from there.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2019-05-20 15:13:09 +00:00
|
|
|
|
You can also access the raw timer used to implement the functions above,
|
|
|
|
|
with @ref glfwGetTimerValue.
|
2016-03-06 10:38:55 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2016-03-23 09:09:07 +00:00
|
|
|
|
uint64_t value = glfwGetTimerValue();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2016-03-06 10:38:55 +00:00
|
|
|
|
|
2019-05-20 15:13:09 +00:00
|
|
|
|
This value is in 1 / frequency seconds. The frequency of the raw
|
|
|
|
|
timer varies depending on the operating system and hardware. You can query the
|
|
|
|
|
frequency, in Hz, with @ref glfwGetTimerFrequency.
|
2016-03-06 10:38:55 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2019-08-12 10:52:31 +00:00
|
|
|
|
uint64_t frequency = glfwGetTimerFrequency();
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2016-03-06 10:38:55 +00:00
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Clipboard input and output {#clipboard}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-11-04 20:11:58 +00:00
|
|
|
|
const char* text = glfwGetClipboardString(NULL);
|
2015-09-16 14:27:28 +00:00
|
|
|
|
if (text)
|
2017-02-13 14:36:06 +00:00
|
|
|
|
{
|
2015-09-16 14:27:28 +00:00
|
|
|
|
insert_text(text);
|
2017-02-13 14:36:06 +00:00
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2015-09-16 14:27:28 +00:00
|
|
|
|
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
|
|
|
|
returned.
|
|
|
|
|
|
2014-09-18 13:03:29 +00:00
|
|
|
|
The contents of the system clipboard can be set to a UTF-8 encoded string with
|
|
|
|
|
@ref glfwSetClipboardString.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2017-11-04 20:11:58 +00:00
|
|
|
|
glfwSetClipboardString(NULL, "A string with words in it");
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
|
2024-02-13 19:45:29 +00:00
|
|
|
|
## Path drop input {#path_drop}
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
If you wish to receive the paths of files and/or directories dropped on
|
2014-10-02 15:35:10 +00:00
|
|
|
|
a window, set a file drop callback.
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
glfwSetDropCallback(window, drop_callback);
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
The callback function receives an array of paths encoded as UTF-8.
|
|
|
|
|
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```c
|
2014-09-18 13:03:29 +00:00
|
|
|
|
void drop_callback(GLFWwindow* window, int count, const char** paths)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
handle_dropped_file(paths[i]);
|
|
|
|
|
}
|
2024-02-13 19:57:45 +00:00
|
|
|
|
```
|
2014-09-18 13:03:29 +00:00
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|