mirror of
https://github.com/glfw/glfw.git
synced 2025-12-16 12:13:17 +00:00
Merge branch 'master' of https://github.com/glfw/glfw into mir-deprecations
This commit is contained in:
commit
a280bffcff
36
.github/CONTRIBUTING.md
vendored
36
.github/CONTRIBUTING.md
vendored
@ -51,6 +51,27 @@ __Don't worry about adding too much information__. Unimportant information can
|
|||||||
be abbreviated or removed later, but missing information can stall bug fixing,
|
be abbreviated or removed later, but missing information can stall bug fixing,
|
||||||
especially when your schedule doesn't align with that of the maintainer.
|
especially when your schedule doesn't align with that of the maintainer.
|
||||||
|
|
||||||
|
__Please provide text as text, not as images__. This includes code, error
|
||||||
|
messages and any other text. Text in images cannot be found by other users
|
||||||
|
searching for the same problem and may have to be re-typed by maintainers when
|
||||||
|
debugging.
|
||||||
|
|
||||||
|
You don't need to manually indent your code or other text to quote it with
|
||||||
|
GitHub Markdown; just surround it with triple backticks:
|
||||||
|
|
||||||
|
```
|
||||||
|
Some quoted text.
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also add syntax highlighting by appending the common file extension:
|
||||||
|
|
||||||
|
```c
|
||||||
|
int five(void)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
There are issue labels for both platforms and GPU manufacturers, so there is no
|
There are issue labels for both platforms and GPU manufacturers, so there is no
|
||||||
need to mention these in the subject line. If you do, it will be removed when
|
need to mention these in the subject line. If you do, it will be removed when
|
||||||
the issue is labeled.
|
the issue is labeled.
|
||||||
@ -139,6 +160,9 @@ Always include the __operating system name and version__ (e.g. `Windows
|
|||||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||||
|
|
||||||
|
If you are running your program in a virtual machine, please mention this and
|
||||||
|
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||||
|
|
||||||
Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
|
Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
|
||||||
/dev/js`), as described
|
/dev/js`), as described
|
||||||
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
|
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
|
||||||
@ -178,6 +202,9 @@ Always include the __operating system name and version__ (e.g. `Windows
|
|||||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||||
|
|
||||||
|
If you are running your program in a virtual machine, please mention this and
|
||||||
|
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||||
|
|
||||||
Please also include any __error messages__ provided to your application via the
|
Please also include any __error messages__ provided to your application via the
|
||||||
[error
|
[error
|
||||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||||
@ -215,6 +242,9 @@ Always include the __operating system name and version__ (e.g. `Windows
|
|||||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||||
|
|
||||||
|
If you are running your program in a virtual machine, please mention this and
|
||||||
|
include the __VM name and version__ (e.g. `VirtualBox 5.1`).
|
||||||
|
|
||||||
Please also include any __error messages__ provided to your application via the
|
Please also include any __error messages__ provided to your application via the
|
||||||
[error
|
[error
|
||||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||||
@ -306,6 +336,9 @@ other bugs and features to work on.
|
|||||||
If the patch fixes a bug introduced after the last release, it should not get
|
If the patch fixes a bug introduced after the last release, it should not get
|
||||||
a change log entry.
|
a change log entry.
|
||||||
|
|
||||||
|
If you haven't already, read the excellent article [How to Write a Git Commit
|
||||||
|
Message](https://chris.beams.io/posts/git-commit/).
|
||||||
|
|
||||||
|
|
||||||
## Contributing a feature
|
## Contributing a feature
|
||||||
|
|
||||||
@ -343,6 +376,9 @@ If it adds a new OpenGL, OpenGL ES or Vulkan option or extension, support
|
|||||||
for it must be added to `tests/glfwinfo.c` and the behavior of the library when
|
for it must be added to `tests/glfwinfo.c` and the behavior of the library when
|
||||||
the extension is missing documented in `docs/compat.dox`.
|
the extension is missing documented in `docs/compat.dox`.
|
||||||
|
|
||||||
|
If you haven't already, read the excellent article [How to Write a Git Commit
|
||||||
|
Message](https://chris.beams.io/posts/git-commit/).
|
||||||
|
|
||||||
Features will not be rejected because they don't include all the above parts,
|
Features will not be rejected because they don't include all the above parts,
|
||||||
but please keep in mind that maintainer time is finite and that there are many
|
but please keep in mind that maintainer time is finite and that there are many
|
||||||
other features and bugs to work on.
|
other features and bugs to work on.
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2002-2006 Marcus Geelnard
|
Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
|
|
||||||
This software is provided 'as-is', without any express or implied
|
This software is provided 'as-is', without any express or implied
|
||||||
15
README.md
15
README.md
@ -127,11 +127,14 @@ information on what to include when reporting a bug.
|
|||||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||||
receiving window maximization events (#778)
|
receiving window maximization events (#778)
|
||||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
||||||
|
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||||
|
(#889,#906,#934)
|
||||||
- Added `glfwInitHint` function for setting library initialization hints
|
- Added `glfwInitHint` function for setting library initialization hints
|
||||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||||
- Added definition of `GLAPIENTRY` to public header
|
- Added definition of `GLAPIENTRY` to public header
|
||||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||||
(#749,#842)
|
(#749,#842)
|
||||||
|
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||||
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
- Added macOS specific `GLFW_COCOA_FRAME_AUTOSAVE` window hint (#195)
|
||||||
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
- Added macOS specific `GLFW_COCOA_GRAPHICS_SWITCHING` window hint (#377,#935)
|
||||||
@ -162,10 +165,15 @@ information on what to include when reporting a bug.
|
|||||||
- [Win32] Bugfix: Mouse capture logic lost secondary release messages (#954)
|
- [Win32] Bugfix: Mouse capture logic lost secondary release messages (#954)
|
||||||
- [Win32] Bugfix: The 32-bit Vulkan loader library static was not searched for
|
- [Win32] Bugfix: The 32-bit Vulkan loader library static was not searched for
|
||||||
- [Win32] Bugfix: Vulkan libraries have a new path as of SDK 1.0.42.0 (#956)
|
- [Win32] Bugfix: Vulkan libraries have a new path as of SDK 1.0.42.0 (#956)
|
||||||
|
- [Win32] Bugfix: Monitors with no display devices were not enumerated (#960)
|
||||||
|
- [Win32] Bugfix: Monitor events were not emitted (#784)
|
||||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||||
- [X11] Bugfix: Dynamic X11 library loading did not use full sonames (#941)
|
- [X11] Bugfix: Dynamic X11 library loading did not use full sonames (#941)
|
||||||
- [X11] Bugfix: Window creation on 64-bit would read past top of stack (#951)
|
- [X11] Bugfix: Window creation on 64-bit would read past top of stack (#951)
|
||||||
|
- [X11] Bugfix: XDND support had multiple non-conformance issues (#968)
|
||||||
|
- [X11] Bugfix: The RandR monitor path was disabled despite working RandR (#972)
|
||||||
|
- [X11] Bugfix: IM-duplicated key events would leak at low polling rates (#747)
|
||||||
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
|
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
|
||||||
- [Cocoa] Added support for Vulkan window surface creation via
|
- [Cocoa] Added support for Vulkan window surface creation via
|
||||||
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
|
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
|
||||||
@ -178,8 +186,15 @@ information on what to include when reporting a bug.
|
|||||||
function on macOS 10.12+
|
function on macOS 10.12+
|
||||||
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
||||||
- [Cocoa] Bugfix: Windows created after the first were not cascaded (#195)
|
- [Cocoa] Bugfix: Windows created after the first were not cascaded (#195)
|
||||||
|
- [Cocoa] Bugfix: Leaving video mode with `glfwSetWindowMonitor` would set
|
||||||
|
incorrect position and size (#748)
|
||||||
|
- [Cocoa] Bugfix: Iconified full screen windows could not be restored (#848)
|
||||||
|
- [Cocoa] Bugfix: Value range was ignored for joystick hats and buttons (#888)
|
||||||
|
- [Cocoa] Bugfix: Full screen framebuffer was incorrectly sized for some video
|
||||||
|
modes (#682)
|
||||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||||
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
- [EGL] Added support for `EGL_KHR_get_all_proc_addresses` (#871)
|
||||||
|
- [EGL] Added support for `EGL_KHR_context_flush_control`
|
||||||
- [EGL] Bugfix: The test for `EGL_RGB_BUFFER` was invalid
|
- [EGL] Bugfix: The test for `EGL_RGB_BUFFER` was invalid
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -204,7 +204,8 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
|||||||
"x11=__X11:__" \
|
"x11=__X11:__" \
|
||||||
"wayland=__Wayland:__" \
|
"wayland=__Wayland:__" \
|
||||||
"win32=__Windows:__" \
|
"win32=__Windows:__" \
|
||||||
"macos=__macOS:__"
|
"macos=__macOS:__" \
|
||||||
|
"linux=__Linux:__"
|
||||||
|
|
||||||
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
# This tag can be used to specify a number of word-keyword mappings (TCL only).
|
||||||
# A mapping has the form "name=value". For example adding
|
# A mapping has the form "name=value". For example adding
|
||||||
|
|||||||
@ -510,21 +510,24 @@ A simple mouse wheel, being vertical, provides offsets along the Y-axis.
|
|||||||
|
|
||||||
The joystick functions expose connected joysticks and controllers, with both
|
The joystick functions expose connected joysticks and controllers, with both
|
||||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
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
|
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||||
|
present with @ref glfwJoystickPresent.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
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
|
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
disconnected or the library is terminated, so as joysticks are connected and
|
||||||
and disconnected, they will become spread out.
|
disconnected, there may appear gaps in the IDs.
|
||||||
|
|
||||||
Joystick state is updated as needed when a joystick function is called and does
|
Joystick axis, button and hat state is updated when polled and does not require
|
||||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
a window to be created or events to be processed. However, if you want joystick
|
||||||
to be called.
|
connection and disconnection events reliably delivered to the
|
||||||
|
[joystick callback](@ref joystick_event) then you must
|
||||||
|
[process events](@ref events).
|
||||||
|
|
||||||
To see all the properties of all connected joysticks in real-time, run the
|
To see all the properties of all connected joysticks in real-time, run the
|
||||||
`joysticks` test program.
|
`joysticks` test program.
|
||||||
@ -538,7 +541,7 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is a value between -1.0 and 1.0.
|
Each element in the returned array is a value between -1.0 and 1.0.
|
||||||
@ -552,11 +555,55 @@ returned array.
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
int count;
|
int count;
|
||||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
Each element in the returned array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
@subsection joystick_hat Joystick hat states
|
||||||
|
|
||||||
|
The states of all hats are returned by @ref glfwGetJoystickHats. See the
|
||||||
|
reference documentation for the lifetime of the returned array.
|
||||||
|
|
||||||
|
@code
|
||||||
|
int count;
|
||||||
|
const unsigned char* hats = glfwGetJoystickHats(GLFW_JOYSTICK_7, &count);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
Each element in the returned array is one of the following:
|
||||||
|
|
||||||
|
Name | Value
|
||||||
|
--------------------- | --------------------------------
|
||||||
|
`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.
|
||||||
|
|
||||||
|
@code
|
||||||
|
if (hats[2] & GLFW_HAT_RIGHT)
|
||||||
|
{
|
||||||
|
// State of hat 2 could be right-up, right or right-down
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
@subsection joystick_name Joystick name
|
@subsection joystick_name Joystick name
|
||||||
|
|
||||||
@ -565,7 +612,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
|||||||
returned string.
|
returned string.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
||||||
|
|||||||
@ -77,6 +77,11 @@ platform but they will only affect their specific platform. Other platforms
|
|||||||
will simply ignore them. Setting these hints requires no platform specific
|
will simply ignore them. Setting these hints requires no platform specific
|
||||||
headers or calls.
|
headers or calls.
|
||||||
|
|
||||||
|
@anchor GLFW_JOYSTICK_HAT_BUTTONS
|
||||||
|
__GLFW_JOYSTICK_HAT_BUTTONS__ specifies whether to also expose joystick hats as
|
||||||
|
buttons, for compatibility with earlier versions of GLFW that did not have @ref
|
||||||
|
glfwGetJoystickHats.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection init_hints_osx macOS specific hints
|
@subsubsection init_hints_osx macOS specific hints
|
||||||
|
|
||||||
@ -95,6 +100,7 @@ initialized.
|
|||||||
|
|
||||||
Init hint | Default value | Supported values
|
Init hint | Default value | Supported values
|
||||||
------------------------------- | ------------- | ----------------
|
------------------------------- | ------------- | ----------------
|
||||||
|
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,13 @@ GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
|||||||
windows with @ref glfwSetWindowAttrib.
|
windows with @ref glfwSetWindowAttrib.
|
||||||
|
|
||||||
|
|
||||||
|
@subsection news_33_joyhats Support for joystick hats
|
||||||
|
|
||||||
|
GLFW now supports querying the hats of a joystick with @ref glfwGetJoystickHats
|
||||||
|
and controlling whether hats are also exposed as buttons with the @ref
|
||||||
|
GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||||
|
|
||||||
|
|
||||||
@subsection news_33_inithint Support for initialization hints
|
@subsection news_33_inithint Support for initialization hints
|
||||||
|
|
||||||
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
GLFW now supports setting library initialization hints with @ref glfwInitHint.
|
||||||
|
|||||||
@ -297,6 +297,23 @@ extern "C" {
|
|||||||
#define GLFW_REPEAT 2
|
#define GLFW_REPEAT 2
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
/*! @defgroup hat_state Joystick hat states
|
||||||
|
*
|
||||||
|
* See [joystick hat input](@ref joystick_hat) for how these are used.
|
||||||
|
*
|
||||||
|
* @ingroup input
|
||||||
|
* @{ */
|
||||||
|
#define GLFW_HAT_CENTERED 0
|
||||||
|
#define GLFW_HAT_UP 1
|
||||||
|
#define GLFW_HAT_RIGHT 2
|
||||||
|
#define GLFW_HAT_DOWN 4
|
||||||
|
#define GLFW_HAT_LEFT 8
|
||||||
|
#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP)
|
||||||
|
#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
|
||||||
|
#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP)
|
||||||
|
#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN)
|
||||||
|
/*! @} */
|
||||||
|
|
||||||
/*! @defgroup keys Keyboard keys
|
/*! @defgroup keys Keyboard keys
|
||||||
* @brief Keyboard key IDs.
|
* @brief Keyboard key IDs.
|
||||||
*
|
*
|
||||||
@ -928,6 +945,8 @@ extern "C" {
|
|||||||
|
|
||||||
/*! @addtogroup init
|
/*! @addtogroup init
|
||||||
* @{ */
|
* @{ */
|
||||||
|
#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001
|
||||||
|
|
||||||
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
|
#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001
|
||||||
#define GLFW_COCOA_MENUBAR 0x00051002
|
#define GLFW_COCOA_MENUBAR 0x00051002
|
||||||
/*! @} */
|
/*! @} */
|
||||||
@ -4003,7 +4022,7 @@ GLFWAPI int glfwJoystickPresent(int jid);
|
|||||||
* This function returns the values of all axes of the specified joystick.
|
* This function returns the values of all axes of the specified joystick.
|
||||||
* Each element in the array is a value between -1.0 and 1.0.
|
* Each element in the array is a value between -1.0 and 1.0.
|
||||||
*
|
*
|
||||||
* Querying a joystick slot with no device present is not an error, but will
|
* Querying a joystick ID with no device present is not an error, but will
|
||||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* check device presence.
|
||||||
*
|
*
|
||||||
@ -4036,7 +4055,14 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
|
|||||||
* This function returns the state of all buttons of the specified joystick.
|
* This function returns the state of all buttons of the specified joystick.
|
||||||
* Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
* Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||||
*
|
*
|
||||||
* Querying a joystick slot with no device present is not an error, but will
|
* For backward compatibility with earlier versions that did not have @ref
|
||||||
|
* glfwGetJoystickHats, the button array also includes all hats, each
|
||||||
|
* represented as four buttons. The hats are in the same order as returned by
|
||||||
|
* __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
|
||||||
|
* _left_. To disable these extra buttons, set the @ref
|
||||||
|
* GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
|
||||||
|
*
|
||||||
|
* Querying a joystick ID with no device present is not an error, but will
|
||||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* check device presence.
|
||||||
*
|
*
|
||||||
@ -4065,13 +4091,72 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count);
|
||||||
|
|
||||||
|
/*! @brief Returns the state of all hats of the specified joystick.
|
||||||
|
*
|
||||||
|
* This function returns the state of all hats of the specified joystick.
|
||||||
|
* Each element in the array is one of the following values:
|
||||||
|
*
|
||||||
|
* Name | Value
|
||||||
|
* --------------------- | --------------------------------
|
||||||
|
* `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.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* if (hats[2] & GLFW_HAT_RIGHT)
|
||||||
|
* {
|
||||||
|
* // State of hat 2 could be right-up, right or right-down
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Querying a joystick ID with no device present is not an error, but will
|
||||||
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
|
* check device presence.
|
||||||
|
*
|
||||||
|
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||||
|
* @param[out] count Where to store the number of hat states in the returned
|
||||||
|
* array. This is set to zero if the joystick is not present or an error
|
||||||
|
* occurred.
|
||||||
|
* @return An array of hat states, or `NULL` if the joystick is not present
|
||||||
|
* or an [error](@ref error_handling) occurred.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
|
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @bug @linux Joystick hats are currently unimplemented.
|
||||||
|
*
|
||||||
|
* @pointer_lifetime The returned array is allocated and freed by GLFW. You
|
||||||
|
* should not free it yourself. It is valid until the specified joystick is
|
||||||
|
* disconnected, this function is called again for that joystick or the library
|
||||||
|
* is terminated.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref joystick_hat
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup input
|
||||||
|
*/
|
||||||
|
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
|
||||||
|
|
||||||
/*! @brief Returns the name of the specified joystick.
|
/*! @brief Returns the name of the specified joystick.
|
||||||
*
|
*
|
||||||
* This function returns the name, encoded as UTF-8, of the specified joystick.
|
* This function returns the name, encoded as UTF-8, of the specified joystick.
|
||||||
* The returned string is allocated and freed by GLFW. You should not free it
|
* The returned string is allocated and freed by GLFW. You should not free it
|
||||||
* yourself.
|
* yourself.
|
||||||
*
|
*
|
||||||
* Querying a joystick slot with no device present is not an error, but will
|
* Querying a joystick ID with no device present is not an error, but will
|
||||||
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
* cause this function to return `NULL`. Call @ref glfwJoystickPresent to
|
||||||
* check device presence.
|
* check device presence.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -464,7 +464,7 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
|||||||
* @param[out] buffer Where to store the address of the color buffer, or
|
* @param[out] buffer Where to store the address of the color buffer, or
|
||||||
* `NULL`.
|
* `NULL`.
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||||
* [error](@ref error_handling) occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
* synchronized.
|
* synchronized.
|
||||||
@ -485,7 +485,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height
|
|||||||
* @param[out] buffer Where to store the address of the depth buffer, or
|
* @param[out] buffer Where to store the address of the depth buffer, or
|
||||||
* `NULL`.
|
* `NULL`.
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||||
* [error](@ref error_handling) occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @thread_safety This function may be called from any thread. Access is not
|
* @thread_safety This function may be called from any thread. Access is not
|
||||||
* synchronized.
|
* synchronized.
|
||||||
|
|||||||
@ -33,10 +33,11 @@ elseif (_GLFW_X11)
|
|||||||
endif()
|
endif()
|
||||||
elseif (_GLFW_WAYLAND)
|
elseif (_GLFW_WAYLAND)
|
||||||
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
|
set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
|
||||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
|
posix_time.h posix_tls.h xkb_unicode.h egl_context.h
|
||||||
|
osmesa_context.h)
|
||||||
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
|
||||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||||
egl_context.c)
|
egl_context.c osmesa_context.c)
|
||||||
|
|
||||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||||
PROTOCOL
|
PROTOCOL
|
||||||
@ -48,10 +49,11 @@ elseif (_GLFW_WAYLAND)
|
|||||||
BASENAME pointer-constraints-unstable-v1)
|
BASENAME pointer-constraints-unstable-v1)
|
||||||
elseif (_GLFW_MIR)
|
elseif (_GLFW_MIR)
|
||||||
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
|
||||||
posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
|
posix_time.h posix_tls.h xkb_unicode.h egl_context.h
|
||||||
|
osmesa_context.h)
|
||||||
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
|
||||||
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
|
||||||
egl_context.c)
|
egl_context.c osmesa_context.c)
|
||||||
elseif (_GLFW_OSMESA)
|
elseif (_GLFW_OSMESA)
|
||||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||||
posix_time.h posix_tls.h osmesa_context.h)
|
posix_time.h posix_tls.h osmesa_context.h)
|
||||||
|
|||||||
@ -311,9 +311,6 @@ int _glfwPlatformInit(void)
|
|||||||
if (!initializeTIS())
|
if (!initializeTIS())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerNS();
|
_glfwInitTimerNS();
|
||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
@ -362,7 +359,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
_glfwTerminateJoysticksNS();
|
_glfwTerminateJoysticksNS();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
|
|
||||||
[_glfw.ns.autoreleasePool release];
|
[_glfw.ns.autoreleasePool release];
|
||||||
_glfw.ns.autoreleasePool = nil;
|
_glfw.ns.autoreleasePool = nil;
|
||||||
|
|||||||
@ -53,29 +53,19 @@ typedef struct _GLFWjoyelementNS
|
|||||||
//
|
//
|
||||||
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||||
{
|
{
|
||||||
IOReturn result = kIOReturnSuccess;
|
|
||||||
IOHIDValueRef valueRef;
|
IOHIDValueRef valueRef;
|
||||||
long value = 0;
|
long value = 0;
|
||||||
|
|
||||||
if (js && element && js->ns.device)
|
if (js->ns.device)
|
||||||
{
|
{
|
||||||
result = IOHIDDeviceGetValue(js->ns.device,
|
if (IOHIDDeviceGetValue(js->ns.device,
|
||||||
element->native,
|
element->native,
|
||||||
&valueRef);
|
&valueRef) == kIOReturnSuccess)
|
||||||
|
|
||||||
if (kIOReturnSuccess == result)
|
|
||||||
{
|
{
|
||||||
value = IOHIDValueGetIntegerValue(valueRef);
|
value = IOHIDValueGetIntegerValue(valueRef);
|
||||||
|
|
||||||
// Record min and max for auto calibration
|
|
||||||
if (value < element->minimum)
|
|
||||||
element->minimum = value;
|
|
||||||
if (value > element->maximum)
|
|
||||||
element->maximum = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto user scale
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +194,8 @@ static void matchCallback(void* context,
|
|||||||
|
|
||||||
js = _glfwAllocJoystick(name,
|
js = _glfwAllocJoystick(name,
|
||||||
CFArrayGetCount(axes),
|
CFArrayGetCount(axes),
|
||||||
CFArrayGetCount(buttons) + CFArrayGetCount(hats) * 4);
|
CFArrayGetCount(buttons),
|
||||||
|
CFArrayGetCount(hats));
|
||||||
|
|
||||||
js->ns.device = device;
|
js->ns.device = device;
|
||||||
js->ns.axes = axes;
|
js->ns.axes = axes;
|
||||||
@ -347,44 +338,57 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.axes, i);
|
CFArrayGetValueAtIndex(js->ns.axes, i);
|
||||||
|
|
||||||
const long value = getElementValue(js, axis);
|
const long raw = getElementValue(js, axis);
|
||||||
const long delta = axis->maximum - axis->minimum;
|
// Perform auto calibration
|
||||||
|
if (raw < axis->minimum)
|
||||||
|
axis->minimum = raw;
|
||||||
|
if (raw > axis->maximum)
|
||||||
|
axis->maximum = raw;
|
||||||
|
|
||||||
|
const long delta = axis->maximum - axis->minimum;
|
||||||
if (delta == 0)
|
if (delta == 0)
|
||||||
_glfwInputJoystickAxis(jid, i, value);
|
_glfwInputJoystickAxis(jid, i, 0.f);
|
||||||
else
|
else
|
||||||
_glfwInputJoystickAxis(jid, i, (2.f * (value - axis->minimum) / delta) - 1.f);
|
{
|
||||||
|
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
|
||||||
|
_glfwInputJoystickAxis(jid, i, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode == _GLFW_POLL_BUTTONS)
|
else if (mode == _GLFW_POLL_BUTTONS)
|
||||||
{
|
{
|
||||||
CFIndex i, bi = 0;
|
CFIndex i;
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||||
{
|
{
|
||||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||||
const char value = getElementValue(js, button) ? 1 : 0;
|
const char value = getElementValue(js, button) - button->minimum;
|
||||||
_glfwInputJoystickButton(jid, bi++, value);
|
_glfwInputJoystickButton(jid, i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
{
|
{
|
||||||
|
const int states[9] =
|
||||||
|
{
|
||||||
|
GLFW_HAT_UP,
|
||||||
|
GLFW_HAT_RIGHT_UP,
|
||||||
|
GLFW_HAT_RIGHT,
|
||||||
|
GLFW_HAT_RIGHT_DOWN,
|
||||||
|
GLFW_HAT_DOWN,
|
||||||
|
GLFW_HAT_LEFT_DOWN,
|
||||||
|
GLFW_HAT_LEFT,
|
||||||
|
GLFW_HAT_LEFT_UP,
|
||||||
|
GLFW_HAT_CENTERED
|
||||||
|
};
|
||||||
|
|
||||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.hats, i);
|
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||||
|
long state = getElementValue(js, hat) - hat->minimum;
|
||||||
// Bit fields of button presses for each direction, including nil
|
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
|
||||||
|
|
||||||
long j, state = getElementValue(js, hat);
|
|
||||||
if (state < 0 || state > 8)
|
if (state < 0 || state > 8)
|
||||||
state = 8;
|
state = 8;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
_glfwInputJoystickHat(jid, i, states[state]);
|
||||||
{
|
|
||||||
const char value = directions[state] & (1 << j) ? 1 : 0;
|
|
||||||
_glfwInputJoystickButton(jid, bi++, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -48,9 +48,8 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
IOServiceMatching("IODisplayConnect"),
|
IOServiceMatching("IODisplayConnect"),
|
||||||
&it) != 0)
|
&it) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
// This may happen if a desktop Mac is running headless
|
||||||
"Cocoa: Failed to get display service port iterator");
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((service = IOIteratorNext(it)) != 0)
|
while ((service = IOIteratorNext(it)) != 0)
|
||||||
@ -99,8 +98,6 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
(const void**) &nameRef))
|
(const void**) &nameRef))
|
||||||
{
|
{
|
||||||
// This may happen if a desktop Mac is running headless
|
// This may happen if a desktop Mac is running headless
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Cocoa: Failed to retrieve display name");
|
|
||||||
CFRelease(info);
|
CFRelease(info);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacO
|
|||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerNS ns
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
|
||||||
|
|
||||||
@ -151,11 +151,11 @@ typedef struct _GLFWcursorNS
|
|||||||
|
|
||||||
// Cocoa-specific global timer data
|
// Cocoa-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimeNS
|
typedef struct _GLFWtimerNS
|
||||||
{
|
{
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimeNS;
|
} _GLFWtimerNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerNS(void);
|
void _glfwInitTimerNS(void);
|
||||||
|
|||||||
@ -40,7 +40,7 @@ void _glfwInitTimerNS(void)
|
|||||||
mach_timebase_info_data_t info;
|
mach_timebase_info_data_t info;
|
||||||
mach_timebase_info(&info);
|
mach_timebase_info(&info);
|
||||||
|
|
||||||
_glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
|
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +55,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
return _glfw.ns_time.frequency;
|
return _glfw.timer.ns.frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -777,6 +777,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canBecomeMainWindow
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@ -1025,7 +1030,12 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
_glfw.ns.cascadePoint = [window->ns.object cascadeTopLeftFromPoint:_glfw.ns.cascadePoint];
|
_glfw.ns.cascadePoint = [window->ns.object cascadeTopLeftFromPoint:_glfw.ns.cascadePoint];
|
||||||
|
|
||||||
if (wndconfig->resizable)
|
if (wndconfig->resizable)
|
||||||
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
{
|
||||||
|
const NSWindowCollectionBehavior behavior =
|
||||||
|
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||||
|
NSWindowCollectionBehaviorManaged;
|
||||||
|
[window->ns.object setCollectionBehavior:behavior];
|
||||||
|
}
|
||||||
|
|
||||||
if (wndconfig->floating)
|
if (wndconfig->floating)
|
||||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||||
@ -1310,6 +1320,10 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
_glfwInputWindowMonitorChange(window, monitor);
|
_glfwInputWindowMonitorChange(window, monitor);
|
||||||
|
|
||||||
|
// HACK: Allow the state cached in Cocoa to catch up to reality
|
||||||
|
// TODO: Solve this in a less terrible way
|
||||||
|
_glfwPlatformPollEvents();
|
||||||
|
|
||||||
const NSUInteger styleMask = getStyleMask(window);
|
const NSUInteger styleMask = getStyleMask(window);
|
||||||
[window->ns.object setStyleMask:styleMask];
|
[window->ns.object setStyleMask:styleMask];
|
||||||
[window->ns.object makeFirstResponder:window->ns.view];
|
[window->ns.object makeFirstResponder:window->ns.view];
|
||||||
|
|||||||
@ -331,7 +331,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
window->context.source = ctxconfig->source;
|
window->context.source = ctxconfig->source;
|
||||||
window->context.client = GLFW_OPENGL_API;
|
window->context.client = GLFW_OPENGL_API;
|
||||||
@ -578,7 +578,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
|||||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
@ -601,7 +601,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
|||||||
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return (GLFWwindow*) _glfwPlatformGetCurrentContext();
|
return _glfwPlatformGetTls(&_glfw.context);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
||||||
@ -626,7 +626,7 @@ GLFWAPI void glfwSwapInterval(int interval)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
@ -643,7 +643,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
@ -708,7 +708,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
window = _glfwPlatformGetCurrentContext();
|
window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||||
|
|||||||
@ -199,12 +199,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.context, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersEGL(_GLFWwindow* window)
|
static void swapBuffersEGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window != _glfwPlatformGetCurrentContext())
|
if (window != _glfwPlatformGetTls(&_glfw.context))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||||
@ -233,7 +233,7 @@ static int extensionSupportedEGL(const char* extension)
|
|||||||
|
|
||||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
if (window->context.egl.client)
|
if (window->context.egl.client)
|
||||||
{
|
{
|
||||||
@ -291,6 +291,8 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
"EGL.dll",
|
"EGL.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libEGL.dylib",
|
"libEGL.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libEGL-1.so",
|
||||||
#else
|
#else
|
||||||
"libEGL.so.1",
|
"libEGL.so.1",
|
||||||
#endif
|
#endif
|
||||||
@ -401,6 +403,8 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
||||||
_glfw.egl.KHR_get_all_proc_addresses =
|
_glfw.egl.KHR_get_all_proc_addresses =
|
||||||
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
|
||||||
|
_glfw.egl.KHR_context_flush_control =
|
||||||
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -438,6 +442,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
EGLint attribs[40];
|
EGLint attribs[40];
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLContext share = NULL;
|
EGLContext share = NULL;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
if (!_glfw.egl.display)
|
if (!_glfw.egl.display)
|
||||||
{
|
{
|
||||||
@ -478,7 +483,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (_glfw.egl.KHR_create_context)
|
if (_glfw.egl.KHR_create_context)
|
||||||
{
|
{
|
||||||
int index = 0, mask = 0, flags = 0;
|
int mask = 0, flags = 0;
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
@ -527,21 +532,28 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (flags)
|
if (flags)
|
||||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||||
|
|
||||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
if (_glfw.egl.KHR_context_flush_control)
|
||||||
// supported on EGL but are not a hard constraint, so ignore and continue
|
{
|
||||||
|
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||||
|
}
|
||||||
|
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||||
|
{
|
||||||
|
setEGLattrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||||
|
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||||
|
|
||||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||||
config, share, attribs);
|
config, share, attribs);
|
||||||
@ -609,6 +621,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
"libGLESv2.dll",
|
"libGLESv2.dll",
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
"libGLESv2.dylib",
|
"libGLESv2.dylib",
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
"libGLESv2-2.so",
|
||||||
#else
|
#else
|
||||||
"libGLESv2.so.2",
|
"libGLESv2.so.2",
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -110,6 +110,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
|||||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
||||||
#define EGL_GL_COLORSPACE_KHR 0x309d
|
#define EGL_GL_COLORSPACE_KHR 0x309d
|
||||||
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
|
||||||
|
#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
|
||||||
|
|
||||||
typedef int EGLint;
|
typedef int EGLint;
|
||||||
typedef unsigned int EGLBoolean;
|
typedef unsigned int EGLBoolean;
|
||||||
@ -181,6 +184,7 @@ typedef struct _GLFWlibraryEGL
|
|||||||
GLFWbool KHR_create_context_no_error;
|
GLFWbool KHR_create_context_no_error;
|
||||||
GLFWbool KHR_gl_colorspace;
|
GLFWbool KHR_gl_colorspace;
|
||||||
GLFWbool KHR_get_all_proc_addresses;
|
GLFWbool KHR_get_all_proc_addresses;
|
||||||
|
GLFWbool KHR_context_flush_control;
|
||||||
|
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
|
|||||||
@ -165,7 +165,7 @@ static void makeContextCurrentGLX(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.context, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersGLX(_GLFWwindow* window)
|
static void swapBuffersGLX(_GLFWwindow* window)
|
||||||
@ -175,7 +175,7 @@ static void swapBuffersGLX(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalGLX(int interval)
|
static void swapIntervalGLX(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
if (_glfw.glx.EXT_swap_control)
|
if (_glfw.glx.EXT_swap_control)
|
||||||
{
|
{
|
||||||
|
|||||||
11
src/init.c
11
src/init.c
@ -46,6 +46,7 @@ _GLFWlibrary _glfw = { GLFW_FALSE };
|
|||||||
static GLFWerrorfun _glfwErrorCallback;
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
static _GLFWinitconfig _glfwInitHints =
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
{
|
{
|
||||||
|
GLFW_TRUE, // hat buttons
|
||||||
{
|
{
|
||||||
GLFW_TRUE, // menubar
|
GLFW_TRUE, // menubar
|
||||||
GLFW_TRUE // chdir
|
GLFW_TRUE // chdir
|
||||||
@ -112,6 +113,8 @@ static void terminate(void)
|
|||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
_glfwPlatformTerminate();
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
|
_glfwPlatformDestroyTls(&_glfw.context);
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,6 +164,9 @@ GLFWAPI int glfwInit(void)
|
|||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
_glfw.hints.init = _glfwInitHints;
|
_glfw.hints.init = _glfwInitHints;
|
||||||
|
|
||||||
|
if (!_glfwPlatformCreateTls(&_glfw.context))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
if (!_glfwPlatformInit())
|
if (!_glfwPlatformInit())
|
||||||
{
|
{
|
||||||
terminate();
|
terminate();
|
||||||
@ -168,7 +174,7 @@ GLFWAPI int glfwInit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfw.initialized = GLFW_TRUE;
|
_glfw.initialized = GLFW_TRUE;
|
||||||
_glfw.timerOffset = _glfwPlatformGetTimerValue();
|
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
// Not all window hints have zero as their default value
|
// Not all window hints have zero as their default value
|
||||||
glfwDefaultWindowHints();
|
glfwDefaultWindowHints();
|
||||||
@ -188,6 +194,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
|
|||||||
{
|
{
|
||||||
switch (hint)
|
switch (hint)
|
||||||
{
|
{
|
||||||
|
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||||
|
_glfwInitHints.hatButtons = value;
|
||||||
|
return;
|
||||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||||
_glfwInitHints.ns.chdir = value;
|
_glfwInitHints.ns.chdir = value;
|
||||||
return;
|
return;
|
||||||
|
|||||||
62
src/input.c
62
src/input.c
@ -140,6 +140,19 @@ void _glfwInputJoystickButton(int jid, int button, char value)
|
|||||||
_glfw.joysticks[jid].buttons[button] = value;
|
_glfw.joysticks[jid].buttons[button] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwInputJoystickHat(int jid, int hat, char value)
|
||||||
|
{
|
||||||
|
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||||
|
const int base = js->buttonCount + hat * 4;
|
||||||
|
|
||||||
|
js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
|
||||||
|
js->hats[hat] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
@ -152,7 +165,10 @@ GLFWbool _glfwIsPrintable(int key)
|
|||||||
key == GLFW_KEY_KP_EQUAL;
|
key == GLFW_KEY_KP_EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount)
|
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||||
|
int axisCount,
|
||||||
|
int buttonCount,
|
||||||
|
int hatCount)
|
||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
_GLFWjoystick* js;
|
_GLFWjoystick* js;
|
||||||
@ -170,9 +186,11 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCou
|
|||||||
js->present = GLFW_TRUE;
|
js->present = GLFW_TRUE;
|
||||||
js->name = strdup(name);
|
js->name = strdup(name);
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
js->axes = calloc(axisCount, sizeof(float));
|
||||||
js->buttons = calloc(buttonCount, 1);
|
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||||
|
js->hats = calloc(hatCount, 1);
|
||||||
js->axisCount = axisCount;
|
js->axisCount = axisCount;
|
||||||
js->buttonCount = buttonCount;
|
js->buttonCount = buttonCount;
|
||||||
|
js->hatCount = hatCount;
|
||||||
|
|
||||||
return js;
|
return js;
|
||||||
}
|
}
|
||||||
@ -182,6 +200,7 @@ void _glfwFreeJoystick(_GLFWjoystick* js)
|
|||||||
free(js->name);
|
free(js->name);
|
||||||
free(js->axes);
|
free(js->axes);
|
||||||
free(js->buttons);
|
free(js->buttons);
|
||||||
|
free(js->hats);
|
||||||
memset(js, 0, sizeof(_GLFWjoystick));
|
memset(js, 0, sizeof(_GLFWjoystick));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,10 +682,43 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
|||||||
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
*count = _glfw.joysticks[jid].buttonCount;
|
if (_glfw.hints.init.hatButtons)
|
||||||
|
{
|
||||||
|
*count = _glfw.joysticks[jid].buttonCount +
|
||||||
|
_glfw.joysticks[jid].hatCount * 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*count = _glfw.joysticks[jid].buttonCount;
|
||||||
|
|
||||||
return _glfw.joysticks[jid].buttons;
|
return _glfw.joysticks[jid].buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||||
|
{
|
||||||
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", jid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_glfw.joysticks[jid].present)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!_glfwPlatformPollJoystick(jid, _GLFW_POLL_BUTTONS))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*count = _glfw.joysticks[jid].hatCount;
|
||||||
|
return _glfw.joysticks[jid].hats;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||||
{
|
{
|
||||||
assert(jid >= GLFW_JOYSTICK_1);
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
@ -718,7 +770,7 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
|||||||
GLFWAPI double glfwGetTime(void)
|
GLFWAPI double glfwGetTime(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
|
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
|
||||||
_glfwPlatformGetTimerFrequency();
|
_glfwPlatformGetTimerFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -732,7 +784,7 @@ GLFWAPI void glfwSetTime(double time)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.timerOffset = _glfwPlatformGetTimerValue() -
|
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
|
||||||
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,7 @@ typedef struct _GLFWlibrary _GLFWlibrary;
|
|||||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||||
typedef struct _GLFWcursor _GLFWcursor;
|
typedef struct _GLFWcursor _GLFWcursor;
|
||||||
typedef struct _GLFWjoystick _GLFWjoystick;
|
typedef struct _GLFWjoystick _GLFWjoystick;
|
||||||
|
typedef struct _GLFWtls _GLFWtls;
|
||||||
|
|
||||||
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
||||||
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
||||||
@ -266,6 +267,7 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
*/
|
*/
|
||||||
struct _GLFWinitconfig
|
struct _GLFWinitconfig
|
||||||
{
|
{
|
||||||
|
GLFWbool hatButtons;
|
||||||
struct {
|
struct {
|
||||||
GLFWbool menubar;
|
GLFWbool menubar;
|
||||||
GLFWbool chdir;
|
GLFWbool chdir;
|
||||||
@ -476,12 +478,22 @@ struct _GLFWjoystick
|
|||||||
int axisCount;
|
int axisCount;
|
||||||
unsigned char* buttons;
|
unsigned char* buttons;
|
||||||
int buttonCount;
|
int buttonCount;
|
||||||
|
unsigned char* hats;
|
||||||
|
int hatCount;
|
||||||
char* name;
|
char* name;
|
||||||
|
|
||||||
// This is defined in the joystick API's joystick.h
|
// This is defined in the joystick API's joystick.h
|
||||||
_GLFW_PLATFORM_JOYSTICK_STATE;
|
_GLFW_PLATFORM_JOYSTICK_STATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! @brief Thread local storage structure.
|
||||||
|
*/
|
||||||
|
struct _GLFWtls
|
||||||
|
{
|
||||||
|
// This is defined in the platform's tls.h
|
||||||
|
_GLFW_PLATFORM_TLS_STATE;
|
||||||
|
};
|
||||||
|
|
||||||
/*! @brief Library global data.
|
/*! @brief Library global data.
|
||||||
*/
|
*/
|
||||||
struct _GLFWlibrary
|
struct _GLFWlibrary
|
||||||
@ -505,7 +517,13 @@ struct _GLFWlibrary
|
|||||||
|
|
||||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||||
|
|
||||||
uint64_t timerOffset;
|
_GLFWtls context;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint64_t offset;
|
||||||
|
// This is defined in the platform's time.h
|
||||||
|
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
|
||||||
|
} timer;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
GLFWbool available;
|
||||||
@ -539,12 +557,8 @@ struct _GLFWlibrary
|
|||||||
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
||||||
// This is defined in the context API's context.h
|
// This is defined in the context API's context.h
|
||||||
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
|
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
|
||||||
// This is defined in the platform's time.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_TIME_STATE;
|
|
||||||
// This is defined in the platform's joystick.h
|
// This is defined in the platform's joystick.h
|
||||||
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
||||||
// This is defined in the platform's tls.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_TLS_STATE;
|
|
||||||
// This is defined in egl_context.h
|
// This is defined in egl_context.h
|
||||||
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
||||||
// This is defined in osmesa_context.h
|
// This is defined in osmesa_context.h
|
||||||
@ -631,13 +645,15 @@ void _glfwPlatformWaitEvents(void);
|
|||||||
void _glfwPlatformWaitEventsTimeout(double timeout);
|
void _glfwPlatformWaitEventsTimeout(double timeout);
|
||||||
void _glfwPlatformPostEmptyEvent(void);
|
void _glfwPlatformPostEmptyEvent(void);
|
||||||
|
|
||||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
|
|
||||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void);
|
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
||||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
|
||||||
|
|
||||||
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||||
|
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
|
|
||||||
@ -823,6 +839,13 @@ void _glfwInputJoystickAxis(int jid, int axis, float value);
|
|||||||
*/
|
*/
|
||||||
void _glfwInputJoystickButton(int jid, int button, char value);
|
void _glfwInputJoystickButton(int jid, int button, char value);
|
||||||
|
|
||||||
|
/*! @brief Notifies shared code of the new value of a joystick hat.
|
||||||
|
* @param[in] jid The joystick whose hat to update.
|
||||||
|
* @param[in] button The index of the hat to update.
|
||||||
|
* @param[in] value The new value of the hat.
|
||||||
|
*/
|
||||||
|
void _glfwInputJoystickHat(int jid, int hat, char value);
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Utility functions
|
// Utility functions
|
||||||
@ -912,7 +935,7 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
|||||||
/*! @brief Returns an available joystick object with arrays and name allocated.
|
/*! @brief Returns an available joystick object with arrays and name allocated.
|
||||||
* @ingroup utility
|
* @ingroup utility
|
||||||
*/
|
*/
|
||||||
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount);
|
_GLFWjoystick* _glfwAllocJoystick(const char* name, int axisCount, int buttonCount, int hatCount);
|
||||||
|
|
||||||
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
||||||
* @ingroup utility
|
* @ingroup utility
|
||||||
|
|||||||
@ -77,7 +77,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||||
|
|
||||||
js = _glfwAllocJoystick(name, axisCount, buttonCount);
|
js = _glfwAllocJoystick(name, axisCount, buttonCount, 0);
|
||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|||||||
@ -190,9 +190,6 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
createKeyTables();
|
createKeyTables();
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@ -218,7 +215,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
{
|
{
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
|
|
||||||
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
||||||
|
|
||||||
|
|||||||
@ -401,10 +401,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitEGL())
|
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||||
return GLFW_FALSE;
|
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
{
|
||||||
return GLFW_FALSE;
|
if (!_glfwInitEGL())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
|
{
|
||||||
|
if (!_glfwInitOSMesa())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ static void makeContextCurrentNSGL(_GLFWwindow* window)
|
|||||||
else
|
else
|
||||||
[NSOpenGLContext clearCurrentContext];
|
[NSOpenGLContext clearCurrentContext];
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.context, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||||
@ -45,7 +45,7 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalNSGL(int interval)
|
static void swapIntervalNSGL(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
GLint sync = interval;
|
GLint sync = interval;
|
||||||
[window->context.nsgl.object setValues:&sync
|
[window->context.nsgl.object setValues:&sync
|
||||||
|
|||||||
@ -34,9 +34,6 @@
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
@ -44,7 +41,6 @@ int _glfwPlatformInit(void)
|
|||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
_glfwTerminateOSMesa();
|
_glfwTerminateOSMesa();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
|||||||
@ -63,7 +63,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.context, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||||
|
|||||||
@ -44,14 +44,14 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
{
|
{
|
||||||
_glfw.posix_time.monotonic = GLFW_TRUE;
|
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||||
_glfw.posix_time.frequency = 1000000000;
|
_glfw.timer.posix.frequency = 1000000000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
_glfw.posix_time.monotonic = GLFW_FALSE;
|
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||||
_glfw.posix_time.frequency = 1000000;
|
_glfw.timer.posix.frequency = 1000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
{
|
{
|
||||||
#if defined(CLOCK_MONOTONIC)
|
#if defined(CLOCK_MONOTONIC)
|
||||||
if (_glfw.posix_time.monotonic)
|
if (_glfw.timer.posix.monotonic)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
@ -80,6 +80,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
return _glfw.posix_time.frequency;
|
return _glfw.timer.posix.frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,19 +28,19 @@
|
|||||||
#ifndef _glfw3_posix_time_h_
|
#ifndef _glfw3_posix_time_h_
|
||||||
#define _glfw3_posix_time_h_
|
#define _glfw3_posix_time_h_
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
// POSIX-specific global timer data
|
// POSIX-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimePOSIX
|
typedef struct _GLFWtimerPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool monotonic;
|
GLFWbool monotonic;
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimePOSIX;
|
} _GLFWtimerPOSIX;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerPOSIX(void);
|
void _glfwInitTimerPOSIX(void);
|
||||||
|
|||||||
@ -27,42 +27,46 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
//////////////////////////////////////////////////////////////////////////
|
#include <string.h>
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void)
|
|
||||||
{
|
|
||||||
if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"POSIX: Failed to create context TLS");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.posix_tls.allocated = GLFW_TRUE;
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwTerminateThreadLocalStoragePOSIX(void)
|
|
||||||
{
|
|
||||||
if (_glfw.posix_tls.allocated)
|
|
||||||
pthread_key_delete(_glfw.posix_tls.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
pthread_setspecific(_glfw.posix_tls.context, context);
|
assert(tls->posix.allocated == GLFW_FALSE);
|
||||||
|
|
||||||
|
if (pthread_key_create(&tls->posix.key, NULL) != 0)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"POSIX: Failed to create context TLS");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls->posix.allocated = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
return pthread_getspecific(_glfw.posix_tls.context);
|
assert(tls->posix.allocated == GLFW_TRUE);
|
||||||
|
if (tls->posix.allocated)
|
||||||
|
pthread_key_delete(tls->posix.key);
|
||||||
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->posix.allocated == GLFW_TRUE);
|
||||||
|
return pthread_getspecific(tls->posix.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||||
|
{
|
||||||
|
assert(tls->posix.allocated == GLFW_TRUE);
|
||||||
|
pthread_setspecific(tls->posix.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,20 +30,17 @@
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls
|
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
|
||||||
|
|
||||||
|
|
||||||
// POSIX-specific global TLS data
|
// POSIX-specific thread local storage data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtlsPOSIX
|
typedef struct _GLFWtlsPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
GLFWbool allocated;
|
||||||
pthread_key_t context;
|
pthread_key_t key;
|
||||||
|
|
||||||
} _GLFWtlsPOSIX;
|
} _GLFWtlsPOSIX;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
|
|
||||||
void _glfwTerminateThreadLocalStoragePOSIX(void);
|
|
||||||
|
|
||||||
#endif // _glfw3_posix_tls_h_
|
#endif // _glfw3_posix_tls_h_
|
||||||
|
|||||||
@ -233,12 +233,12 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
|
|||||||
if (window)
|
if (window)
|
||||||
{
|
{
|
||||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||||
_glfwPlatformSetCurrentContext(window);
|
_glfwPlatformSetTls(&_glfw.context, window);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to make context current");
|
"WGL: Failed to make context current");
|
||||||
_glfwPlatformSetCurrentContext(NULL);
|
_glfwPlatformSetTls(&_glfw.context, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -249,7 +249,7 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
|
|||||||
"WGL: Failed to clear current context");
|
"WGL: Failed to clear current context");
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetCurrentContext(NULL);
|
_glfwPlatformSetTls(&_glfw.context, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +268,7 @@ static void swapBuffersWGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalWGL(int interval)
|
static void swapIntervalWGL(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context);
|
||||||
|
|
||||||
window->context.wgl.interval = interval;
|
window->context.wgl.interval = interval;
|
||||||
|
|
||||||
|
|||||||
@ -307,10 +307,10 @@ static HWND createHelperWindow(void)
|
|||||||
MSG msg;
|
MSG msg;
|
||||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||||
_GLFW_WNDCLASSNAME,
|
_GLFW_WNDCLASSNAME,
|
||||||
L"GLFW helper window",
|
L"GLFW message window",
|
||||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||||
0, 0, 1, 1,
|
0, 0, 1, 1,
|
||||||
HWND_MESSAGE, NULL,
|
NULL, NULL,
|
||||||
GetModuleHandleW(NULL),
|
GetModuleHandleW(NULL),
|
||||||
NULL);
|
NULL);
|
||||||
if (!window)
|
if (!window)
|
||||||
@ -435,9 +435,6 @@ void _glfwInputErrorWin32(int error, const char* description)
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
if (!_glfwInitThreadLocalStorageWin32())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
// To make SetForegroundWindow work as we want, we need to fiddle
|
// To make SetForegroundWindow work as we want, we need to fiddle
|
||||||
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
||||||
// as possible in the hope of still being the foreground process)
|
// as possible in the hope of still being the foreground process)
|
||||||
@ -489,7 +486,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
|
|
||||||
_glfwTerminateJoysticksWin32();
|
_glfwTerminateJoysticksWin32();
|
||||||
_glfwTerminateThreadLocalStorageWin32();
|
|
||||||
|
|
||||||
freeLibraries();
|
freeLibraries();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -427,7 +427,8 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|||||||
|
|
||||||
js = _glfwAllocJoystick(name,
|
js = _glfwAllocJoystick(name,
|
||||||
data.axisCount + data.sliderCount,
|
data.axisCount + data.sliderCount,
|
||||||
data.buttonCount + data.povCount * 4);
|
data.buttonCount,
|
||||||
|
data.povCount);
|
||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
IDirectInputDevice8_Release(device);
|
IDirectInputDevice8_Release(device);
|
||||||
@ -512,7 +513,7 @@ void _glfwDetectJoystickConnectionWin32(void)
|
|||||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 14);
|
js = _glfwAllocJoystick(getDeviceDescription(&xic), 6, 10, 1);
|
||||||
if (!js)
|
if (!js)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -561,7 +562,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
|
|
||||||
if (js->win32.device)
|
if (js->win32.device)
|
||||||
{
|
{
|
||||||
int i, j, ai = 0, bi = 0;
|
int i, ai = 0, bi = 0, pi = 0;
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
DIJOYSTATE state;
|
DIJOYSTATE state;
|
||||||
|
|
||||||
@ -612,19 +613,26 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
|
|
||||||
case _GLFW_TYPE_POV:
|
case _GLFW_TYPE_POV:
|
||||||
{
|
{
|
||||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
const int states[9] =
|
||||||
|
{
|
||||||
|
GLFW_HAT_UP,
|
||||||
|
GLFW_HAT_RIGHT_UP,
|
||||||
|
GLFW_HAT_RIGHT,
|
||||||
|
GLFW_HAT_RIGHT_DOWN,
|
||||||
|
GLFW_HAT_DOWN,
|
||||||
|
GLFW_HAT_LEFT_DOWN,
|
||||||
|
GLFW_HAT_LEFT,
|
||||||
|
GLFW_HAT_LEFT_UP,
|
||||||
|
GLFW_HAT_CENTERED
|
||||||
|
};
|
||||||
|
|
||||||
// Screams of horror are appropriate at this point
|
// Screams of horror are appropriate at this point
|
||||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||||
if (state < 0 || state > 8)
|
if (state < 0 || state > 8)
|
||||||
state = 8;
|
state = 8;
|
||||||
|
|
||||||
for (j = 0; j < 4; j++)
|
_glfwInputJoystickHat(jid, pi, states[state]);
|
||||||
{
|
pi++;
|
||||||
const char value = (directions[state] & (1 << j)) != 0;
|
|
||||||
_glfwInputJoystickButton(jid, bi, value);
|
|
||||||
bi++;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,7 +640,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i, dpad = 0;
|
||||||
DWORD result;
|
DWORD result;
|
||||||
XINPUT_STATE xis;
|
XINPUT_STATE xis;
|
||||||
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
||||||
@ -647,11 +655,7 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
XINPUT_GAMEPAD_BACK,
|
XINPUT_GAMEPAD_BACK,
|
||||||
XINPUT_GAMEPAD_START,
|
XINPUT_GAMEPAD_START,
|
||||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||||
XINPUT_GAMEPAD_DPAD_UP,
|
|
||||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
|
||||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
|
||||||
XINPUT_GAMEPAD_DPAD_LEFT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
result = XInputGetState(js->win32.index, &xis);
|
result = XInputGetState(js->win32.index, &xis);
|
||||||
@ -693,11 +697,22 @@ int _glfwPlatformPollJoystick(int jid, int mode)
|
|||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
_glfwInputJoystickAxis(jid, i, axes[i]);
|
_glfwInputJoystickAxis(jid, i, axes[i]);
|
||||||
|
|
||||||
for (i = 0; i < 14; i++)
|
for (i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||||
_glfwInputJoystickButton(jid, i, value);
|
_glfwInputJoystickButton(jid, i, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
|
||||||
|
dpad |= GLFW_HAT_UP;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
|
||||||
|
dpad |= GLFW_HAT_RIGHT;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
|
||||||
|
dpad |= GLFW_HAT_DOWN;
|
||||||
|
if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
|
||||||
|
dpad |= GLFW_HAT_LEFT;
|
||||||
|
|
||||||
|
_glfwInputJoystickHat(jid, 0, dpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
|
|||||||
@ -94,7 +94,7 @@ void _glfwPollMonitorsWin32(void)
|
|||||||
_GLFWmonitor** disconnected = NULL;
|
_GLFWmonitor** disconnected = NULL;
|
||||||
DWORD adapterIndex, displayIndex;
|
DWORD adapterIndex, displayIndex;
|
||||||
DISPLAY_DEVICEW adapter, display;
|
DISPLAY_DEVICEW adapter, display;
|
||||||
GLFWbool hasDisplays = GLFW_FALSE;
|
_GLFWmonitor* monitor;
|
||||||
|
|
||||||
disconnectedCount = _glfw.monitorCount;
|
disconnectedCount = _glfw.monitorCount;
|
||||||
if (disconnectedCount)
|
if (disconnectedCount)
|
||||||
@ -105,30 +105,6 @@ void _glfwPollMonitorsWin32(void)
|
|||||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK: Check if any active adapters have connected displays
|
|
||||||
// If not, this is a headless system or a VMware guest
|
|
||||||
|
|
||||||
for (adapterIndex = 0; ; adapterIndex++)
|
|
||||||
{
|
|
||||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
|
||||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
|
||||||
|
|
||||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
|
||||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
|
||||||
|
|
||||||
if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
|
|
||||||
{
|
|
||||||
hasDisplays = GLFW_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (adapterIndex = 0; ; adapterIndex++)
|
for (adapterIndex = 0; ; adapterIndex++)
|
||||||
{
|
{
|
||||||
int type = _GLFW_INSERT_LAST;
|
int type = _GLFW_INSERT_LAST;
|
||||||
@ -145,37 +121,46 @@ void _glfwPollMonitorsWin32(void)
|
|||||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||||
type = _GLFW_INSERT_FIRST;
|
type = _GLFW_INSERT_FIRST;
|
||||||
|
|
||||||
if (hasDisplays)
|
for (displayIndex = 0; ; displayIndex++)
|
||||||
{
|
{
|
||||||
for (displayIndex = 0; ; displayIndex++)
|
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||||
|
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||||
|
|
||||||
|
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
{
|
{
|
||||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
if (disconnected[i] &&
|
||||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
wcscmp(disconnected[i]->win32.displayName,
|
||||||
|
display.DeviceName) == 0)
|
||||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
|
||||||
{
|
{
|
||||||
if (disconnected[i] &&
|
disconnected[i] = NULL;
|
||||||
wcscmp(disconnected[i]->win32.displayName,
|
break;
|
||||||
display.DeviceName) == 0)
|
|
||||||
{
|
|
||||||
disconnected[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < disconnectedCount)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_glfwInputMonitor(createMonitor(&adapter, &display),
|
|
||||||
GLFW_CONNECTED, type);
|
|
||||||
|
|
||||||
type = _GLFW_INSERT_LAST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i < disconnectedCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitor = createMonitor(&adapter, &display);
|
||||||
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
|
|
||||||
|
type = _GLFW_INSERT_LAST;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
// HACK: If an active adapter does not have any display devices
|
||||||
|
// (as sometimes happens), add it directly as a monitor
|
||||||
|
if (displayIndex == 0)
|
||||||
{
|
{
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
for (i = 0; i < disconnectedCount; i++)
|
||||||
{
|
{
|
||||||
@ -191,8 +176,14 @@ void _glfwPollMonitorsWin32(void)
|
|||||||
if (i < disconnectedCount)
|
if (i < disconnectedCount)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_glfwInputMonitor(createMonitor(&adapter, NULL),
|
monitor = createMonitor(&adapter, NULL);
|
||||||
GLFW_CONNECTED, type);
|
if (!monitor)
|
||||||
|
{
|
||||||
|
free(disconnected);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -220,10 +220,10 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
|||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
|
||||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||||
|
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
||||||
|
|
||||||
|
|
||||||
// Win32-specific per-window data
|
// Win32-specific per-window data
|
||||||
@ -321,19 +321,19 @@ typedef struct _GLFWcursorWin32
|
|||||||
|
|
||||||
// Win32-specific global timer data
|
// Win32-specific global timer data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtimeWin32
|
typedef struct _GLFWtimerWin32
|
||||||
{
|
{
|
||||||
GLFWbool hasPC;
|
GLFWbool hasPC;
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimeWin32;
|
} _GLFWtimerWin32;
|
||||||
|
|
||||||
// Win32-specific global TLS data
|
// Win32-specific thread local storage data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWtlsWin32
|
typedef struct _GLFWtlsWin32
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
GLFWbool allocated;
|
||||||
DWORD context;
|
DWORD index;
|
||||||
|
|
||||||
} _GLFWtlsWin32;
|
} _GLFWtlsWin32;
|
||||||
|
|
||||||
@ -341,9 +341,6 @@ typedef struct _GLFWtlsWin32
|
|||||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||||
void _glfwUnregisterWindowClassWin32(void);
|
void _glfwUnregisterWindowClassWin32(void);
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStorageWin32(void);
|
|
||||||
void _glfwTerminateThreadLocalStorageWin32(void);
|
|
||||||
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||||
void _glfwInputErrorWin32(int error, const char* description);
|
void _glfwInputErrorWin32(int error, const char* description);
|
||||||
|
|||||||
@ -40,13 +40,13 @@ void _glfwInitTimerWin32(void)
|
|||||||
|
|
||||||
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||||
{
|
{
|
||||||
_glfw.win32_time.hasPC = GLFW_TRUE;
|
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
||||||
_glfw.win32_time.frequency = frequency;
|
_glfw.timer.win32.frequency = frequency;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfw.win32_time.hasPC = GLFW_FALSE;
|
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
||||||
_glfw.win32_time.frequency = 1000;
|
_glfw.timer.win32.frequency = 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ void _glfwInitTimerWin32(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
uint64_t _glfwPlatformGetTimerValue(void)
|
||||||
{
|
{
|
||||||
if (_glfw.win32_time.hasPC)
|
if (_glfw.timer.win32.hasPC)
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||||
@ -69,6 +69,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
|||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||||
{
|
{
|
||||||
return _glfw.win32_time.frequency;
|
return _glfw.timer.win32.frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,43 +27,46 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWbool _glfwInitThreadLocalStorageWin32(void)
|
|
||||||
{
|
|
||||||
_glfw.win32_tls.context = TlsAlloc();
|
|
||||||
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to allocate TLS index");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32_tls.allocated = GLFW_TRUE;
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwTerminateThreadLocalStorageWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32_tls.allocated)
|
|
||||||
TlsFree(_glfw.win32_tls.context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
TlsSetValue(_glfw.win32_tls.context, context);
|
assert(tls->win32.allocated == GLFW_FALSE);
|
||||||
|
|
||||||
|
tls->win32.index = TlsAlloc();
|
||||||
|
if (tls->win32.index == TLS_OUT_OF_INDEXES)
|
||||||
|
{
|
||||||
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to allocate TLS index");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls->win32.allocated = GLFW_TRUE;
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
return TlsGetValue(_glfw.win32_tls.context);
|
assert(tls->win32.allocated == GLFW_TRUE);
|
||||||
|
if (tls->win32.allocated)
|
||||||
|
TlsFree(tls->win32.index);
|
||||||
|
memset(tls, 0, sizeof(_GLFWtls));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||||
|
{
|
||||||
|
assert(tls->win32.allocated == GLFW_TRUE);
|
||||||
|
return TlsGetValue(tls->win32.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||||
|
{
|
||||||
|
assert(tls->win32.allocated == GLFW_TRUE);
|
||||||
|
TlsSetValue(tls->win32.index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -467,30 +467,23 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
|
case WM_DISPLAYCHANGE:
|
||||||
|
_glfwPollMonitorsWin32();
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_DEVICECHANGE:
|
case WM_DEVICECHANGE:
|
||||||
{
|
{
|
||||||
if (wParam == DBT_DEVNODES_CHANGED)
|
if (wParam == DBT_DEVICEARRIVAL)
|
||||||
{
|
|
||||||
_glfwPollMonitorsWin32();
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else if (wParam == DBT_DEVICEARRIVAL)
|
|
||||||
{
|
{
|
||||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||||
if (dbh)
|
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||||
{
|
_glfwDetectJoystickConnectionWin32();
|
||||||
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
|
||||||
_glfwDetectJoystickConnectionWin32();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
||||||
{
|
{
|
||||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||||
if (dbh)
|
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||||
{
|
_glfwDetectJoystickDisconnectionWin32();
|
||||||
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
|
||||||
_glfwDetectJoystickDisconnectionWin32();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -192,7 +192,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
window->denom = GLFW_DONT_CARE;
|
window->denom = GLFW_DONT_CARE;
|
||||||
|
|
||||||
// Save the currently current context so it can be restored later
|
// Save the currently current context so it can be restored later
|
||||||
previous = _glfwPlatformGetCurrentContext();
|
previous = _glfwPlatformGetTls(&_glfw.context);
|
||||||
if (ctxconfig.client != GLFW_NO_API)
|
if (ctxconfig.client != GLFW_NO_API)
|
||||||
glfwMakeContextCurrent(NULL);
|
glfwMakeContextCurrent(NULL);
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
|||||||
|
|
||||||
// The window's context must not be current on another thread when the
|
// The window's context must not be current on another thread when the
|
||||||
// window is destroyed
|
// window is destroyed
|
||||||
if (window == _glfwPlatformGetCurrentContext())
|
if (window == _glfwPlatformGetTls(&_glfw.context))
|
||||||
glfwMakeContextCurrent(NULL);
|
glfwMakeContextCurrent(NULL);
|
||||||
|
|
||||||
_glfwPlatformDestroyWindow(window);
|
_glfwPlatformDestroyWindow(window);
|
||||||
|
|||||||
@ -667,9 +667,6 @@ int _glfwPlatformInit(void)
|
|||||||
// Sync so we got all initial output events
|
// Sync so we got all initial output events
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
@ -695,7 +692,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
{
|
{
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
|
|
||||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||||
|
|||||||
@ -51,6 +51,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
|
#include "osmesa_context.h"
|
||||||
|
|
||||||
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
||||||
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||||
|
|||||||
@ -395,10 +395,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitEGL())
|
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||||
return GLFW_FALSE;
|
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
{
|
||||||
return GLFW_FALSE;
|
if (!_glfwInitEGL())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
|
{
|
||||||
|
if (!_glfwInitOSMesa())
|
||||||
|
return GLFW_FALSE;
|
||||||
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->title)
|
if (wndconfig->title)
|
||||||
|
|||||||
@ -455,7 +455,7 @@ static void detectEWMH(void)
|
|||||||
XFree(supportedAtoms);
|
XFree(supportedAtoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize X11 display and look for supported X11 extensions
|
// Look for and initialize supported X11 extensions
|
||||||
//
|
//
|
||||||
static GLFWbool initExtensions(void)
|
static GLFWbool initExtensions(void)
|
||||||
{
|
{
|
||||||
@ -477,7 +477,7 @@ static GLFWbool initExtensions(void)
|
|||||||
&_glfw.x11.vidmode.errorBase);
|
&_glfw.x11.vidmode.errorBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.x11.xi.handle = dlopen("libXi.so", RTLD_LAZY | RTLD_GLOBAL);
|
_glfw.x11.xi.handle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_GLOBAL);
|
||||||
if (_glfw.x11.xi.handle)
|
if (_glfw.x11.xi.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
|
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
|
||||||
@ -503,7 +503,6 @@ static GLFWbool initExtensions(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for RandR extension
|
|
||||||
if (XRRQueryExtension(_glfw.x11.display,
|
if (XRRQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.randr.eventBase,
|
&_glfw.x11.randr.eventBase,
|
||||||
&_glfw.x11.randr.errorBase))
|
&_glfw.x11.randr.errorBase))
|
||||||
@ -530,26 +529,23 @@ static GLFWbool initExtensions(void)
|
|||||||
|
|
||||||
if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
|
if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
|
||||||
{
|
{
|
||||||
// This is either a headless system or an older Nvidia binary driver
|
// This is likely an older Nvidia driver with broken gamma support
|
||||||
// with broken gamma support
|
// Flag it as useless and fall back to xf86vm gamma, if available
|
||||||
// Flag it as useless and fall back to Xf86VidMode gamma, if
|
|
||||||
// available
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Detected broken RandR gamma ramp support");
|
|
||||||
_glfw.x11.randr.gammaBroken = GLFW_TRUE;
|
_glfw.x11.randr.gammaBroken = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sr->ncrtc || !sr->noutput || !sr->nmode)
|
if (!sr->ncrtc)
|
||||||
{
|
{
|
||||||
// This is either a headless system or broken Cygwin/X RandR
|
// A system without CRTCs is likely a system with broken RandR
|
||||||
// Flag it as useless and fall back to Xlib display functions
|
// Disable the RandR monitor path and fall back to core functions
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Detected broken RandR monitor support");
|
|
||||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
|
XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
|
||||||
RROutputChangeNotifyMask);
|
RROutputChangeNotifyMask);
|
||||||
}
|
}
|
||||||
@ -562,7 +558,6 @@ static GLFWbool initExtensions(void)
|
|||||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
_glfw.x11.xinerama.available = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if Xkb is supported on this display
|
|
||||||
_glfw.x11.xkb.major = 1;
|
_glfw.x11.xkb.major = 1;
|
||||||
_glfw.x11.xkb.minor = 0;
|
_glfw.x11.xkb.minor = 0;
|
||||||
_glfw.x11.xkb.available =
|
_glfw.x11.xkb.available =
|
||||||
@ -629,9 +624,10 @@ static GLFWbool initExtensions(void)
|
|||||||
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
|
_glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);
|
||||||
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
_glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);
|
||||||
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
|
_glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);
|
||||||
_glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
|
|
||||||
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
||||||
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
|
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
|
||||||
|
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
||||||
|
_glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
|
||||||
|
|
||||||
// ICCCM, EWMH and Motif window property atoms
|
// ICCCM, EWMH and Motif window property atoms
|
||||||
// These can be set safely even without WM support
|
// These can be set safely even without WM support
|
||||||
@ -664,11 +660,8 @@ static GLFWbool initExtensions(void)
|
|||||||
//
|
//
|
||||||
static Cursor createHiddenCursor(void)
|
static Cursor createHiddenCursor(void)
|
||||||
{
|
{
|
||||||
unsigned char pixels[16 * 16 * 4];
|
unsigned char pixels[16 * 16 * 4] = { 0 };
|
||||||
GLFWimage image = { 16, 16, pixels };
|
GLFWimage image = { 16, 16, pixels };
|
||||||
|
|
||||||
memset(pixels, 0, sizeof(pixels));
|
|
||||||
|
|
||||||
return _glfwCreateCursorX11(&image, 0, 0);
|
return _glfwCreateCursorX11(&image, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,9 +814,6 @@ int _glfwPlatformInit(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@ -884,7 +874,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
#endif
|
#endif
|
||||||
_glfwTerminateThreadLocalStoragePOSIX();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
|||||||
@ -202,13 +202,6 @@ void _glfwPollMonitorsX11(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(disconnected);
|
free(disconnected);
|
||||||
|
|
||||||
if (!_glfw.monitorCount)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: RandR monitor support seems broken");
|
|
||||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_glfw.monitorCount)
|
if (!_glfw.monitorCount)
|
||||||
@ -437,9 +430,9 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
|
|
||||||
_glfwAllocGammaArrays(ramp, size);
|
_glfwAllocGammaArrays(ramp, size);
|
||||||
|
|
||||||
memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
|
memcpy(ramp->red, gamma->red, size * sizeof(unsigned short));
|
||||||
memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
|
memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
|
||||||
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||||
|
|
||||||
XRRFreeGamma(gamma);
|
XRRFreeGamma(gamma);
|
||||||
}
|
}
|
||||||
@ -462,9 +455,9 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|||||||
{
|
{
|
||||||
XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
|
XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
|
||||||
|
|
||||||
memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
|
memcpy(gamma->red, ramp->red, ramp->size * sizeof(unsigned short));
|
||||||
memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
|
memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
|
||||||
memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
|
memcpy(gamma->blue, ramp->blue, ramp->size * sizeof(unsigned short));
|
||||||
|
|
||||||
XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
|
XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
|
||||||
XRRFreeGamma(gamma);
|
XRRFreeGamma(gamma);
|
||||||
|
|||||||
@ -141,8 +141,7 @@ typedef struct _GLFWwindowX11
|
|||||||
// The last position the cursor was warped to by GLFW
|
// The last position the cursor was warped to by GLFW
|
||||||
int warpCursorPosX, warpCursorPosY;
|
int warpCursorPosX, warpCursorPosY;
|
||||||
|
|
||||||
// The information from the last KeyPress event
|
// The time of the last KeyPress event
|
||||||
unsigned int lastKeyCode;
|
|
||||||
Time lastKeyTime;
|
Time lastKeyTime;
|
||||||
|
|
||||||
} _GLFWwindowX11;
|
} _GLFWwindowX11;
|
||||||
@ -208,9 +207,10 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom XdndStatus;
|
Atom XdndStatus;
|
||||||
Atom XdndActionCopy;
|
Atom XdndActionCopy;
|
||||||
Atom XdndDrop;
|
Atom XdndDrop;
|
||||||
Atom XdndLeave;
|
|
||||||
Atom XdndFinished;
|
Atom XdndFinished;
|
||||||
Atom XdndSelection;
|
Atom XdndSelection;
|
||||||
|
Atom XdndTypeList;
|
||||||
|
Atom text_uri_list;
|
||||||
|
|
||||||
// Selection (clipboard) atoms
|
// Selection (clipboard) atoms
|
||||||
Atom TARGETS;
|
Atom TARGETS;
|
||||||
@ -253,7 +253,9 @@ typedef struct _GLFWlibraryX11
|
|||||||
} saver;
|
} saver;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
int version;
|
||||||
Window source;
|
Window source;
|
||||||
|
Atom format;
|
||||||
} xdnd;
|
} xdnd;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
195
src/x11_window.c
195
src/x11_window.c
@ -48,6 +48,8 @@
|
|||||||
#define Button6 6
|
#define Button6 6
|
||||||
#define Button7 7
|
#define Button7 7
|
||||||
|
|
||||||
|
#define _GLFW_XDND_VERSION 5
|
||||||
|
|
||||||
|
|
||||||
// Wait for data to arrive using select
|
// Wait for data to arrive using select
|
||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
@ -415,7 +417,12 @@ static char** parseUriList(char* text, int* count)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(line, prefix, strlen(prefix)) == 0)
|
if (strncmp(line, prefix, strlen(prefix)) == 0)
|
||||||
|
{
|
||||||
line += strlen(prefix);
|
line += strlen(prefix);
|
||||||
|
// TODO: Validate hostname
|
||||||
|
while (*line != '/')
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
|
||||||
(*count)++;
|
(*count)++;
|
||||||
|
|
||||||
@ -619,10 +626,9 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
XFree(hint);
|
XFree(hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.x11.XdndAware)
|
// Announce support for Xdnd (drag and drop)
|
||||||
{
|
{
|
||||||
// Announce support for Xdnd (drag and drop)
|
const Atom version = _GLFW_XDND_VERSION;
|
||||||
const Atom version = 5;
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.XdndAware, XA_ATOM, 32,
|
_glfw.x11.XdndAware, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char*) &version, 1);
|
PropModeReplace, (unsigned char*) &version, 1);
|
||||||
@ -957,6 +963,17 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event->type == SelectionClear)
|
||||||
|
{
|
||||||
|
handleSelectionClear(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (event->type == SelectionRequest)
|
||||||
|
{
|
||||||
|
handleSelectionRequest(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
window = findWindowByHandle(event->xany.window);
|
window = findWindowByHandle(event->xany.window);
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
{
|
{
|
||||||
@ -975,17 +992,16 @@ static void processEvent(XEvent *event)
|
|||||||
if (window->x11.ic)
|
if (window->x11.ic)
|
||||||
{
|
{
|
||||||
// HACK: Ignore duplicate key press events generated by ibus
|
// HACK: Ignore duplicate key press events generated by ibus
|
||||||
// Corresponding release events are filtered out by the
|
// These have the same timestamp as the original event
|
||||||
// GLFW key repeat logic
|
// Corresponding release events are filtered out
|
||||||
if (window->x11.lastKeyCode != keycode ||
|
// implicitly by the GLFW key repeat logic
|
||||||
window->x11.lastKeyTime != event->xkey.time)
|
if (window->x11.lastKeyTime < event->xkey.time)
|
||||||
{
|
{
|
||||||
if (keycode)
|
if (keycode)
|
||||||
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
_glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
|
||||||
}
|
|
||||||
|
|
||||||
window->x11.lastKeyCode = keycode;
|
window->x11.lastKeyTime = event->xkey.time;
|
||||||
window->x11.lastKeyTime = event->xkey.time;
|
}
|
||||||
|
|
||||||
if (!filtered)
|
if (!filtered)
|
||||||
{
|
{
|
||||||
@ -1296,44 +1312,121 @@ static void processEvent(XEvent *event)
|
|||||||
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
|
else if (event->xclient.message_type == _glfw.x11.XdndEnter)
|
||||||
{
|
{
|
||||||
// A drag operation has entered the window
|
// A drag operation has entered the window
|
||||||
// TODO: Check if UTF-8 string is supported by the source
|
unsigned long i, count;
|
||||||
|
Atom* formats = NULL;
|
||||||
|
const GLFWbool list = event->xclient.data.l[1] & 1;
|
||||||
|
|
||||||
|
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
||||||
|
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
||||||
|
_glfw.x11.xdnd.format = None;
|
||||||
|
|
||||||
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
|
||||||
|
_glfw.x11.XdndTypeList,
|
||||||
|
XA_ATOM,
|
||||||
|
(unsigned char**) &formats);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count = 3;
|
||||||
|
formats = (Atom*) event->xclient.data.l + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (formats[i] == _glfw.x11.text_uri_list)
|
||||||
|
{
|
||||||
|
_glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list && formats)
|
||||||
|
XFree(formats);
|
||||||
}
|
}
|
||||||
else if (event->xclient.message_type == _glfw.x11.XdndDrop)
|
else if (event->xclient.message_type == _glfw.x11.XdndDrop)
|
||||||
{
|
{
|
||||||
// The drag operation has finished dropping on
|
// The drag operation has finished by dropping on the window
|
||||||
// the window, ask to convert it to a UTF-8 string
|
Time time = CurrentTime;
|
||||||
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
|
||||||
XConvertSelection(_glfw.x11.display,
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
_glfw.x11.XdndSelection,
|
return;
|
||||||
_glfw.x11.UTF8_STRING,
|
|
||||||
_glfw.x11.XdndSelection,
|
if (_glfw.x11.xdnd.format)
|
||||||
window->x11.handle, CurrentTime);
|
{
|
||||||
|
if (_glfw.x11.xdnd.version >= 1)
|
||||||
|
time = event->xclient.data.l[2];
|
||||||
|
|
||||||
|
// Request the chosen format from the source window
|
||||||
|
XConvertSelection(_glfw.x11.display,
|
||||||
|
_glfw.x11.XdndSelection,
|
||||||
|
_glfw.x11.xdnd.format,
|
||||||
|
_glfw.x11.XdndSelection,
|
||||||
|
window->x11.handle,
|
||||||
|
time);
|
||||||
|
}
|
||||||
|
else if (_glfw.x11.xdnd.version >= 2)
|
||||||
|
{
|
||||||
|
XEvent reply;
|
||||||
|
memset(&reply, 0, sizeof(reply));
|
||||||
|
|
||||||
|
reply.type = ClientMessage;
|
||||||
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
|
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
||||||
|
reply.xclient.format = 32;
|
||||||
|
reply.xclient.data.l[0] = window->x11.handle;
|
||||||
|
reply.xclient.data.l[1] = 0; // The drag was rejected
|
||||||
|
reply.xclient.data.l[2] = None;
|
||||||
|
|
||||||
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
||||||
|
False, NoEventMask, &reply);
|
||||||
|
XFlush(_glfw.x11.display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (event->xclient.message_type == _glfw.x11.XdndPosition)
|
else if (event->xclient.message_type == _glfw.x11.XdndPosition)
|
||||||
{
|
{
|
||||||
// The drag operation has moved over the window
|
// The drag operation has moved over the window
|
||||||
const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF;
|
const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
|
||||||
const int absY = (event->xclient.data.l[2]) & 0xFFFF;
|
const int yabs = (event->xclient.data.l[2]) & 0xffff;
|
||||||
int x, y;
|
Window dummy;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
_glfwPlatformGetWindowPos(window, &x, &y);
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
_glfwInputCursorPos(window, absX - x, absY - y);
|
return;
|
||||||
|
|
||||||
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
|
_glfw.x11.root,
|
||||||
|
window->x11.handle,
|
||||||
|
xabs, yabs,
|
||||||
|
&xpos, &ypos,
|
||||||
|
&dummy);
|
||||||
|
|
||||||
|
_glfwInputCursorPos(window, xpos, ypos);
|
||||||
|
|
||||||
// Reply that we are ready to copy the dragged data
|
|
||||||
XEvent reply;
|
XEvent reply;
|
||||||
memset(&reply, 0, sizeof(reply));
|
memset(&reply, 0, sizeof(reply));
|
||||||
|
|
||||||
reply.type = ClientMessage;
|
reply.type = ClientMessage;
|
||||||
reply.xclient.window = event->xclient.data.l[0];
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
reply.xclient.data.l[0] = window->x11.handle;
|
reply.xclient.data.l[0] = window->x11.handle;
|
||||||
reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle
|
|
||||||
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
||||||
reply.xclient.data.l[3] = 0;
|
reply.xclient.data.l[3] = 0;
|
||||||
reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, event->xclient.data.l[0],
|
if (_glfw.x11.xdnd.format)
|
||||||
|
{
|
||||||
|
// Reply that we are ready to copy the dragged data
|
||||||
|
reply.xclient.data.l[1] = 1; // Accept with no rectangle
|
||||||
|
if (_glfw.x11.xdnd.version >= 2)
|
||||||
|
reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
||||||
False, NoEventMask, &reply);
|
False, NoEventMask, &reply);
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
@ -1343,11 +1436,11 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case SelectionNotify:
|
case SelectionNotify:
|
||||||
{
|
{
|
||||||
if (event->xselection.property)
|
if (event->xselection.property == _glfw.x11.XdndSelection)
|
||||||
{
|
{
|
||||||
// The converted data from the drag operation has arrived
|
// The converted data from the drag operation has arrived
|
||||||
char* data;
|
char* data;
|
||||||
const int result =
|
const unsigned long result =
|
||||||
_glfwGetWindowPropertyX11(event->xselection.requestor,
|
_glfwGetWindowPropertyX11(event->xselection.requestor,
|
||||||
event->xselection.property,
|
event->xselection.property,
|
||||||
event->xselection.target,
|
event->xselection.target,
|
||||||
@ -1368,21 +1461,23 @@ static void processEvent(XEvent *event)
|
|||||||
if (data)
|
if (data)
|
||||||
XFree(data);
|
XFree(data);
|
||||||
|
|
||||||
XEvent reply;
|
if (_glfw.x11.xdnd.version >= 2)
|
||||||
memset(&reply, 0, sizeof(reply));
|
{
|
||||||
|
XEvent reply;
|
||||||
|
memset(&reply, 0, sizeof(reply));
|
||||||
|
|
||||||
reply.type = ClientMessage;
|
reply.type = ClientMessage;
|
||||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
reply.xclient.data.l[0] = window->x11.handle;
|
reply.xclient.data.l[0] = window->x11.handle;
|
||||||
reply.xclient.data.l[1] = result;
|
reply.xclient.data.l[1] = result;
|
||||||
reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;
|
reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;
|
||||||
|
|
||||||
// Reply that all is well
|
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
|
False, NoEventMask, &reply);
|
||||||
False, NoEventMask, &reply);
|
XFlush(_glfw.x11.display);
|
||||||
XFlush(_glfw.x11.display);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1476,18 +1571,6 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SelectionClear:
|
|
||||||
{
|
|
||||||
handleSelectionClear(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SelectionRequest:
|
|
||||||
{
|
|
||||||
handleSelectionRequest(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -463,17 +463,19 @@ static void joystick_callback(int jid, int event)
|
|||||||
{
|
{
|
||||||
if (event == GLFW_CONNECTED)
|
if (event == GLFW_CONNECTED)
|
||||||
{
|
{
|
||||||
int axisCount, buttonCount;
|
int axisCount, buttonCount, hatCount;
|
||||||
|
|
||||||
glfwGetJoystickAxes(jid, &axisCount);
|
glfwGetJoystickAxes(jid, &axisCount);
|
||||||
glfwGetJoystickButtons(jid, &buttonCount);
|
glfwGetJoystickButtons(jid, &buttonCount);
|
||||||
|
glfwGetJoystickHats(jid, &hatCount);
|
||||||
|
|
||||||
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes and %i buttons\n",
|
printf("%08x at %0.3f: Joystick %i (%s) was connected with %i axes, %i buttons, and %i hats\n",
|
||||||
counter++, glfwGetTime(),
|
counter++, glfwGetTime(),
|
||||||
jid,
|
jid,
|
||||||
glfwGetJoystickName(jid),
|
glfwGetJoystickName(jid),
|
||||||
axisCount,
|
axisCount,
|
||||||
buttonCount);
|
buttonCount,
|
||||||
|
hatCount);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -90,7 +90,7 @@ static const char* joystick_label(int jid)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int jid;
|
int jid, hat_buttons = GLFW_FALSE;
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
struct nk_context* nk;
|
struct nk_context* nk;
|
||||||
struct nk_font_atlas* atlas;
|
struct nk_font_atlas* atlas;
|
||||||
@ -142,6 +142,8 @@ int main(void)
|
|||||||
{
|
{
|
||||||
nk_layout_row_dynamic(nk, 30, 1);
|
nk_layout_row_dynamic(nk, 30, 1);
|
||||||
|
|
||||||
|
nk_checkbox_label(nk, "Hat buttons", &hat_buttons);
|
||||||
|
|
||||||
if (joystick_count)
|
if (joystick_count)
|
||||||
{
|
{
|
||||||
for (i = 0; i < joystick_count; i++)
|
for (i = 0; i < joystick_count; i++)
|
||||||
@ -167,29 +169,81 @@ int main(void)
|
|||||||
NK_WINDOW_MINIMIZABLE |
|
NK_WINDOW_MINIMIZABLE |
|
||||||
NK_WINDOW_TITLE))
|
NK_WINDOW_TITLE))
|
||||||
{
|
{
|
||||||
int j, axis_count, button_count;
|
int j, axis_count, button_count, hat_count;
|
||||||
const float* axes;
|
const float* axes;
|
||||||
const unsigned char* buttons;
|
const unsigned char* buttons;
|
||||||
|
const unsigned char* hats;
|
||||||
|
|
||||||
nk_layout_row_dynamic(nk, 30, 1);
|
nk_layout_row_dynamic(nk, 30, 1);
|
||||||
|
|
||||||
axes = glfwGetJoystickAxes(joysticks[i], &axis_count);
|
axes = glfwGetJoystickAxes(joysticks[i], &axis_count);
|
||||||
if (axis_count)
|
buttons = glfwGetJoystickButtons(joysticks[i], &button_count);
|
||||||
|
hats = glfwGetJoystickHats(joysticks[i], &hat_count);
|
||||||
|
|
||||||
|
if (!hat_buttons)
|
||||||
|
button_count -= hat_count * 4;
|
||||||
|
|
||||||
|
for (j = 0; j < axis_count; j++)
|
||||||
|
nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f);
|
||||||
|
|
||||||
|
nk_layout_row_dynamic(nk, 30, 8);
|
||||||
|
|
||||||
|
for (j = 0; j < button_count; j++)
|
||||||
{
|
{
|
||||||
for (j = 0; j < axis_count; j++)
|
char name[16];
|
||||||
nk_slide_float(nk, -1.f, axes[j], 1.f, 0.1f);
|
snprintf(name, sizeof(name), "%i", j + 1);
|
||||||
|
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
nk_layout_row_dynamic(nk, 30, 8);
|
nk_layout_row_dynamic(nk, 30, 8);
|
||||||
|
|
||||||
buttons = glfwGetJoystickButtons(joysticks[i], &button_count);
|
for (j = 0; j < hat_count; j++)
|
||||||
if (button_count)
|
|
||||||
{
|
{
|
||||||
for (j = 0; j < button_count; j++)
|
float radius;
|
||||||
|
struct nk_rect area;
|
||||||
|
struct nk_vec2 center;
|
||||||
|
|
||||||
|
if (nk_widget(&area, nk) != NK_WIDGET_VALID)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
center = nk_vec2(area.x + area.w / 2.f,
|
||||||
|
area.y + area.h / 2.f);
|
||||||
|
radius = NK_MIN(area.w, area.h) / 2.f;
|
||||||
|
|
||||||
|
nk_stroke_circle(nk_window_get_canvas(nk),
|
||||||
|
nk_rect(center.x - radius,
|
||||||
|
center.y - radius,
|
||||||
|
radius * 2.f,
|
||||||
|
radius * 2.f),
|
||||||
|
1.f,
|
||||||
|
nk_rgb(175, 175, 175));
|
||||||
|
|
||||||
|
if (hats[j])
|
||||||
{
|
{
|
||||||
char name[16];
|
const float angles[] =
|
||||||
snprintf(name, sizeof(name), "%i", j + 1);
|
{
|
||||||
nk_select_label(nk, name, NK_TEXT_CENTERED, buttons[j]);
|
0.f, 0.f,
|
||||||
|
NK_PI * 1.5f, NK_PI * 1.75f,
|
||||||
|
NK_PI, 0.f,
|
||||||
|
NK_PI * 1.25f, 0.f,
|
||||||
|
NK_PI * 0.5f, NK_PI * 0.25f,
|
||||||
|
0.f, 0.f,
|
||||||
|
NK_PI * 0.75f, 0.f,
|
||||||
|
};
|
||||||
|
const float cosa = nk_cos(angles[hats[j]]);
|
||||||
|
const float sina = nk_sin(angles[hats[j]]);
|
||||||
|
const struct nk_vec2 p0 = nk_vec2(0.f, -radius);
|
||||||
|
const struct nk_vec2 p1 = nk_vec2( radius / 2.f, -radius / 3.f);
|
||||||
|
const struct nk_vec2 p2 = nk_vec2(-radius / 2.f, -radius / 3.f);
|
||||||
|
|
||||||
|
nk_fill_triangle(nk_window_get_canvas(nk),
|
||||||
|
center.x + cosa * p0.x + sina * p0.y,
|
||||||
|
center.y + cosa * p0.y - sina * p0.x,
|
||||||
|
center.x + cosa * p1.x + sina * p1.y,
|
||||||
|
center.y + cosa * p1.y - sina * p1.x,
|
||||||
|
center.x + cosa * p2.x + sina * p2.y,
|
||||||
|
center.y + cosa * p2.y - sina * p2.x,
|
||||||
|
nk_rgb(175, 175, 175));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user