mirror of
https://github.com/glfw/glfw.git
synced 2026-09-17 22:32:50 +00:00
Compare commits
428 Commits
3.2
...
drag-window
| Author | SHA1 | Date | |
|---|---|---|---|
| cad8f2f7d5 | |||
| ea46ea0929 | |||
| ce87a1142e | |||
| a4c76fbeed | |||
| 5b7281bd41 | |||
| 85eda77d35 | |||
| 213dd2d0d6 | |||
| 00d2efb9ab | |||
| 4feede6dd5 | |||
| c0bc10427c | |||
| 2d8d8f5917 | |||
| 472e5fc4a9 | |||
| e55e616f1f | |||
| 50a228394f | |||
| afbd589348 | |||
| 82284b86eb | |||
| d3247a8c83 | |||
| 67c9155f3b | |||
| 8e899ccc29 | |||
| d55c57b504 | |||
| ea6c50d9e2 | |||
| 6634c47e57 | |||
| 2fa90ae19f | |||
| 2e9aff759e | |||
| 617c42b20a | |||
| 953106e74d | |||
| 07bf2b166b | |||
| 8c0512027f | |||
| be51c201dd | |||
| 57f872054c | |||
| 9bb5e880ae | |||
| 9610d68f19 | |||
| 539a728063 | |||
| 58c05ba8ee | |||
| d5de48ab53 | |||
| 99762ad7f0 | |||
| 6da26c8d6c | |||
| d2952e4e92 | |||
| 206f9ca4bc | |||
| d1a2ec4d20 | |||
| 78666204a1 | |||
| 2ca9a0979e | |||
| 5bcf9c76fd | |||
| 4dee58d480 | |||
| 32f482a6d8 | |||
| 0321bec232 | |||
| 2bb8517e9e | |||
| f4ea29cd06 | |||
| 52f7684487 | |||
| d2779aa765 | |||
| a3007b9b0e | |||
| 14a3fe0ac0 | |||
| beaeb0d4af | |||
| c48127fa9e | |||
| 372e908682 | |||
| bc7ebc1a89 | |||
| 186d03b32a | |||
| c8ea64976f | |||
| 2023095d8e | |||
| 8597002a17 | |||
| 4f7102be26 | |||
| e4e3e50867 | |||
| fa0b5e1b85 | |||
| 018ae69b33 | |||
| 244d6d7823 | |||
| d1d08ef99f | |||
| 85c6168bba | |||
| 2f5e230338 | |||
| baa9cd8968 | |||
| 412eb6a611 | |||
| 4e8e25a521 | |||
| 731ff91acd | |||
| b234e28d5d | |||
| d6fcbdc38b | |||
| f737e8ce9f | |||
| 6350641f0a | |||
| 16ddfafeaa | |||
| 4884232360 | |||
| 9457cf33d1 | |||
| 66b16f1fc1 | |||
| 2226e60944 | |||
| 9558b85f7b | |||
| c9003b5547 | |||
| 9f63a8abfa | |||
| 4ff66a7818 | |||
| 72d58d7b93 | |||
| 11c15b562d | |||
| 9b81d72c46 | |||
| b0277a129b | |||
| 120082ee3a | |||
| 6abb5cbcbb | |||
| b215a989f5 | |||
| 5fe4dfb511 | |||
| cf2eab5b4e | |||
| 55d0560746 | |||
| 1982543cd2 | |||
| aaf2800c9c | |||
| 62414bff6e | |||
| 2376d3b16a | |||
| 6a65341e14 | |||
| bff31f006e | |||
| 7410346c5c | |||
| 27a8b3c17b | |||
| 7c070f55be | |||
| 3d8aa53573 | |||
| 7c88c92778 | |||
| 21355e31db | |||
| 97dbd8b63b | |||
| 0df9cc2fc5 | |||
| e2ce3026a0 | |||
| 6a8ade99c7 | |||
| 43fc399cd1 | |||
| 5ae781586f | |||
| 798d7c6d68 | |||
| 368dec7ac7 | |||
| 12dcfd08b8 | |||
| 0e0862cfc7 | |||
| 5b306f0390 | |||
| d88347ee7d | |||
| 7a8516d296 | |||
| c50aba1335 | |||
| 6d9a58bfef | |||
| 071a049f07 | |||
| e019f7e7f2 | |||
| 315c9455d5 | |||
| 97b0c645bf | |||
| 53f46d32e2 | |||
| e9560ef021 | |||
| a44f2c0e65 | |||
| c54b5da403 | |||
| c745f434f5 | |||
| 3fa6f48ac6 | |||
| ce8fe645f4 | |||
| 79eaf49ec0 | |||
| 9950d8a319 | |||
| 4928e2bf0a | |||
| a570d0a129 | |||
| 918b4e81d2 | |||
| dd96d0ac93 | |||
| 106a617fa8 | |||
| 3817b4e1c5 | |||
| 2ba461e348 | |||
| 5352e2caa0 | |||
| 463930761b | |||
| 980f955f6c | |||
| f69829f7b4 | |||
| c3fd757b03 | |||
| 343288c1f6 | |||
| 355b46e6c5 | |||
| 366b90be1a | |||
| 77a8f103d8 | |||
| 4250725a60 | |||
| b151904316 | |||
| 558afefc04 | |||
| 21eabd3938 | |||
| 0c090a8c8b | |||
| 926d2beddb | |||
| 98bdd36231 | |||
| 8e870d4cc0 | |||
| afb5449ca4 | |||
| 5a74b5008d | |||
| 72ac5badb0 | |||
| 3af0c47c97 | |||
| a46c95c7f2 | |||
| 6801478a13 | |||
| ef5a21496c | |||
| 67a55efa27 | |||
| c5694b3013 | |||
| 466347a335 | |||
| 9cfaf0944c | |||
| bfd564f257 | |||
| 43c1910453 | |||
| 260dbf0a1d | |||
| f3e20ca437 | |||
| a2867ff6ea | |||
| 9689f7b925 | |||
| 2037b5ce39 | |||
| f4c5e6568e | |||
| 865bf67b1a | |||
| f474b6da85 | |||
| a578bc2fad | |||
| 5a11d19940 | |||
| c28778e28c | |||
| c873327fe3 | |||
| d25b427efe | |||
| 9cd378caa7 | |||
| b0258803c6 | |||
| 77eb94409c | |||
| 0735250eb1 | |||
| fa21cd13d2 | |||
| d74fffd5de | |||
| e7722af9a2 | |||
| 0cd409bd6d | |||
| 2ea7f9769a | |||
| 221451b817 | |||
| 48a795c101 | |||
| f29c963030 | |||
| dd81707992 | |||
| ec410fb6fe | |||
| 3edaa5280d | |||
| 51e415a026 | |||
| 04f559e28d | |||
| ecda05af29 | |||
| 4661315192 | |||
| 0f488ac286 | |||
| e649708cb2 | |||
| f656d95339 | |||
| 6eae8f22dc | |||
| 21eeaffc23 | |||
| 831426ca63 | |||
| 58ceab5f1e | |||
| 766a9dc9fd | |||
| 0e8ba24f32 | |||
| 744cee6ec9 | |||
| 32eb50b75e | |||
| 887e58bd21 | |||
| 11a2413476 | |||
| be4eb6fb2b | |||
| 9e56099edd | |||
| d92bb41e25 | |||
| 69e351b44a | |||
| ce161c2c02 | |||
| f383f7721c | |||
| 1252016b9c | |||
| 1b17a5293c | |||
| 3e4752f99e | |||
| f44307da4e | |||
| fd127d59fa | |||
| 29b72c59f3 | |||
| 11376a2dd0 | |||
| cc9168bda1 | |||
| f4d0c83181 | |||
| 096efdf798 | |||
| 20735bf840 | |||
| e3c3e780ae | |||
| 9190cf8796 | |||
| d19a21bd01 | |||
| 94b8486d4b | |||
| cce430fbfa | |||
| 5b8051581e | |||
| 0e8d129efb | |||
| 62012e3c68 | |||
| b8c71e7f2d | |||
| ac83639631 | |||
| fef21361c5 | |||
| 368fa9475d | |||
| a90ee65f7b | |||
| e83be1d73a | |||
| e8c3e54dda | |||
| 2aee114950 | |||
| 4d322a97e1 | |||
| 8210f89b12 | |||
| a28baabefe | |||
| e94d16667b | |||
| c3db1cae3f | |||
| 017162e3fd | |||
| fef25ea934 | |||
| a9282bad29 | |||
| 67931bdeb2 | |||
| 85f867983f | |||
| ec17161651 | |||
| 3d4bd9667a | |||
| 7420814fe2 | |||
| 8d6f265441 | |||
| bc8b0480e9 | |||
| 046d281abc | |||
| efc6b35615 | |||
| bf747e32b4 | |||
| ef15735161 | |||
| 99c65bb67c | |||
| 967e837c73 | |||
| ca084d40c1 | |||
| 238ebb600d | |||
| a49601ba87 | |||
| aa10ec6e45 | |||
| be935debe9 | |||
| 1c8a74b661 | |||
| 73ddbc3acd | |||
| 7f9840cecf | |||
| cc3036860a | |||
| 2af40c3fe6 | |||
| ea1958a948 | |||
| 9d42e146e7 | |||
| c156b50e4c | |||
| 3752d68e7d | |||
| cb860e8150 | |||
| 434238fcd4 | |||
| 2d10547266 | |||
| f9a21281c4 | |||
| d590eb074f | |||
| 66ff4aae89 | |||
| 450d0d69af | |||
| 28889954ef | |||
| f0a55df963 | |||
| 40fff219b5 | |||
| 2ed818bc03 | |||
| 9017eaee08 | |||
| 38aae024cd | |||
| 1fc11c27e7 | |||
| c4a8930909 | |||
| a280c97321 | |||
| dfd1c85916 | |||
| fc86d741db | |||
| ca38af0d83 | |||
| f7584bf14c | |||
| 0090ce3df7 | |||
| 433db8f9f9 | |||
| 7e9e321c38 | |||
| 6ac1ed18ea | |||
| 54930ddd33 | |||
| 3e59b7345c | |||
| 838c4e938c | |||
| f79a52fe9b | |||
| 2eb1657d91 | |||
| e6a32db7b9 | |||
| acce7ec9cf | |||
| fbb2d5e10d | |||
| f86edf8d3c | |||
| 08ba147241 | |||
| 2b6a139526 | |||
| 9f60cd18e3 | |||
| ac7b3e405c | |||
| bb3cb8f233 | |||
| e745b0dd47 | |||
| f17d60da64 | |||
| afb6e485b7 | |||
| ccfd6dde45 | |||
| 706868dad8 | |||
| 3b3a1390ad | |||
| fafe1732b5 | |||
| 5ff7d9505f | |||
| 2e6a110181 | |||
| 1592b40e25 | |||
| 9cd0c101f0 | |||
| 3d62c9ed9d | |||
| 53fafad915 | |||
| 999f3556fd | |||
| 4f5731ac39 | |||
| 4aafdea5a7 | |||
| c18d3aecbc | |||
| f1c536fe13 | |||
| ad9233e620 | |||
| f88a609000 | |||
| 80ba9944e5 | |||
| 0f12be7549 | |||
| b581799c9a | |||
| 067d1d6935 | |||
| ada1fdc14d | |||
| c98d09f15d | |||
| a6676e6bc2 | |||
| 51e59f4873 | |||
| 74ed35792f | |||
| 25914d381a | |||
| fcdef1d0a0 | |||
| 1d3240ff9c | |||
| 7c3706763a | |||
| 8bdb105897 | |||
| d3775b973e | |||
| e77a76a284 | |||
| 00b91a07cb | |||
| 52e47b5a53 | |||
| 7be62631ae | |||
| d2686c8413 | |||
| cba652e4f3 | |||
| 370cd14b46 | |||
| d3e288cc4d | |||
| 06a6629eef | |||
| a19490c291 | |||
| d4eb88b255 | |||
| c844fea9df | |||
| 923568a279 | |||
| 2c32503b10 | |||
| fe0317aee5 | |||
| 751be1ae8c | |||
| f48b63de38 | |||
| 3beb200c68 | |||
| d43b743ff4 | |||
| 70423af38c | |||
| f7006f64fb | |||
| 6431c26e8b | |||
| 04d05fbdc2 | |||
| 614debd13f | |||
| 2060de5ed0 | |||
| d5e00e6b0f | |||
| 52d801bd19 | |||
| ac09592355 | |||
| fb418b26d7 | |||
| 4888d7d410 | |||
| 89bc316a7a | |||
| c1b1e0aab1 | |||
| 2bea621f7d | |||
| 868f248696 | |||
| 30111efc6d | |||
| a28236d939 | |||
| 6fd4a87881 | |||
| 9c5b994369 | |||
| 9befef1b03 | |||
| 0ff22e4a49 | |||
| 18b6ba0af4 | |||
| 9f14ac291f | |||
| 65d4652e92 | |||
| 613868b893 | |||
| 73abf8a800 | |||
| 3bb5c459d6 | |||
| 145ea03ca2 | |||
| 49f429018e | |||
| 66149a29da | |||
| 0ee8159f6c | |||
| e81f4b29db | |||
| 1b82546b90 | |||
| e250c226ca | |||
| d67a0259cf | |||
| 7f2e4d8ace | |||
| 6f313ff245 | |||
| a991c01731 | |||
| b5aae7e901 | |||
| 5b7d6ed8b9 | |||
| 38856886e6 | |||
| f2ba78e04b | |||
| ae32d968b9 | |||
| df5dcf5162 | |||
| 76801973e1 | |||
| b6b8ff591d | |||
| 9a781cef53 | |||
| aaccfd8201 | |||
| 4bccb3dc9f | |||
| d8c278bf52 | |||
| 407385dc72 |
+2
-1
@@ -4,6 +4,7 @@ branches:
|
||||
- master
|
||||
skip_tags: true
|
||||
environment:
|
||||
CFLAGS: /WX
|
||||
matrix:
|
||||
- BUILD_SHARED_LIBS: ON
|
||||
- BUILD_SHARED_LIBS: OFF
|
||||
@@ -12,7 +13,7 @@ matrix:
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
||||
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% ..
|
||||
- cmake --build .
|
||||
notifications:
|
||||
- provider: Email
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
*.m linguist-language=Objective-C
|
||||
+330
-45
@@ -1,35 +1,139 @@
|
||||
# Contribution Guide
|
||||
|
||||
This file is a work in progress and you can report errors or submit patches for
|
||||
it the same as any other file.
|
||||
## Contents
|
||||
|
||||
- [Asking a question](#asking-a-question)
|
||||
- [Reporting a bug](#reporting-a-bug)
|
||||
- [Reporting a compile or link bug](#reporting-a-compile-or-link-bug)
|
||||
- [Reporting a segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
|
||||
- [Reporting a context creation bug](#reporting-a-context-creation-bug)
|
||||
- [Reporting a monitor or video mode bug](#reporting-a-monitor-or-video-mode-bug)
|
||||
- [Reporting a window, input or event bug](#reporting-a-window-input-or-event-bug)
|
||||
- [Reporting some other library bug](#reporting-some-other-library-bug)
|
||||
- [Reporting a documentation bug](#reporting-a-documentation-bug)
|
||||
- [Reporting a website bug](#reporting-a-website-bug)
|
||||
- [Requesting a feature](#requesting-a-feature)
|
||||
- [Contributing a bug fix](#contributing-a-bug-fix)
|
||||
- [Contributing a feature](#contributing-a-feature)
|
||||
|
||||
|
||||
## Asking a question
|
||||
|
||||
Questions about how to use GLFW should be asked either in the [support
|
||||
section](http://discourse.glfw.org/c/support) of the forum, under the [Stack
|
||||
Overflow tag](https://stackoverflow.com/questions/tagged/glfw) or [Game
|
||||
Development tag](https://gamedev.stackexchange.com/questions/tagged/glfw) on
|
||||
Stack Exchange or in the IRC channel `#glfw` on
|
||||
[Freenode](http://freenode.net/).
|
||||
|
||||
Questions about the design or implementation of GLFW or about future plans
|
||||
should be asked in the [dev section](http://discourse.glfw.org/c/dev) of the
|
||||
forum or in the IRC channel. Please don't open a GitHub issue to discuss design
|
||||
questions without first checking with a maintainer.
|
||||
|
||||
|
||||
## Reporting a bug
|
||||
|
||||
If GLFW is behaving unexpectedly, make sure you have set an error callback.
|
||||
GLFW will often tell you the cause of an issue via this callback.
|
||||
If GLFW is behaving unexpectedly at run-time, start by setting an [error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling).
|
||||
GLFW will often tell you the cause of an error via this callback. If it
|
||||
doesn't, that might be a separate bug.
|
||||
|
||||
If GLFW is crashing or triggering asserts, make sure that all your object
|
||||
handles and other pointers are valid.
|
||||
|
||||
Always include the __operating system name and version__ (i.e. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (i.e. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (i.e. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
If possible, please also include the __GLFW version string__ (`3.2.0 X11 EGL
|
||||
clock_gettime /dev/js XI Xf86vm`), as described
|
||||
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string).
|
||||
For bugs where it makes sense, a short, self contained example is absolutely
|
||||
invaluable. Just put it inline in the body text. Note that if the bug is
|
||||
reproducible with one of the test programs that come with GLFW, just mention
|
||||
that instead.
|
||||
|
||||
__Don't worry about adding too much information__. Unimportant information can
|
||||
be abbreviated or removed later, but missing information can stall bug fixing,
|
||||
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
|
||||
need to mention these in the subject line. If you do, it will be removed when
|
||||
the issue is labeled.
|
||||
|
||||
If your bug is already reported, please add any new information you have, or if
|
||||
it already has everything, give it a :+1:.
|
||||
|
||||
|
||||
### Reporting a compile or link bug
|
||||
|
||||
__Note:__ GLFW needs many system APIs to do its job. See the [Building
|
||||
applications](http://www.glfw.org/docs/latest/build.html) guide for more
|
||||
information.
|
||||
__Note:__ GLFW needs many system APIs to do its job, which on some platforms
|
||||
means linking to many system libraries. If you are using GLFW as a static
|
||||
library, that means your application needs to link to these in addition to GLFW.
|
||||
|
||||
In addition to the information above, always include the complete build log from
|
||||
your compiler and linker. Issue posts are editable so it can always be
|
||||
shortened later.
|
||||
__Note:__ Check the [Compiling
|
||||
GLFW](http://www.glfw.org/docs/latest/compile.html) guide and or [Building
|
||||
applications](http://www.glfw.org/docs/latest/build.html) guide for before
|
||||
opening an issue of this kind. Most issues are caused by a missing package or
|
||||
linker flag.
|
||||
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`) and the __compiler name and version__ (e.g. `Visual
|
||||
C++ 2015 Update 2`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
Please also include the __complete build log__ from your compiler and linker,
|
||||
even if it's long. It can always be shortened later, if necessary.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
```
|
||||
OS and version:
|
||||
Compiler version:
|
||||
Release or commit:
|
||||
Build log:
|
||||
```
|
||||
|
||||
|
||||
### Reporting a segfault or other crash bug
|
||||
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
Please also include any __error messages__ provided to your application via the
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||
the __full call stack__ of the crash, or if the crash does not occur in debug
|
||||
mode, mention that instead.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
```
|
||||
OS and version:
|
||||
Release or commit:
|
||||
Error messages:
|
||||
Call stack:
|
||||
```
|
||||
|
||||
|
||||
### Reporting a context creation bug
|
||||
@@ -38,23 +142,45 @@ __Note:__ Windows ships with graphics drivers that do not support OpenGL. If
|
||||
GLFW says that your machine lacks support for OpenGL, it very likely does.
|
||||
Install drivers from the computer manufacturer or graphics card manufacturer
|
||||
([Nvidia](http://www.geforce.com/drivers),
|
||||
[AMD](http://support.amd.com/en-us/download),
|
||||
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
|
||||
[AMD](http://support.amd.com/en-us/download),
|
||||
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
|
||||
fix this.
|
||||
|
||||
__Note:__ AMD only supports OpenGL ES on Windows via EGL. EGL support is not
|
||||
enabled in GLFW by default. You need to [enable EGL when
|
||||
compiling](http://www.glfw.org/docs/latest/compile.html) GLFW to use this.
|
||||
__Note:__ AMD only supports OpenGL ES on Windows via EGL. See the
|
||||
[GLFW\_CONTEXT\_CREATION\_API](http://www.glfw.org/docs/latest/window_guide.html#window_hints_ctx)
|
||||
hint for how to select EGL.
|
||||
|
||||
The `glfwinfo` tool is included in the GLFW source tree as `tests/glfwinfo.c`
|
||||
and is built along with the library. It lets you request any kind of context
|
||||
and framebuffer format supported by the GLFW API without having to recompile.
|
||||
If context creation fails in your application, please verify that it also fails
|
||||
with this tool before reporting it as a bug.
|
||||
Please verify that context creation also fails with the `glfwinfo` tool before
|
||||
reporting it as a bug. This tool is included in the GLFW source tree as
|
||||
`tests/glfwinfo.c` and is built along with the library. It has switches for all
|
||||
GLFW context and framebuffer hints. Run `glfwinfo -h` for a complete list.
|
||||
|
||||
In addition to the information above (OS and GLFW version), always include the
|
||||
__GPU model and driver version__ (i.e. `GeForce GTX660 with 352.79`) when
|
||||
reporting this kind of bug.
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__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
|
||||
/dev/js`), as described
|
||||
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
|
||||
__GPU model and driver version__ (e.g. `GeForce GTX660 with 352.79`), and the
|
||||
__output of `glfwinfo`__ (with switches matching any hints you set in your
|
||||
code) when reporting this kind of bug. If this tool doesn't run on the machine,
|
||||
mention that instead.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
```
|
||||
OS and version:
|
||||
GPU and driver:
|
||||
Release or commit:
|
||||
Version string:
|
||||
glfwinfo output:
|
||||
```
|
||||
|
||||
|
||||
### Reporting a monitor or video mode bug
|
||||
@@ -63,23 +189,47 @@ __Note:__ On headless systems on some platforms, no monitors are reported. This
|
||||
causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are
|
||||
prepared for.
|
||||
|
||||
__Note:__ Some third-party tools report more video modes than those approved of
|
||||
by the OS. For safety and compatbility, GLFW only reports video modes the OS
|
||||
__Note:__ Some third-party tools report more video modes than are approved of
|
||||
by the OS. For safety and compatibility, GLFW only reports video modes the OS
|
||||
wants programs to use. This is not a bug.
|
||||
|
||||
The `monitors` tool is included in the GLFW source tree as `tests/monitors.c`
|
||||
and is built along with the library. lists all information about connected
|
||||
monitors made available by GLFW.
|
||||
and is built along with the library. It lists all information GLFW provides
|
||||
about monitors it detects.
|
||||
|
||||
In addition to the information above (OS and GLFW version), please also include
|
||||
the output of the `monitors` tool when reporting this kind of bug. If it
|
||||
doesn't work at all, please mention this.
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__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
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||
the __output of `monitors`__ when reporting this kind of bug. If this tool
|
||||
doesn't run on the machine, mention this instead.
|
||||
|
||||
|
||||
### Reporting a window event bug
|
||||
#### Quick template
|
||||
|
||||
__Note:__ While GLFW tries to provide the exact same behavior between platforms,
|
||||
the exact ordering of related window events will sometimes differ.
|
||||
```
|
||||
OS and version:
|
||||
Release or commit:
|
||||
Error messages:
|
||||
monitors output:
|
||||
```
|
||||
|
||||
|
||||
### Reporting a window, input or event bug
|
||||
|
||||
__Note:__ The exact ordering of related window events will sometimes differ.
|
||||
|
||||
__Note:__ Window moving and resizing (by the user) will block the main thread on
|
||||
some platforms. This is not a bug. Set a [refresh
|
||||
callback](http://www.glfw.org/docs/latest/window.html#window_refresh) if you
|
||||
want to keep the window contents updated during a move or size operation.
|
||||
|
||||
The `events` tool is included in the GLFW source tree as `tests/events.c` and is
|
||||
built along with the library. It prints all information provided to every
|
||||
@@ -87,20 +237,155 @@ callback supported by GLFW as events occur. Each event is listed with the time
|
||||
and a unique number to make discussions about event logs easier. The tool has
|
||||
command-line options for creating multiple windows and full screen windows.
|
||||
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__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
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
|
||||
if relevant, the __output of `events`__ when reporting this kind of bug. If
|
||||
this tool doesn't run on the machine, mention this instead.
|
||||
|
||||
__X11:__ If possible, please include what desktop environment (e.g. GNOME,
|
||||
Unity, KDE) and/or window manager (e.g. Openbox, dwm, Window Maker) you are
|
||||
running. If the bug is related to keyboard input, please include any input
|
||||
method (e.g. ibus, SCIM) you are using.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
```
|
||||
OS and version:
|
||||
Release or commit:
|
||||
Error messages:
|
||||
events output:
|
||||
```
|
||||
|
||||
|
||||
### Reporting some other library bug
|
||||
|
||||
Always include the __operating system name and version__ (e.g. `Windows
|
||||
7 64-bit` or `Ubuntu 15.10`). If you are using an official release of GLFW,
|
||||
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
|
||||
__GLFW commit ID__ (e.g. `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.
|
||||
|
||||
Please also include any __error messages__ provided to your application via the
|
||||
[error
|
||||
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling), if
|
||||
relevant.
|
||||
|
||||
|
||||
#### Quick template
|
||||
|
||||
```
|
||||
OS and version:
|
||||
Release or commit:
|
||||
Error messages:
|
||||
```
|
||||
|
||||
|
||||
### Reporting a documentation bug
|
||||
|
||||
If you found the error in the generated documentation then it's fine to just
|
||||
link to that webpage. You don't need to figure out which documentation source
|
||||
file the text comes from.
|
||||
If you found a bug in the documentation, including this file, then it's fine to
|
||||
just link to that web page or mention that source file. You don't need to match
|
||||
the source to the output or vice versa.
|
||||
|
||||
|
||||
### Reporting a website bug
|
||||
|
||||
If the bug is in the documentation (anything under `/docs/`) then please see the
|
||||
section above. Bugs in the rest of the site are reported to to the [website
|
||||
source repository](https://github.com/glfw/website/issues).
|
||||
|
||||
|
||||
## Requesting a feature
|
||||
|
||||
Please explain why you need the feature and how you intend to use it. If you
|
||||
have a specific API design in mind, please add that as well. If you have or are
|
||||
planning to write code for the feature, see the section below.
|
||||
|
||||
If there already is a request for the feature you need, add your specific use
|
||||
case unless it is already mentioned. If it is, give it a :+1:.
|
||||
|
||||
|
||||
## Contributing a bug fix
|
||||
|
||||
There should be text here, but there isn't.
|
||||
__Note:__ You must have all necessary [intellectual
|
||||
property rights](https://en.wikipedia.org/wiki/Intellectual_property) to any
|
||||
code you contribute. If you did not write the code yourself, you must explain
|
||||
where it came from and under what license you received it. Even code using the
|
||||
same license as GLFW may not be copied without attribution.
|
||||
|
||||
__There is no preferred patch size__. A one character fix is just as welcome as
|
||||
a thousand line one, if that is the appropriate size for the fix.
|
||||
|
||||
In addition to the code, a complete bug fix includes:
|
||||
|
||||
- Change log entry in `README.md`, describing the incorrect behavior
|
||||
- Credits entries for all authors of the bug fix
|
||||
|
||||
Bug fixes 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
|
||||
other bugs and features to work on.
|
||||
|
||||
If the patch fixes a bug introduced after the last release, it should not get
|
||||
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
|
||||
|
||||
This is not (yet) the text you are looking for.
|
||||
__Note:__ You must have all necessary rights to any code you contribute. If you
|
||||
did not write the code yourself, you must explain where it came from and under
|
||||
what license. Even code using the same license as GLFW may not be copied
|
||||
without attribution.
|
||||
|
||||
__Note:__ If you haven't already implemented the feature, check first if there
|
||||
already is an open issue for it and if it's already being developed in an
|
||||
[experimental branch](https://github.com/glfw/glfw/branches/all).
|
||||
|
||||
__There is no preferred patch size__. A one character change is just as welcome
|
||||
as one adding a thousand line one, if that is the appropriate size for the
|
||||
feature.
|
||||
|
||||
In addition to the code, a complete feature includes:
|
||||
|
||||
- Change log entry in `README.md`, listing all new symbols
|
||||
- News page entry, briefly describing the feature
|
||||
- Guide documentation, with minimal examples, in the relevant guide
|
||||
- Reference documentation, with all applicable tags
|
||||
- Cross-references and mentions in appropriate places
|
||||
- Credits entries for all authors of the feature
|
||||
|
||||
If the feature requires platform-specific code, at minimum stubs must be added
|
||||
for the new platform function to all supported and experimental platforms.
|
||||
|
||||
If it adds a new callback, support for it must be added to `tests/event.c`.
|
||||
|
||||
If it adds a new monitor property, support for it must be added to
|
||||
`tests/monitor.c`.
|
||||
|
||||
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
|
||||
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,
|
||||
but please keep in mind that maintainer time is finite and that there are many
|
||||
other features and bugs to work on.
|
||||
|
||||
Please also keep in mind that any part of the public API that has been included
|
||||
in a release cannot be changed until the next _major_ version. Features can be
|
||||
added and existing parts can sometimes be overloaded (in the general sense of
|
||||
doing more things, not in the C++ sense), but code written to the API of one
|
||||
minor release should both compile and run on subsequent minor releases.
|
||||
|
||||
|
||||
+5
-3
@@ -40,11 +40,11 @@ src/wayland-relative-pointer-unstable-v1-protocol.c
|
||||
# Compiled binaries
|
||||
src/libglfw.so
|
||||
src/libglfw.so.3
|
||||
src/libglfw.so.3.2
|
||||
src/libglfw.so.3.3
|
||||
src/libglfw.dylib
|
||||
src/libglfw.dylib
|
||||
src/libglfw.3.dylib
|
||||
src/libglfw.3.2.dylib
|
||||
src/libglfw.3.3.dylib
|
||||
src/libglfw3.a
|
||||
src/glfw3.lib
|
||||
src/glfw3.dll
|
||||
@@ -55,6 +55,7 @@ examples/*.exe
|
||||
examples/boing
|
||||
examples/gears
|
||||
examples/heightmap
|
||||
examples/offscreen
|
||||
examples/particles
|
||||
examples/splitview
|
||||
examples/simple
|
||||
@@ -67,6 +68,7 @@ tests/empty
|
||||
tests/events
|
||||
tests/gamma
|
||||
tests/glfwinfo
|
||||
tests/icon
|
||||
tests/iconify
|
||||
tests/joysticks
|
||||
tests/monitors
|
||||
@@ -75,8 +77,8 @@ tests/reopen
|
||||
tests/sharing
|
||||
tests/tearing
|
||||
tests/threads
|
||||
tests/timeout
|
||||
tests/title
|
||||
tests/version
|
||||
tests/vulkan
|
||||
tests/windows
|
||||
|
||||
|
||||
+11
-3
@@ -8,19 +8,27 @@ os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: false
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- kubuntu-backports
|
||||
packages:
|
||||
- cmake
|
||||
- libxrandr-dev
|
||||
- libxinerama-dev
|
||||
- libxcursor-dev
|
||||
- libxi-dev
|
||||
env:
|
||||
- BUILD_SHARED_LIBS=ON
|
||||
- BUILD_SHARED_LIBS=OFF
|
||||
global:
|
||||
- CFLAGS=-Werror
|
||||
matrix:
|
||||
- BUILD_SHARED_LIBS=ON
|
||||
- BUILD_SHARED_LIBS=OFF
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} ..
|
||||
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} ..
|
||||
- cmake --build .
|
||||
notifications:
|
||||
email:
|
||||
|
||||
+28
-12
@@ -1,18 +1,34 @@
|
||||
# Try to find Mir on a Unix system
|
||||
# FindMir
|
||||
# -------
|
||||
# Finds the Mir library
|
||||
#
|
||||
# This will define:
|
||||
# This will will define the following variables::
|
||||
#
|
||||
# MIR_LIBRARIES - Link these to use Wayland
|
||||
# MIR_INCLUDE_DIR - Include directory for Wayland
|
||||
#
|
||||
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
# MIR_FOUND - the system has Mir
|
||||
# MIR_INCLUDE_DIRS - the Mir include directory
|
||||
# MIR_LIBRARIES - the Mir libraries
|
||||
# MIR_DEFINITIONS - the Mir definitions
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
find_package (PkgConfig)
|
||||
pkg_check_modules (PKG_MIR QUIET mirclient)
|
||||
find_package (PkgConfig)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules (PC_MIR mirclient>=0.26.2 QUIET)
|
||||
|
||||
set (MIR_INCLUDE_DIR ${PKG_MIR_INCLUDE_DIRS})
|
||||
set (MIR_LIBRARIES ${PKG_MIR_LIBRARIES})
|
||||
find_path(MIR_INCLUDE_DIR NAMES mir_toolkit/mir_client_library.h
|
||||
PATHS ${PC_MIR_INCLUDE_DIRS})
|
||||
|
||||
endif ()
|
||||
find_library(MIR_LIBRARY NAMES mirclient
|
||||
PATHS ${PC_MIR_LIBRARIES} ${PC_MIR_LIBRARY_DIRS})
|
||||
|
||||
include (FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args (MIR
|
||||
REQUIRED_VARS MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
|
||||
if (MIR_FOUND)
|
||||
set(MIR_LIBRARIES ${MIR_LIBRARY})
|
||||
set(MIR_INCLUDE_DIRS ${PC_MIR_INCLUDE_DIRS})
|
||||
set(MIR_DEFINITIONS -DHAVE_MIR=1)
|
||||
endif()
|
||||
|
||||
mark_as_advanced (MIR_LIBRARY MIR_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Try to find OSMesa on a Unix system
|
||||
#
|
||||
# This will define:
|
||||
#
|
||||
# OSMESA_LIBRARIES - Link these to use OSMesa
|
||||
# OSMESA_INCLUDE_DIR - Include directory for OSMesa
|
||||
#
|
||||
# Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
|
||||
if (NOT WIN32)
|
||||
|
||||
find_package (PkgConfig)
|
||||
pkg_check_modules (PKG_OSMESA QUIET osmesa)
|
||||
|
||||
set (OSMESA_INCLUDE_DIR ${PKG_OSMESA_INCLUDE_DIRS})
|
||||
set (OSMESA_LIBRARIES ${PKG_OSMESA_LIBRARIES})
|
||||
|
||||
endif ()
|
||||
@@ -8,15 +8,32 @@ if (WIN32)
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/Include"
|
||||
"$ENV{VK_SDK_PATH}/Include")
|
||||
if (CMAKE_CL_64)
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib"
|
||||
"$ENV{VULKAN_SDK}/Bin"
|
||||
"$ENV{VK_SDK_PATH}/Bin")
|
||||
else()
|
||||
find_library(VULKAN_LIBRARY NAMES vulkan-1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
find_library(VULKAN_STATIC_LIBRARY NAMES vkstatic.1 HINTS
|
||||
"$ENV{VULKAN_SDK}/Lib32"
|
||||
"$ENV{VULKAN_SDK}/Bin32"
|
||||
"$ENV{VK_SDK_PATH}/Bin32")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||
find_library(VULKAN_LIBRARY MoltenVK)
|
||||
set(CMAKE_FIND_FRAMEWORK ONLY)
|
||||
find_library(VULKAN_STATIC_LIBRARY MoltenVK)
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"${VULKAN_LIBRARY}/Headers")
|
||||
else()
|
||||
find_path(VULKAN_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS
|
||||
"$ENV{VULKAN_SDK}/include")
|
||||
@@ -27,5 +44,5 @@ endif()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Vulkan DEFAULT_MSG VULKAN_LIBRARY VULKAN_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY)
|
||||
mark_as_advanced(VULKAN_INCLUDE_DIR VULKAN_LIBRARY VULKAN_STATIC_LIBRARY)
|
||||
|
||||
|
||||
+82
-63
@@ -1,8 +1,8 @@
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
project(GLFW C)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
# Until all major package systems have moved to CMake 3,
|
||||
@@ -10,8 +10,12 @@ if (NOT CMAKE_VERSION VERSION_LESS "3.0")
|
||||
cmake_policy(SET CMP0042 OLD)
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_VERSION VERSION_LESS "3.1")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
set(GLFW_VERSION_MAJOR "3")
|
||||
set(GLFW_VERSION_MINOR "2")
|
||||
set(GLFW_VERSION_MINOR "3")
|
||||
set(GLFW_VERSION_PATCH "0")
|
||||
set(GLFW_VERSION_EXTRA "")
|
||||
set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
|
||||
@@ -25,18 +29,17 @@ option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON)
|
||||
option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
|
||||
option(GLFW_BUILD_DOCS "Build the GLFW documentation" ON)
|
||||
option(GLFW_INSTALL "Generate installation target" ON)
|
||||
option(GLFW_VULKAN_STATIC "Use the Vulkan loader statically linked into application" OFF)
|
||||
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
|
||||
|
||||
if (UNIX)
|
||||
option(GLFW_USE_OSMESA "Use OSMesa for offscreen context creation" OFF)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
option(GLFW_USE_HYBRID_HPG "Force use of high-performance GPU on hybrid systems" OFF)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
option(GLFW_USE_CHDIR "Make glfwInit chdir to Contents/Resources" ON)
|
||||
option(GLFW_USE_MENUBAR "Populate the menu bar on first window creation" ON)
|
||||
option(GLFW_USE_RETINA "Use the full resolution of Retina displays" ON)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
|
||||
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
|
||||
@@ -57,7 +60,11 @@ else()
|
||||
set(GLFW_LIB_NAME glfw3)
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||
if (GLFW_VULKAN_STATIC)
|
||||
set(_GLFW_VULKAN_STATIC 1)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(Vulkan)
|
||||
@@ -71,6 +78,17 @@ endif()
|
||||
# Set compiler specific flags
|
||||
#--------------------------------------------------------------------
|
||||
if (MSVC)
|
||||
if (MSVC90)
|
||||
# Workaround for VS 2008 not shipping with the DirectX 9 SDK
|
||||
include(CheckIncludeFile)
|
||||
check_include_file(dinput.h DINPUT_H_FOUND)
|
||||
if (NOT DINPUT_H_FOUND)
|
||||
message(FATAL_ERROR "DirectX 9 SDK not found")
|
||||
endif()
|
||||
# Workaround for VS 2008 not shipping with stdint.h
|
||||
list(APPEND glfw_INCLUDE_DIRS "${GLFW_SOURCE_DIR}/deps/vs2008")
|
||||
endif()
|
||||
|
||||
if (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
|
||||
foreach (flag CMAKE_C_FLAGS
|
||||
CMAKE_C_FLAGS_DEBUG
|
||||
@@ -124,30 +142,58 @@ if (MINGW)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# Dependencies required by the MoltenVK static library
|
||||
set(GLFW_VULKAN_DEPS
|
||||
"-lc++"
|
||||
"-framework Cocoa"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Detect and select backend APIs
|
||||
#--------------------------------------------------------------------
|
||||
if (WIN32)
|
||||
if (GLFW_USE_WAYLAND)
|
||||
set(_GLFW_WAYLAND 1)
|
||||
message(STATUS "Using Wayland for window creation")
|
||||
elseif (GLFW_USE_MIR)
|
||||
set(_GLFW_MIR 1)
|
||||
message(STATUS "Using Mir for window creation")
|
||||
elseif (GLFW_USE_OSMESA)
|
||||
set(_GLFW_OSMESA 1)
|
||||
message(STATUS "Using OSMesa for headless context creation")
|
||||
elseif (WIN32)
|
||||
set(_GLFW_WIN32 1)
|
||||
message(STATUS "Using Win32 for window creation")
|
||||
elseif (APPLE)
|
||||
set(_GLFW_COCOA 1)
|
||||
message(STATUS "Using Cocoa for window creation")
|
||||
elseif (UNIX)
|
||||
if (GLFW_USE_WAYLAND)
|
||||
set(_GLFW_WAYLAND 1)
|
||||
message(STATUS "Using Wayland for window creation")
|
||||
elseif (GLFW_USE_MIR)
|
||||
set(_GLFW_MIR 1)
|
||||
message(STATUS "Using Mir for window creation")
|
||||
else()
|
||||
set(_GLFW_X11 1)
|
||||
message(STATUS "Using X11 for window creation")
|
||||
endif()
|
||||
set(_GLFW_X11 1)
|
||||
message(STATUS "Using X11 for window creation")
|
||||
else()
|
||||
message(FATAL_ERROR "No supported platform was detected")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Add Vulkan static library if requested
|
||||
#--------------------------------------------------------------------
|
||||
if (GLFW_VULKAN_STATIC)
|
||||
if (VULKAN_FOUND AND VULKAN_STATIC_LIBRARY)
|
||||
list(APPEND glfw_LIBRARIES ${VULKAN_STATIC_LIBRARY} ${GLFW_VULKAN_DEPS})
|
||||
if (BUILD_SHARED_LIBS)
|
||||
message(WARNING "Linking Vulkan loader static library into GLFW")
|
||||
endif()
|
||||
else()
|
||||
if (BUILD_SHARED_LIBS OR GLFW_BUILD_EXAMPLES OR GLFW_BUILD_TESTS)
|
||||
message(FATAL_ERROR "Vulkan loader static library not found")
|
||||
else()
|
||||
message(WARNING "Vulkan loader static library not found")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Find and add Unix math and time libraries
|
||||
#--------------------------------------------------------------------
|
||||
@@ -215,21 +261,6 @@ if (_GLFW_X11)
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xinerama_LIB}")
|
||||
list(APPEND glfw_PKG_DEPS "xinerama")
|
||||
|
||||
# Check for Xf86VidMode (fallback gamma control)
|
||||
if (X11_xf86vmode_FOUND)
|
||||
list(APPEND glfw_INCLUDE_DIRS "${X11_xf86vmode_INCLUDE_PATH}")
|
||||
list(APPEND glfw_PKG_DEPS "xxf86vm")
|
||||
|
||||
if (X11_Xxf86vm_LIB)
|
||||
list(APPEND glfw_LIBRARIES "${X11_Xxf86vm_LIB}")
|
||||
else()
|
||||
# Backwards compatibility (see CMake bug 0006976)
|
||||
list(APPEND glfw_LIBRARIES Xxf86vm)
|
||||
endif()
|
||||
|
||||
set(_GLFW_HAS_XF86VM TRUE)
|
||||
endif()
|
||||
|
||||
# Check for Xkb (X keyboard extension)
|
||||
if (NOT X11_Xkb_FOUND)
|
||||
message(FATAL_ERROR "The X keyboard extension headers were not found")
|
||||
@@ -253,7 +284,7 @@ endif()
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_WAYLAND)
|
||||
find_package(ECM REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
|
||||
list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
|
||||
|
||||
find_package(Wayland REQUIRED)
|
||||
find_package(WaylandScanner REQUIRED)
|
||||
@@ -277,7 +308,7 @@ if (_GLFW_MIR)
|
||||
find_package(Mir REQUIRED)
|
||||
list(APPEND glfw_PKG_DEPS "mirclient")
|
||||
|
||||
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIR}")
|
||||
list(APPEND glfw_INCLUDE_DIRS "${MIR_INCLUDE_DIRS}")
|
||||
list(APPEND glfw_LIBRARIES "${MIR_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
find_package(XKBCommon REQUIRED)
|
||||
@@ -286,36 +317,24 @@ if (_GLFW_MIR)
|
||||
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use OSMesa for offscreen context creation
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_OSMESA)
|
||||
find_package(OSMesa REQUIRED)
|
||||
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif()
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Use Cocoa for window creation and NSOpenGL for context creation
|
||||
#--------------------------------------------------------------------
|
||||
if (_GLFW_COCOA)
|
||||
|
||||
if (GLFW_USE_MENUBAR)
|
||||
set(_GLFW_USE_MENUBAR 1)
|
||||
endif()
|
||||
|
||||
if (GLFW_USE_CHDIR)
|
||||
set(_GLFW_USE_CHDIR 1)
|
||||
endif()
|
||||
|
||||
if (GLFW_USE_RETINA)
|
||||
set(_GLFW_USE_RETINA 1)
|
||||
endif()
|
||||
|
||||
# Set up library and include paths
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
find_library(IOKIT_FRAMEWORK IOKit)
|
||||
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation)
|
||||
find_library(CORE_VIDEO_FRAMEWORK CoreVideo)
|
||||
mark_as_advanced(COCOA_FRAMEWORK
|
||||
IOKIT_FRAMEWORK
|
||||
CORE_FOUNDATION_FRAMEWORK
|
||||
CORE_VIDEO_FRAMEWORK)
|
||||
list(APPEND glfw_LIBRARIES "${COCOA_FRAMEWORK}"
|
||||
"${IOKIT_FRAMEWORK}"
|
||||
"${CORE_FOUNDATION_FRAMEWORK}"
|
||||
"${CORE_VIDEO_FRAMEWORK}")
|
||||
list(APPEND glfw_LIBRARIES
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework CoreFoundation"
|
||||
"-framework CoreVideo")
|
||||
|
||||
set(glfw_PKG_DEPS "")
|
||||
set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Copyright (c) 2002-2006 Marcus Geelnard
|
||||
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
Copyright (c) 2002-2006 Marcus Geelnard
|
||||
Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -2,63 +2,94 @@
|
||||
|
||||
[](https://travis-ci.org/glfw/glfw)
|
||||
[](https://ci.appveyor.com/project/elmindreda/glfw)
|
||||
[](https://scan.coverity.com/projects/glfw-glfw)
|
||||
|
||||
## Introduction
|
||||
|
||||
GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan
|
||||
application development. It provides a simple, platform-independent API for
|
||||
creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
Version 3.2 adds support for Vulkan surface creation, window mode switching,
|
||||
window maximization, window input focus control, window size and aspect ratio
|
||||
limits, human-readable key names, window icons, joystick connection events,
|
||||
XInput and DirectInput joystick input, event waiting with timeout, 64-bit
|
||||
integer raw timer, context-less window creation, error-less contexts via
|
||||
`GL_KHR_no_error` (where available), run-time context creation API selection,
|
||||
Windows 8.1 per-monitor DPI and the CMake config-file package system, adds
|
||||
simpler build-time configuration, improved documentation and fixes for a large
|
||||
number of bugs that together affect all supported platforms.
|
||||
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
|
||||
Experimental implementations for the Wayland protocol and the Mir display server
|
||||
are available but not yet officially supported.
|
||||
|
||||
GLFW is licensed under the [zlib/libpng
|
||||
license](http://www.glfw.org/license.html).
|
||||
|
||||
The latest stable release is version 3.2.1.
|
||||
|
||||
See the [downloads](http://www.glfw.org/download.html) page for details and
|
||||
files, or fetch the `latest` branch, which always points to the latest stable
|
||||
release. Each release starting with 3.0 also has a corresponding [annotated
|
||||
tag](https://github.com/glfw/glfw/releases) with source and binary archives.
|
||||
The [version history](http://www.glfw.org/changelog.html) lists all user-visible
|
||||
changes for every release.
|
||||
|
||||
This is a development branch for version 3.3, which is _not yet described_.
|
||||
Pre-release documentation is available [here](http://www.glfw.org/docs/3.3/).
|
||||
|
||||
The `master` branch is the stable integration branch and _should_ always compile
|
||||
and run on all supported platforms, although details of newly added features may
|
||||
change until they have been included in a release. New features and many bug
|
||||
fixes live in [other branches](https://github.com/glfw/glfw/branches/all) until
|
||||
they are stable enough to merge.
|
||||
|
||||
If you are new to GLFW, you may find the
|
||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW
|
||||
3 useful. If you have used GLFW 2 in the past, there is a
|
||||
[transition guide](http://www.glfw.org/docs/latest/moving.html) for moving to
|
||||
the GLFW 3 API.
|
||||
[tutorial](http://www.glfw.org/docs/latest/quick.html) for GLFW 3 useful. If
|
||||
you have used GLFW 2 in the past, there is a [transition
|
||||
guide](http://www.glfw.org/docs/latest/moving.html) for moving to the GLFW
|
||||
3 API.
|
||||
|
||||
|
||||
## Compiling GLFW
|
||||
|
||||
See the [Compiling GLFW](http://www.glfw.org/docs/latest/compile.html) guide in
|
||||
the GLFW documentation.
|
||||
GLFW itself requires only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
|
||||
GLFW supports compilation on Windows with Visual C++ 2010 and later, MinGW and
|
||||
MinGW-w64, on macOS with Clang and on Linux and other Unix-like systems with GCC
|
||||
and Clang. It will likely compile in other environments as well, but this is
|
||||
not regularly tested.
|
||||
|
||||
There are [pre-compiled Windows binaries](http://www.glfw.org/download.html)
|
||||
available for all supported compilers.
|
||||
|
||||
See the [compilation guide](http://www.glfw.org/docs/latest/compile.html) for
|
||||
more information about how to compile GLFW yourself.
|
||||
|
||||
|
||||
## Using GLFW
|
||||
|
||||
See the
|
||||
[Building programs that use GLFW](http://www.glfw.org/docs/latest/build.html)
|
||||
guide in the GLFW documentation.
|
||||
See the [documentation](http://www.glfw.org/docs/latest/) for tutorials, guides
|
||||
and the API reference.
|
||||
|
||||
|
||||
## Reporting bugs
|
||||
## Contributing to GLFW
|
||||
|
||||
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
|
||||
Please always include the name and version of the OS where the bug occurs and
|
||||
the version of GLFW used. If you have cloned it, include the commit ID used.
|
||||
See the [contribution
|
||||
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
|
||||
more information.
|
||||
|
||||
If it's a build issue, please also include the build log and the name and
|
||||
version of your development environment.
|
||||
|
||||
If it's a context creation issue, please also include the make and model of your
|
||||
graphics card and the version of your driver.
|
||||
## System requirements
|
||||
|
||||
This will help both us and other people experiencing the same bug.
|
||||
GLFW supports Windows XP and later and macOS 10.7 and later. Linux and other
|
||||
Unix-like systems running the X Window System are supported even without
|
||||
a desktop environment or modern extensions, although some features require
|
||||
a running window or clipboard manager. The OSMesa backend requires Mesa 6.3.
|
||||
|
||||
See the [compatibility guide](http://www.glfw.org/docs/latest/compat.html)
|
||||
in the documentation for more information.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
GLFW itself needs only the headers and libraries for your window system. It
|
||||
does not need the headers for any context creation API (WGL, GLX, EGL, NSGL) or
|
||||
rendering API (OpenGL, OpenGL ES, Vulkan) to enable support for them.
|
||||
GLFW itself depends only on the headers and libraries for your window system.
|
||||
|
||||
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
|
||||
package, which is used to generated Wayland protocol headers.
|
||||
|
||||
The examples and test programs depend on a number of tiny libraries. These are
|
||||
located in the `deps/` directory.
|
||||
@@ -71,100 +102,147 @@ located in the `deps/` directory.
|
||||
[glad](https://github.com/Dav1dde/glad) for examples using modern OpenGL
|
||||
- [linmath.h](https://github.com/datenwolf/linmath.h) for linear algebra in
|
||||
examples
|
||||
- [Nuklear](https://github.com/vurtun/nuklear) for test and example UI
|
||||
- [stb\_image\_write](https://github.com/nothings/stb) for writing images to disk
|
||||
- [Vulkan headers](https://www.khronos.org/registry/vulkan/) for Vulkan tests
|
||||
|
||||
The Vulkan example additionally requires the Vulkan SDK to be installed, or it
|
||||
will not be included in the build.
|
||||
will not be included in the build. On macOS you need to provide the path to the
|
||||
MoltenVK SDK manually as it has no standard installation location.
|
||||
|
||||
The documentation is generated with [Doxygen](http://doxygen.org/). If CMake
|
||||
does not find Doxygen, the documentation will not be generated.
|
||||
The documentation is generated with [Doxygen](http://doxygen.org/) if CMake can
|
||||
find that tool.
|
||||
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
Bugs are reported to our [issue tracker](https://github.com/glfw/glfw/issues).
|
||||
Please check the [contribution
|
||||
guide](https://github.com/glfw/glfw/blob/master/.github/CONTRIBUTING.md) for
|
||||
information on what to include when reporting a bug.
|
||||
|
||||
|
||||
## Changelog
|
||||
|
||||
- Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`,
|
||||
`glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
|
||||
`glfwCreateWindowSurface` for platform independent Vulkan support
|
||||
- Added `glfwSetWindowMonitor` for switching between windowed and full screen
|
||||
modes and updating the monitor and desired video mode of full screen windows
|
||||
- Added `glfwMaximizeWindow` and `GLFW_MAXIMIZED` for window maximization
|
||||
- Added `glfwFocusWindow` for giving windows input focus
|
||||
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
|
||||
absolute and relative window size limits
|
||||
- Added `glfwGetKeyName` for querying the layout-specific name of printable
|
||||
keys
|
||||
- Added `glfwWaitEventsTimeout` for waiting for events for a set amount of time
|
||||
- Added `glfwSetWindowIcon` for setting the icon of a window
|
||||
- Added `glfwGetTimerValue` and `glfwGetTimerFrequency` for raw timer access
|
||||
- Added `glfwSetJoystickCallback` and `GLFWjoystickfun` for joystick connection
|
||||
and disconnection events
|
||||
- Added `GLFW_NO_API` for creating window without contexts
|
||||
- Added `GLFW_INCLUDE_VULKAN` for including the Vulkan header
|
||||
- Added `GLFW_CONTEXT_CREATION_API`, `GLFW_NATIVE_CONTEXT_API` and
|
||||
`GLFW_EGL_CONTEXT_API` for run-time context creation API selection
|
||||
- Added `GLFW_CONTEXT_NO_ERROR` context hint for `GL_KHR_no_error` support
|
||||
- Added `GLFW_TRUE` and `GLFW_FALSE` as client API independent boolean values
|
||||
- Added icons to examples on Windows and OS X
|
||||
- Relaxed rules for native access header macros
|
||||
- Removed dependency on external OpenGL or OpenGL ES headers
|
||||
- Removed `_GLFW_USE_OPENGL`, `_GLFW_USE_GLESV1`, `_GLFW_USE_GLESV2`,
|
||||
`_GLFW_WGL`, `_GLFW_NSGL`, `_GLFW_GLX` and `_GLFW_EGL` configuration macros
|
||||
- [Win32] Added support for Windows 8.1 per-monitor DPI
|
||||
- [Win32] Replaced winmm with XInput and DirectInput for joystick input
|
||||
- [Win32] Bugfix: Window creation would segfault if video mode setting required
|
||||
the system to be restarted
|
||||
- [Win32] Bugfix: MinGW import library lacked the `lib` prefix
|
||||
- [Win32] Bugfix: Monitor connection and disconnection events were not reported
|
||||
when no windows existed
|
||||
- [Win32] Bugfix: Activating or deactivating displays in software did not
|
||||
trigger monitor callback
|
||||
- [Win32] Bugfix: No monitors were listed on headless and VMware guest systems
|
||||
- [Win32] Bugfix: Pressing Ctrl+Pause would report `GLFW_KEY_UNKNOWN`
|
||||
- [Win32] Bugfix: Window size events would be reported in wrong order when
|
||||
restoring a full screen window
|
||||
- [Cocoa] Made joystick polling more efficient
|
||||
- [Cocoa] Removed support for OS X 10.6
|
||||
- [Cocoa] Bugfix: Full screen windows on secondary monitors were mispositioned
|
||||
- [Cocoa] Bugfix: Connecting a joystick that reports no name would segfault
|
||||
- [Cocoa] Bugfix: Modifier flags cache was not updated when window became key
|
||||
- [Cocoa] Bugfix: Dead key character composition did not work
|
||||
- [Cocoa] Bugfix: The CGL context was not released until the autorelease pool
|
||||
was drained by another function
|
||||
- [X11] Bugfix: Monitor connection and disconnection events were not reported
|
||||
- [X11] Bugfix: Decoding of UTF-8 text from XIM could continue past the end
|
||||
- [X11] Bugfix: An XKB structure was leaked during `glfwInit`
|
||||
- [X11] Bugfix: XInput2 `XI_Motion` events interfered with the Steam overlay
|
||||
- [POSIX] Bugfix: An unrelated TLS key could be deleted by `glfwTerminate`
|
||||
- [Linux] Made joystick polling more efficient
|
||||
- [WGL] Changed extension loading to only be performed once
|
||||
- [WGL] Removed dependency on external WGL headers
|
||||
- [GLX] Added `glfwGetGLXWindow` to query the `GLXWindow` of a window
|
||||
- [GLX] Replaced legacy drawable with `GLXWindow`
|
||||
- [GLX] Removed dependency on external GLX headers
|
||||
- [GLX] Bugfix: NetBSD does not provide `libGL.so.1`
|
||||
- [EGL] Added `_GLFW_USE_EGLPLATFORM_H` configuration macro for controlling
|
||||
whether to use an existing `EGL/eglplatform.h` header
|
||||
- [EGL] Added and documented test for if the context is current on the calling
|
||||
thread during buffer swap
|
||||
- [EGL] Removed dependency on external EGL headers
|
||||
- Added `glfwGetError` function for querying the last error code and its
|
||||
description (#970)
|
||||
- Added `glfwUpdateGamepadMappings` function for importing gamepad mappings in
|
||||
SDL\_GameControllerDB format (#900)
|
||||
- Added `glfwJoystickIsGamepad` function for querying whether a joystick has
|
||||
a gamepad mapping (#900)
|
||||
- Added `glfwGetJoystickGUID` function for querying the SDL compatible GUID of
|
||||
a joystick (#900)
|
||||
- Added `glfwGetGamepadName` function for querying the name provided by the
|
||||
gamepad mapping (#900)
|
||||
- Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate`
|
||||
for retrieving gamepad input state (#900)
|
||||
- Added `glfwRequestWindowAttention` function for requesting attention from the
|
||||
user (#732,#988)
|
||||
- Added `glfwDragWindow` function for starting a drag operation on a window
|
||||
(#987)
|
||||
- Added `glfwGetKeyScancode` function that allows retrieving platform dependent
|
||||
scancodes for keys (#830)
|
||||
- Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for
|
||||
receiving window maximization events (#778)
|
||||
- Added `glfwSetWindowAttrib` function for changing window attributes (#537)
|
||||
- Added `glfwGetJoystickHats` function for querying joystick hats
|
||||
(#889,#906,#934)
|
||||
- Added `glfwInitHint` and `glfwInitHintString` for setting initialization hints
|
||||
- Added headless [OSMesa](http://mesa3d.org/osmesa.html) backend (#850)
|
||||
- Added definition of `GLAPIENTRY` to public header
|
||||
- Added `GLFW_CENTER_CURSOR` window hint for controlling cursor centering
|
||||
(#749,#842)
|
||||
- Added `GLFW_JOYSTICK_HAT_BUTTONS` init hint (#889)
|
||||
- Added macOS specific `GLFW_COCOA_RETINA_FRAMEBUFFER` window hint
|
||||
- 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_CHDIR_RESOURCES` init hint
|
||||
- Added macOS specific `GLFW_COCOA_MENUBAR` init hint
|
||||
- Added X11 specific `GLFW_X11_WM_CLASS_NAME` and `GLFW_X11_WM_CLASS_CLASS` init
|
||||
hints (#893)
|
||||
- Added `GLFW_INCLUDE_ES32` for including the OpenGL ES 3.2 header
|
||||
- Added `GLFW_OSMESA_CONTEXT_API` for creating OpenGL contexts with
|
||||
[OSMesa](https://www.mesa3d.org/osmesa.html) (#281)
|
||||
- Removed `GLFW_USE_RETINA` compile-time option
|
||||
- Removed `GLFW_USE_CHDIR` compile-time option
|
||||
- Removed `GLFW_USE_MENUBAR` compile-time option
|
||||
- Bugfix: Calling `glfwMaximizeWindow` on a full screen window was not ignored
|
||||
- Bugfix: `GLFW_INCLUDE_VULKAN` could not be combined with the corresponding
|
||||
OpenGL and OpenGL ES header macros
|
||||
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
|
||||
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
|
||||
- Bugfix: Invalid library paths were used in test and example CMake files (#930)
|
||||
- Bugfix: The scancode for synthetic key release events was always zero
|
||||
- [Win32] Added system error strings to relevant GLFW error descriptions (#733)
|
||||
- [Win32] Moved to `WM_INPUT` for disabled cursor mode motion input (#125)
|
||||
- [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861)
|
||||
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
|
||||
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)
|
||||
- [Win32] Bugfix: `glfwVulkanSupported` emitted an error on systems with
|
||||
a loader but no ICD (#916)
|
||||
- [Win32] Bugfix: Non-iconified full sreeen windows did not prevent screen
|
||||
blanking or password enabled screensavers (#851)
|
||||
- [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: 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)
|
||||
- [Win32] Bugfix: The Cygwin DLL was installed to the wrong directory (#1035)
|
||||
- [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125)
|
||||
- [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading
|
||||
- [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X
|
||||
- [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: 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)
|
||||
- [X11] Bugfix: Gamma ramp setting via RandR did not validate ramp size
|
||||
- [X11] Bugfix: Key name string encoding depended on current locale (#981,#983)
|
||||
- [Linux] Moved to evdev for joystick input (#906,#1005)
|
||||
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
|
||||
- [Linux] Bugfix: The joystick device path could be truncated (#1025)
|
||||
- [Cocoa] Added support for Vulkan window surface creation via
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) (#870)
|
||||
- [Cocoa] Added support for loading a `MainMenu.nib` when available
|
||||
- [Cocoa] Bugfix: Disabling window aspect ratio would assert (#852)
|
||||
- [Cocoa] Bugfix: Window creation failed to set first responder (#876,#883)
|
||||
- [Cocoa] Bugfix: Removed use of deprecated `CGDisplayIOServicePort` function
|
||||
(#165,#192,#508,#511)
|
||||
- [Cocoa] Bugfix: Disabled use of deprecated `CGDisplayModeCopyPixelEncoding`
|
||||
function on macOS 10.12+
|
||||
- [Cocoa] Bugfix: Running in AppSandbox would emit warnings (#816,#882)
|
||||
- [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)
|
||||
- [WGL] Added support for `WGL_EXT_colorspace` for OpenGL ES contexts
|
||||
- [WGL] Added support for `WGL_ARB_create_context_no_error`
|
||||
- [GLX] Added support for `GLX_ARB_create_context_no_error`
|
||||
- [GLX] Bugfix: Context creation could segfault if no GLXFBConfigs were
|
||||
available (#1040)
|
||||
- [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
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
The official website for GLFW is [glfw.org](http://www.glfw.org/). There you
|
||||
can find the latest version of GLFW, as well as news, documentation and other
|
||||
information about the project.
|
||||
On [glfw.org](http://www.glfw.org/) you can find the latest version of GLFW, as
|
||||
well as news, documentation and other information about the project.
|
||||
|
||||
If you have questions related to the use of GLFW, we have a
|
||||
[support forum](http://discourse.glfw.org/), and the IRC
|
||||
channel `#glfw` on [Freenode](http://freenode.net/).
|
||||
[forum](http://discourse.glfw.org/), and the `#glfw` IRC channel on
|
||||
[Freenode](http://freenode.net/).
|
||||
|
||||
If you have a bug to report, a patch to submit or a feature you'd like to
|
||||
request, please file it in the
|
||||
[issue tracker](https://github.com/glfw/glfw/issues) on GitHub.
|
||||
|
||||
Finally, if you're interested in helping out with the development of GLFW or
|
||||
porting it to your favorite platform, join us on GitHub or IRC.
|
||||
porting it to your favorite platform, join us on the forum, GitHub or IRC.
|
||||
|
||||
|
||||
## Acknowledgements
|
||||
@@ -180,13 +258,18 @@ skills.
|
||||
- John Bartholomew
|
||||
- Niklas Behrens
|
||||
- Niklas Bergström
|
||||
- Denis Bernard
|
||||
- Doug Binks
|
||||
- blanco
|
||||
- Kyle Brenneman
|
||||
- Martin Capitanio
|
||||
- David Carlier
|
||||
- Chi-kwan Chan
|
||||
- Michał Cichoń
|
||||
- Lambert Clara
|
||||
- Andrew Corrigan
|
||||
- Noel Cower
|
||||
- Jason Daly
|
||||
- Jarrod Davis
|
||||
- Olivier Delannoy
|
||||
- Paul R. Deppe
|
||||
@@ -196,8 +279,10 @@ skills.
|
||||
- Jonathan Dummer
|
||||
- Ralph Eastwood
|
||||
- Siavash Eliasi
|
||||
- Felipe Ferreira
|
||||
- Michael Fogleman
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- Eloi Marín Gratacós
|
||||
@@ -207,14 +292,17 @@ skills.
|
||||
- heromyth
|
||||
- Lucas Hinderberger
|
||||
- Paul Holden
|
||||
- Warren Hu
|
||||
- IntellectualKitty
|
||||
- Aaron Jacobs
|
||||
- Erik S. V. Jansson
|
||||
- Toni Jovanoski
|
||||
- Arseny Kapoulkine
|
||||
- Osman Keskin
|
||||
- Cameron King
|
||||
- Peter Knut
|
||||
- Christoph Kubisch
|
||||
- Konstantin Käfer
|
||||
- Eric Larson
|
||||
- Robin Leffmann
|
||||
- Glenn Lewis
|
||||
@@ -230,6 +318,7 @@ skills.
|
||||
- Bryce Mehring
|
||||
- Jonathan Mercier
|
||||
- Marcel Metz
|
||||
- Liam Middlebrook
|
||||
- Jonathan Miller
|
||||
- Kenneth Miller
|
||||
- Bruce Mitchener
|
||||
@@ -244,10 +333,12 @@ skills.
|
||||
- Peoro
|
||||
- Braden Pellett
|
||||
- Arturo J. Pérez
|
||||
- Anthony Pesch
|
||||
- Orson Peters
|
||||
- Emmanuel Gil Peyrot
|
||||
- Cyril Pichard
|
||||
- Pieroman
|
||||
- Philip Rideout
|
||||
- Jorge Rodriguez
|
||||
- Ed Ropple
|
||||
- Aleksey Rybalkin
|
||||
@@ -262,17 +353,21 @@ skills.
|
||||
- Dmitri Shuralyov
|
||||
- Daniel Skorupski
|
||||
- Bradley Smith
|
||||
- Patrick Snape
|
||||
- Julian Squires
|
||||
- Johannes Stein
|
||||
- Michael Stocker
|
||||
- Justin Stoecker
|
||||
- Elviss Strazdins
|
||||
- Nathan Sweet
|
||||
- TTK-Bandit
|
||||
- Sergey Tikhomirov
|
||||
- A. Tombs
|
||||
- Arthur Tombs
|
||||
- Ioannis Tsakpinis
|
||||
- Samuli Tuomola
|
||||
- Matthew Turner
|
||||
- urraka
|
||||
- Elias Vanderstuyft
|
||||
- Jari Vetoniemi
|
||||
- Ricardo Vieira
|
||||
- Nicholas Vitovitch
|
||||
@@ -283,6 +378,7 @@ skills.
|
||||
- Jay Weisskopf
|
||||
- Frank Wille
|
||||
- yuriks
|
||||
- Ryogo Yoshimura
|
||||
- Santi Zupancic
|
||||
- Jonas Ådahl
|
||||
- Lasse Öörni
|
||||
|
||||
Vendored
+137
-14
@@ -1,3 +1,25 @@
|
||||
/*
|
||||
|
||||
OpenGL loader generated by glad 0.1.12a0 on Fri Sep 23 13:36:15 2016.
|
||||
|
||||
Language/Generator: C/C++
|
||||
Specification: gl
|
||||
APIs: gl=3.2
|
||||
Profile: compatibility
|
||||
Extensions:
|
||||
GL_ARB_multisample,
|
||||
GL_ARB_robustness,
|
||||
GL_KHR_debug
|
||||
Loader: False
|
||||
Local files: False
|
||||
Omit khrplatform: False
|
||||
|
||||
Commandline:
|
||||
--profile="compatibility" --api="gl=3.2" --generator="c" --spec="gl" --no-loader --extensions="GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug"
|
||||
Online:
|
||||
http://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&api=gl%3D3.2&extensions=GL_ARB_multisample&extensions=GL_ARB_robustness&extensions=GL_KHR_debug
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -5,14 +27,59 @@
|
||||
|
||||
struct gladGLversionStruct GLVersion;
|
||||
|
||||
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
|
||||
#define _GLAD_IS_SOME_NEW_VERSION 1
|
||||
#endif
|
||||
|
||||
static int max_loaded_major;
|
||||
static int max_loaded_minor;
|
||||
|
||||
static const char *exts = NULL;
|
||||
static int num_exts_i = 0;
|
||||
static const char **exts_i = NULL;
|
||||
|
||||
static int get_exts(void) {
|
||||
#ifdef _GLAD_IS_SOME_NEW_VERSION
|
||||
if(max_loaded_major < 3) {
|
||||
#endif
|
||||
exts = (const char *)glGetString(GL_EXTENSIONS);
|
||||
#ifdef _GLAD_IS_SOME_NEW_VERSION
|
||||
} else {
|
||||
int index;
|
||||
|
||||
num_exts_i = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
|
||||
if (num_exts_i > 0) {
|
||||
exts_i = (const char **)realloc((void *)exts_i, num_exts_i * sizeof *exts_i);
|
||||
}
|
||||
|
||||
if (exts_i == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(index = 0; index < num_exts_i; index++) {
|
||||
exts_i[index] = (const char*)glGetStringi(GL_EXTENSIONS, index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void free_exts(void) {
|
||||
if (exts_i != NULL) {
|
||||
free((char **)exts_i);
|
||||
exts_i = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int has_ext(const char *ext) {
|
||||
#if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_3_0)
|
||||
if(GLVersion.major < 3 || glGetStringi == NULL) {
|
||||
#ifdef _GLAD_IS_SOME_NEW_VERSION
|
||||
if(max_loaded_major < 3) {
|
||||
#endif
|
||||
const char *extensions;
|
||||
const char *loc;
|
||||
const char *terminator;
|
||||
extensions = (const char*) glGetString(GL_EXTENSIONS);
|
||||
extensions = exts;
|
||||
if(extensions == NULL || ext == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -30,13 +97,14 @@ static int has_ext(const char *ext) {
|
||||
}
|
||||
extensions = terminator;
|
||||
}
|
||||
#if defined(GL_VERSION_3_0) || defined(GL_ES_VERSION_3_0)
|
||||
#ifdef _GLAD_IS_SOME_NEW_VERSION
|
||||
} else {
|
||||
GLint num_exts, index;
|
||||
int index;
|
||||
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
|
||||
for(index = 0; index < num_exts; index++) {
|
||||
if(strcmp((const char*) glGetStringi(GL_EXTENSIONS, index), ext) == 0) {
|
||||
for(index = 0; index < num_exts_i; index++) {
|
||||
const char *e = exts_i[index];
|
||||
|
||||
if(strcmp(e, ext) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -316,7 +384,7 @@ PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
|
||||
PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
|
||||
PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
|
||||
PFNGLDELETESYNCPROC glad_glDeleteSync;
|
||||
PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
|
||||
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
|
||||
PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
|
||||
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
|
||||
PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
|
||||
@@ -363,7 +431,7 @@ PFNGLVIEWPORTPROC glad_glViewport;
|
||||
PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
|
||||
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
|
||||
PFNGLINDEXDVPROC glad_glIndexdv;
|
||||
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
|
||||
PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
|
||||
PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
|
||||
PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
|
||||
PFNGLCLEARDEPTHPROC glad_glClearDepth;
|
||||
@@ -722,9 +790,9 @@ PFNGLCOLORPOINTERPROC glad_glColorPointer;
|
||||
PFNGLFRONTFACEPROC glad_glFrontFace;
|
||||
PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
|
||||
PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
|
||||
int GLAD_GL_KHR_debug;
|
||||
int GLAD_GL_ARB_robustness;
|
||||
int GLAD_GL_ARB_multisample;
|
||||
int GLAD_GL_EXT_separate_specular_color;
|
||||
PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
|
||||
PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB;
|
||||
PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB;
|
||||
@@ -746,6 +814,27 @@ PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB;
|
||||
PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB;
|
||||
PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB;
|
||||
PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB;
|
||||
PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
|
||||
PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
|
||||
PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
|
||||
PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
|
||||
PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
|
||||
PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
|
||||
PFNGLOBJECTLABELPROC glad_glObjectLabel;
|
||||
PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
|
||||
PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
|
||||
PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
|
||||
PFNGLDEBUGMESSAGECONTROLKHRPROC glad_glDebugMessageControlKHR;
|
||||
PFNGLDEBUGMESSAGEINSERTKHRPROC glad_glDebugMessageInsertKHR;
|
||||
PFNGLDEBUGMESSAGECALLBACKKHRPROC glad_glDebugMessageCallbackKHR;
|
||||
PFNGLGETDEBUGMESSAGELOGKHRPROC glad_glGetDebugMessageLogKHR;
|
||||
PFNGLPUSHDEBUGGROUPKHRPROC glad_glPushDebugGroupKHR;
|
||||
PFNGLPOPDEBUGGROUPKHRPROC glad_glPopDebugGroupKHR;
|
||||
PFNGLOBJECTLABELKHRPROC glad_glObjectLabelKHR;
|
||||
PFNGLGETOBJECTLABELKHRPROC glad_glGetObjectLabelKHR;
|
||||
PFNGLOBJECTPTRLABELKHRPROC glad_glObjectPtrLabelKHR;
|
||||
PFNGLGETOBJECTPTRLABELKHRPROC glad_glGetObjectPtrLabelKHR;
|
||||
PFNGLGETPOINTERVKHRPROC glad_glGetPointervKHR;
|
||||
static void load_GL_VERSION_1_0(GLADloadproc load) {
|
||||
if(!GLAD_GL_VERSION_1_0) return;
|
||||
glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace");
|
||||
@@ -1475,10 +1564,38 @@ static void load_GL_ARB_robustness(GLADloadproc load) {
|
||||
glad_glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC)load("glGetnHistogramARB");
|
||||
glad_glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC)load("glGetnMinmaxARB");
|
||||
}
|
||||
static void find_extensionsGL(void) {
|
||||
GLAD_GL_EXT_separate_specular_color = has_ext("GL_EXT_separate_specular_color");
|
||||
static void load_GL_KHR_debug(GLADloadproc load) {
|
||||
if(!GLAD_GL_KHR_debug) return;
|
||||
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC)load("glDebugMessageControl");
|
||||
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC)load("glDebugMessageInsert");
|
||||
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC)load("glDebugMessageCallback");
|
||||
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC)load("glGetDebugMessageLog");
|
||||
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC)load("glPushDebugGroup");
|
||||
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC)load("glPopDebugGroup");
|
||||
glad_glObjectLabel = (PFNGLOBJECTLABELPROC)load("glObjectLabel");
|
||||
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC)load("glGetObjectLabel");
|
||||
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC)load("glObjectPtrLabel");
|
||||
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC)load("glGetObjectPtrLabel");
|
||||
glad_glGetPointerv = (PFNGLGETPOINTERVPROC)load("glGetPointerv");
|
||||
glad_glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC)load("glDebugMessageControlKHR");
|
||||
glad_glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC)load("glDebugMessageInsertKHR");
|
||||
glad_glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC)load("glDebugMessageCallbackKHR");
|
||||
glad_glGetDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC)load("glGetDebugMessageLogKHR");
|
||||
glad_glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC)load("glPushDebugGroupKHR");
|
||||
glad_glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC)load("glPopDebugGroupKHR");
|
||||
glad_glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC)load("glObjectLabelKHR");
|
||||
glad_glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC)load("glGetObjectLabelKHR");
|
||||
glad_glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC)load("glObjectPtrLabelKHR");
|
||||
glad_glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC)load("glGetObjectPtrLabelKHR");
|
||||
glad_glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC)load("glGetPointervKHR");
|
||||
}
|
||||
static int find_extensionsGL(void) {
|
||||
if (!get_exts()) return 0;
|
||||
GLAD_GL_ARB_multisample = has_ext("GL_ARB_multisample");
|
||||
GLAD_GL_ARB_robustness = has_ext("GL_ARB_robustness");
|
||||
GLAD_GL_KHR_debug = has_ext("GL_KHR_debug");
|
||||
free_exts();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void find_coreGL(void) {
|
||||
@@ -1516,6 +1633,7 @@ static void find_coreGL(void) {
|
||||
#endif
|
||||
|
||||
GLVersion.major = major; GLVersion.minor = minor;
|
||||
max_loaded_major = major; max_loaded_minor = minor;
|
||||
GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
|
||||
GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
|
||||
GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
|
||||
@@ -1527,6 +1645,10 @@ static void find_coreGL(void) {
|
||||
GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
|
||||
GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
|
||||
GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
|
||||
if (GLVersion.major > 3 || (GLVersion.major >= 3 && GLVersion.minor >= 2)) {
|
||||
max_loaded_major = 3;
|
||||
max_loaded_minor = 2;
|
||||
}
|
||||
}
|
||||
|
||||
int gladLoadGLLoader(GLADloadproc load) {
|
||||
@@ -1547,9 +1669,10 @@ int gladLoadGLLoader(GLADloadproc load) {
|
||||
load_GL_VERSION_3_1(load);
|
||||
load_GL_VERSION_3_2(load);
|
||||
|
||||
find_extensionsGL();
|
||||
if (!find_extensionsGL()) return 0;
|
||||
load_GL_ARB_multisample(load);
|
||||
load_GL_ARB_robustness(load);
|
||||
load_GL_KHR_debug(load);
|
||||
return GLVersion.major != 0 || GLVersion.minor != 0;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+527
-367
File diff suppressed because it is too large
Load Diff
Vendored
+27
-24
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
@@ -192,19 +192,20 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
|
||||
vec3 u = {x, y, z};
|
||||
|
||||
if(vec3_len(u) > 1e-4) {
|
||||
mat4x4 T, C, S = {{0}};
|
||||
|
||||
vec3_norm(u, u);
|
||||
mat4x4 T;
|
||||
mat4x4_from_vec3_mul_outer(T, u, u);
|
||||
|
||||
mat4x4 S = {
|
||||
{ 0, u[2], -u[1], 0},
|
||||
{-u[2], 0, u[0], 0},
|
||||
{ u[1], -u[0], 0, 0},
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
S[1][2] = u[0];
|
||||
S[2][1] = -u[0];
|
||||
S[2][0] = u[1];
|
||||
S[0][2] = -u[1];
|
||||
S[0][1] = u[2];
|
||||
S[1][0] = -u[2];
|
||||
|
||||
mat4x4_scale(S, S, s);
|
||||
|
||||
mat4x4 C;
|
||||
mat4x4_identity(C);
|
||||
mat4x4_sub(C, C, T);
|
||||
|
||||
@@ -213,7 +214,7 @@ static inline void mat4x4_rotate(mat4x4 R, mat4x4 M, float x, float y, float z,
|
||||
mat4x4_add(T, T, C);
|
||||
mat4x4_add(T, T, S);
|
||||
|
||||
T[3][3] = 1.;
|
||||
T[3][3] = 1.;
|
||||
mat4x4_mul(R, M, T);
|
||||
} else {
|
||||
mat4x4_dup(R, M);
|
||||
@@ -257,6 +258,7 @@ static inline void mat4x4_rotate_Z(mat4x4 Q, mat4x4 M, float angle)
|
||||
}
|
||||
static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
||||
{
|
||||
float idet;
|
||||
float s[6];
|
||||
float c[6];
|
||||
s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1];
|
||||
@@ -272,10 +274,10 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
||||
c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2];
|
||||
c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3];
|
||||
c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3];
|
||||
|
||||
|
||||
/* Assumes it is invertible */
|
||||
float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
|
||||
|
||||
idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] );
|
||||
|
||||
T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet;
|
||||
T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet;
|
||||
T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet;
|
||||
@@ -298,12 +300,12 @@ static inline void mat4x4_invert(mat4x4 T, mat4x4 M)
|
||||
}
|
||||
static inline void mat4x4_orthonormalize(mat4x4 R, mat4x4 M)
|
||||
{
|
||||
mat4x4_dup(R, M);
|
||||
float s = 1.;
|
||||
vec3 h;
|
||||
|
||||
mat4x4_dup(R, M);
|
||||
vec3_norm(R[2], R[2]);
|
||||
|
||||
|
||||
s = vec3_mul_inner(R[1], R[2]);
|
||||
vec3_scale(h, R[2], s);
|
||||
vec3_sub(R[1], R[1], h);
|
||||
@@ -324,7 +326,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
|
||||
{
|
||||
M[0][0] = 2.f*n/(r-l);
|
||||
M[0][1] = M[0][2] = M[0][3] = 0.f;
|
||||
|
||||
|
||||
M[1][1] = 2.f*n/(t-b);
|
||||
M[1][0] = M[1][2] = M[1][3] = 0.f;
|
||||
|
||||
@@ -332,7 +334,7 @@ static inline void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t,
|
||||
M[2][1] = (t+b)/(t-b);
|
||||
M[2][2] = -(f+n)/(f-n);
|
||||
M[2][3] = -1.f;
|
||||
|
||||
|
||||
M[3][2] = -2.f*(f*n)/(f-n);
|
||||
M[3][0] = M[3][1] = M[3][3] = 0.f;
|
||||
}
|
||||
@@ -346,7 +348,7 @@ static inline void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, fl
|
||||
|
||||
M[2][2] = -2.f/(f-n);
|
||||
M[2][0] = M[2][1] = M[2][3] = 0.f;
|
||||
|
||||
|
||||
M[3][0] = -(r+l)/(r-l);
|
||||
M[3][1] = -(t+b)/(t-b);
|
||||
M[3][2] = -(f+n)/(f-n);
|
||||
@@ -387,14 +389,15 @@ static inline void mat4x4_look_at(mat4x4 m, vec3 eye, vec3 center, vec3 up)
|
||||
/* TODO: The negation of of can be spared by swapping the order of
|
||||
* operands in the following cross products in the right way. */
|
||||
vec3 f;
|
||||
vec3_sub(f, center, eye);
|
||||
vec3_norm(f, f);
|
||||
|
||||
vec3 s;
|
||||
vec3 t;
|
||||
|
||||
vec3_sub(f, center, eye);
|
||||
vec3_norm(f, f);
|
||||
|
||||
vec3_mul_cross(s, f, up);
|
||||
vec3_norm(s, s);
|
||||
|
||||
vec3 t;
|
||||
vec3_mul_cross(t, s, f);
|
||||
|
||||
m[0][0] = s[0];
|
||||
@@ -470,9 +473,9 @@ static inline void quat_conj(quat r, quat q)
|
||||
r[3] = q[3];
|
||||
}
|
||||
static inline void quat_rotate(quat r, float angle, vec3 axis) {
|
||||
int i;
|
||||
vec3 v;
|
||||
vec3_scale(v, axis, sinf(angle / 2));
|
||||
int i;
|
||||
for(i=0; i<3; ++i)
|
||||
r[i] = v[i];
|
||||
r[3] = cosf(angle / 2);
|
||||
@@ -507,7 +510,7 @@ static inline void mat4x4_from_quat(mat4x4 M, quat q)
|
||||
float b2 = b*b;
|
||||
float c2 = c*c;
|
||||
float d2 = d*d;
|
||||
|
||||
|
||||
M[0][0] = a2 + b2 - c2 - d2;
|
||||
M[0][1] = 2.f*(b*c + a*d);
|
||||
M[0][2] = 2.f*(b*d - a*c);
|
||||
|
||||
Vendored
+23590
File diff suppressed because it is too large
Load Diff
Vendored
+372
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Nuklear - v1.32.0 - public domain
|
||||
* no warrenty implied; use at your own risk.
|
||||
* authored from 2015-2017 by Micha Mettke
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* API
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifndef NK_GLFW_GL2_H_
|
||||
#define NK_GLFW_GL2_H_
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
enum nk_glfw_init_state{
|
||||
NK_GLFW3_DEFAULT = 0,
|
||||
NK_GLFW3_INSTALL_CALLBACKS
|
||||
};
|
||||
NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state);
|
||||
NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas);
|
||||
NK_API void nk_glfw3_font_stash_end(void);
|
||||
|
||||
NK_API void nk_glfw3_new_frame(void);
|
||||
NK_API void nk_glfw3_render(enum nk_anti_aliasing);
|
||||
NK_API void nk_glfw3_shutdown(void);
|
||||
|
||||
NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint);
|
||||
NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* IMPLEMENTATION
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#ifdef NK_GLFW_GL2_IMPLEMENTATION
|
||||
|
||||
#ifndef NK_GLFW_TEXT_MAX
|
||||
#define NK_GLFW_TEXT_MAX 256
|
||||
#endif
|
||||
#ifndef NK_GLFW_DOUBLE_CLICK_LO
|
||||
#define NK_GLFW_DOUBLE_CLICK_LO 0.02
|
||||
#endif
|
||||
#ifndef NK_GLFW_DOUBLE_CLICK_HI
|
||||
#define NK_GLFW_DOUBLE_CLICK_HI 0.2
|
||||
#endif
|
||||
|
||||
struct nk_glfw_device {
|
||||
struct nk_buffer cmds;
|
||||
struct nk_draw_null_texture null;
|
||||
GLuint font_tex;
|
||||
};
|
||||
|
||||
struct nk_glfw_vertex {
|
||||
float position[2];
|
||||
float uv[2];
|
||||
nk_byte col[4];
|
||||
};
|
||||
|
||||
static struct nk_glfw {
|
||||
GLFWwindow *win;
|
||||
int width, height;
|
||||
int display_width, display_height;
|
||||
struct nk_glfw_device ogl;
|
||||
struct nk_context ctx;
|
||||
struct nk_font_atlas atlas;
|
||||
struct nk_vec2 fb_scale;
|
||||
unsigned int text[NK_GLFW_TEXT_MAX];
|
||||
int text_len;
|
||||
struct nk_vec2 scroll;
|
||||
double last_button_click;
|
||||
} glfw;
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_device_upload_atlas(const void *image, int width, int height)
|
||||
{
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
glGenTextures(1, &dev->font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, dev->font_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_render(enum nk_anti_aliasing AA)
|
||||
{
|
||||
/* setup global state */
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
/* setup viewport/project */
|
||||
glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
{
|
||||
GLsizei vs = sizeof(struct nk_glfw_vertex);
|
||||
size_t vp = offsetof(struct nk_glfw_vertex, position);
|
||||
size_t vt = offsetof(struct nk_glfw_vertex, uv);
|
||||
size_t vc = offsetof(struct nk_glfw_vertex, col);
|
||||
|
||||
/* convert from command queue into draw list and draw to screen */
|
||||
const struct nk_draw_command *cmd;
|
||||
const nk_draw_index *offset = NULL;
|
||||
struct nk_buffer vbuf, ebuf;
|
||||
|
||||
/* fill convert configuration */
|
||||
struct nk_convert_config config;
|
||||
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
|
||||
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)},
|
||||
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)},
|
||||
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)},
|
||||
{NK_VERTEX_LAYOUT_END}
|
||||
};
|
||||
NK_MEMSET(&config, 0, sizeof(config));
|
||||
config.vertex_layout = vertex_layout;
|
||||
config.vertex_size = sizeof(struct nk_glfw_vertex);
|
||||
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
|
||||
config.null = dev->null;
|
||||
config.circle_segment_count = 22;
|
||||
config.curve_segment_count = 22;
|
||||
config.arc_segment_count = 22;
|
||||
config.global_alpha = 1.0f;
|
||||
config.shape_AA = AA;
|
||||
config.line_AA = AA;
|
||||
|
||||
/* convert shapes into vertexes */
|
||||
nk_buffer_init_default(&vbuf);
|
||||
nk_buffer_init_default(&ebuf);
|
||||
nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);
|
||||
|
||||
/* setup vertex buffer pointer */
|
||||
{const void *vertices = nk_buffer_memory_const(&vbuf);
|
||||
glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
|
||||
glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));}
|
||||
|
||||
/* iterate over and execute each draw command */
|
||||
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
|
||||
nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds)
|
||||
{
|
||||
if (!cmd->elem_count) continue;
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
|
||||
glScissor(
|
||||
(GLint)(cmd->clip_rect.x * glfw.fb_scale.x),
|
||||
(GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y),
|
||||
(GLint)(cmd->clip_rect.w * glfw.fb_scale.x),
|
||||
(GLint)(cmd->clip_rect.h * glfw.fb_scale.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
|
||||
offset += cmd->elem_count;
|
||||
}
|
||||
nk_clear(&glfw.ctx);
|
||||
nk_buffer_free(&vbuf);
|
||||
nk_buffer_free(&ebuf);
|
||||
}
|
||||
|
||||
/* default OpenGL state */
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint)
|
||||
{
|
||||
(void)win;
|
||||
if (glfw.text_len < NK_GLFW_TEXT_MAX)
|
||||
glfw.text[glfw.text_len++] = codepoint;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
|
||||
{
|
||||
(void)win; (void)xoff;
|
||||
glfw.scroll.x += (float)xoff;
|
||||
glfw.scroll.y += (float)yoff;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
double x, y;
|
||||
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
|
||||
glfwGetCursorPos(window, &x, &y);
|
||||
if (action == GLFW_PRESS) {
|
||||
double dt = glfwGetTime() - glfw.last_button_click;
|
||||
if (dt > NK_GLFW_DOUBLE_CLICK_LO && dt < NK_GLFW_DOUBLE_CLICK_HI)
|
||||
nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_true);
|
||||
glfw.last_button_click = glfwGetTime();
|
||||
} else nk_input_button(&glfw.ctx, NK_BUTTON_DOUBLE, (int)x, (int)y, nk_false);
|
||||
}
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit)
|
||||
{
|
||||
const char *text = glfwGetClipboardString(glfw.win);
|
||||
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
|
||||
(void)usr;
|
||||
}
|
||||
|
||||
NK_INTERN void
|
||||
nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len)
|
||||
{
|
||||
char *str = 0;
|
||||
(void)usr;
|
||||
if (!len) return;
|
||||
str = (char*)malloc((size_t)len+1);
|
||||
if (!str) return;
|
||||
NK_MEMCPY(str, text, (size_t)len);
|
||||
str[len] = '\0';
|
||||
glfwSetClipboardString(glfw.win, str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
NK_API struct nk_context*
|
||||
nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state)
|
||||
{
|
||||
glfw.win = win;
|
||||
if (init_state == NK_GLFW3_INSTALL_CALLBACKS) {
|
||||
glfwSetScrollCallback(win, nk_gflw3_scroll_callback);
|
||||
glfwSetCharCallback(win, nk_glfw3_char_callback);
|
||||
glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback);
|
||||
}
|
||||
nk_init_default(&glfw.ctx, 0);
|
||||
glfw.ctx.clip.copy = nk_glfw3_clipbard_copy;
|
||||
glfw.ctx.clip.paste = nk_glfw3_clipbard_paste;
|
||||
glfw.ctx.clip.userdata = nk_handle_ptr(0);
|
||||
nk_buffer_init_default(&glfw.ogl.cmds);
|
||||
return &glfw.ctx;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas)
|
||||
{
|
||||
nk_font_atlas_init_default(&glfw.atlas);
|
||||
nk_font_atlas_begin(&glfw.atlas);
|
||||
*atlas = &glfw.atlas;
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_font_stash_end(void)
|
||||
{
|
||||
const void *image; int w, h;
|
||||
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
|
||||
nk_glfw3_device_upload_atlas(image, w, h);
|
||||
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
|
||||
if (glfw.atlas.default_font)
|
||||
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
|
||||
}
|
||||
|
||||
NK_API void
|
||||
nk_glfw3_new_frame(void)
|
||||
{
|
||||
int i;
|
||||
double x, y;
|
||||
struct nk_context *ctx = &glfw.ctx;
|
||||
struct GLFWwindow *win = glfw.win;
|
||||
|
||||
glfwGetWindowSize(win, &glfw.width, &glfw.height);
|
||||
glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height);
|
||||
glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width;
|
||||
glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height;
|
||||
|
||||
nk_input_begin(ctx);
|
||||
for (i = 0; i < glfw.text_len; ++i)
|
||||
nk_input_unicode(ctx, glfw.text[i]);
|
||||
|
||||
/* optional grabbing behavior */
|
||||
if (ctx->input.mouse.grab)
|
||||
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
|
||||
else if (ctx->input.mouse.ungrab)
|
||||
glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
|
||||
nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS||
|
||||
glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS);
|
||||
|
||||
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS ||
|
||||
glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) {
|
||||
nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS);
|
||||
} else {
|
||||
nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS);
|
||||
nk_input_key(ctx, NK_KEY_COPY, 0);
|
||||
nk_input_key(ctx, NK_KEY_PASTE, 0);
|
||||
nk_input_key(ctx, NK_KEY_CUT, 0);
|
||||
nk_input_key(ctx, NK_KEY_SHIFT, 0);
|
||||
}
|
||||
|
||||
glfwGetCursorPos(win, &x, &y);
|
||||
nk_input_motion(ctx, (int)x, (int)y);
|
||||
if (ctx->input.mouse.grabbed) {
|
||||
glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y);
|
||||
ctx->input.mouse.pos.x = ctx->input.mouse.prev.x;
|
||||
ctx->input.mouse.pos.y = ctx->input.mouse.prev.y;
|
||||
}
|
||||
|
||||
nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS);
|
||||
nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS);
|
||||
nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS);
|
||||
nk_input_scroll(ctx, glfw.scroll);
|
||||
nk_input_end(&glfw.ctx);
|
||||
glfw.text_len = 0;
|
||||
glfw.scroll = nk_vec2(0,0);
|
||||
}
|
||||
|
||||
NK_API
|
||||
void nk_glfw3_shutdown(void)
|
||||
{
|
||||
struct nk_glfw_device *dev = &glfw.ogl;
|
||||
nk_font_atlas_clear(&glfw.atlas);
|
||||
nk_free(&glfw.ctx);
|
||||
glDeleteTextures(1, &dev->font_tex);
|
||||
nk_buffer_free(&dev->cmds);
|
||||
NK_MEMSET(&glfw, 0, sizeof(glfw));
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+1048
File diff suppressed because it is too large
Load Diff
Vendored
+1
-1
@@ -21,7 +21,7 @@ freely, subject to the following restrictions:
|
||||
distribution.
|
||||
*/
|
||||
|
||||
/* 2013-01-06 Camilla Berglund <elmindreda@glfw.org>
|
||||
/* 2013-01-06 Camilla Löwy <elmindreda@glfw.org>
|
||||
*
|
||||
* Added casts from time_t to DWORD to avoid warnings on VC++.
|
||||
* Fixed time retrieval on POSIX systems.
|
||||
|
||||
Vendored
+3
-1
@@ -123,7 +123,9 @@ typedef int _tthread_clockid_t;
|
||||
/* Emulate clock_gettime */
|
||||
int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
|
||||
#define clock_gettime _tthread_clock_gettime
|
||||
#define CLOCK_REALTIME 0
|
||||
#ifndef CLOCK_REALTIME
|
||||
#define CLOCK_REALTIME 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Vendored
+247
@@ -0,0 +1,247 @@
|
||||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
Vendored
+7
-7
@@ -51,13 +51,13 @@ extern "C"
|
||||
#define VKAPI_ATTR
|
||||
#define VKAPI_CALL __stdcall
|
||||
#define VKAPI_PTR VKAPI_CALL
|
||||
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
|
||||
// Android does not support Vulkan in native code using the "armeabi" ABI.
|
||||
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
|
||||
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
|
||||
// convention, even if the application's native code is compiled with the
|
||||
// armeabi-v7a calling convention.
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
|
||||
#error "Vulkan isn't supported for the 'armeabi' NDK ABI"
|
||||
#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
|
||||
// On Android 32-bit ARM targets, Vulkan functions use the "hardfloat"
|
||||
// calling convention, i.e. float parameters are passed in registers. This
|
||||
// is true even if the rest of the application passes floats on the stack,
|
||||
// as it does by default when compiling for the armeabi-v7a NDK ABI.
|
||||
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
|
||||
#define VKAPI_CALL
|
||||
#define VKAPI_PTR VKAPI_ATTR
|
||||
|
||||
Vendored
+942
-14
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -17,7 +17,9 @@ set(glfw_DOCS_SOURCES
|
||||
"${GLFW_SOURCE_DIR}/docs/compat.dox")
|
||||
|
||||
if (GLFW_DOCUMENT_INTERNALS)
|
||||
list(APPEND glfw_DOCS_SOURCES "${GLFW_SOURCE_DIR}/src/internal.h")
|
||||
list(APPEND glfw_DOCS_SOURCES
|
||||
"${GLFW_SOURCE_DIR}/docs/internal.dox"
|
||||
"${GLFW_SOURCE_DIR}/src/internal.h")
|
||||
endif()
|
||||
|
||||
foreach(arg ${glfw_DOCS_SOURCES})
|
||||
|
||||
+5
-2
@@ -202,8 +202,10 @@ ALIASES = "thread_safety=@par Thread safety\n" \
|
||||
"errors=@par Errors\n" \
|
||||
"glfw3=@par\n__GLFW 3:__" \
|
||||
"x11=__X11:__" \
|
||||
"wayland=__Wayland:__" \
|
||||
"win32=__Windows:__" \
|
||||
"osx=__OS X:__"
|
||||
"macos=__macOS:__" \
|
||||
"linux=__Linux:__"
|
||||
|
||||
# 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
|
||||
@@ -467,7 +469,7 @@ INLINE_INFO = YES
|
||||
# alphabetically by member name. If set to NO the members will appear in
|
||||
# declaration order.
|
||||
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_MEMBER_DOCS = NO
|
||||
|
||||
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
|
||||
# brief documentation of file, namespace and class members alphabetically
|
||||
@@ -1576,6 +1578,7 @@ PREDEFINED = GLFWAPI= \
|
||||
GLFW_EXPOSE_NATIVE_COCOA \
|
||||
GLFW_EXPOSE_NATIVE_NSGL \
|
||||
GLFW_EXPOSE_NATIVE_EGL \
|
||||
GLFW_EXPOSE_NATIVE_OSMESA \
|
||||
VK_VERSION_1_0
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
|
||||
+121
-58
@@ -15,27 +15,27 @@ specific compiler of your chosen development environment. The compilation
|
||||
and linking process should be explained in your C programming material and in
|
||||
the documentation for your development environment.
|
||||
|
||||
|
||||
@section build_include Including the GLFW header file
|
||||
|
||||
In the source files of your application where you use OpenGL or GLFW, you should
|
||||
include the GLFW header file, i.e.:
|
||||
You should include the GLFW header in the source files where you use OpenGL or
|
||||
GLFW.
|
||||
|
||||
@code
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
The GLFW header declares the GLFW API and by default also includes the OpenGL
|
||||
header of your development environment, which in turn defines all the constants,
|
||||
types and function prototypes of the OpenGL API.
|
||||
This header declares the GLFW API and by default also includes the OpenGL header
|
||||
from your development environment. See below for how to control this.
|
||||
|
||||
The GLFW header also defines everything necessary for your OpenGL header to
|
||||
function. For example, under Windows you are normally required to include
|
||||
`windows.h` before the OpenGL header, which would pollute your code namespace
|
||||
with the entire Win32 API.
|
||||
The GLFW header also defines any platform-specific macros needed by your OpenGL
|
||||
header, so it can be included without needing any window system headers.
|
||||
|
||||
Instead, the GLFW header takes care of this for you, not by including
|
||||
`windows.h`, but by duplicating only the very few necessary parts of it. It
|
||||
does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
For example, under Windows you are normally required to include `windows.h`
|
||||
before the OpenGL header, which would bring in the whole Win32 API. The GLFW
|
||||
header duplicates the small number of macros needed.
|
||||
|
||||
It does this only when needed, so if `windows.h` _is_ included, the GLFW header
|
||||
does not try to redefine those symbols. The reverse is not true, i.e.
|
||||
`windows.h` cannot cope if any of its symbols have already been defined.
|
||||
|
||||
@@ -49,8 +49,21 @@ In other words:
|
||||
|
||||
If you are using an OpenGL extension loading library such as
|
||||
[glad](https://github.com/Dav1dde/glad), the extension loader header should
|
||||
either be included _before_ the GLFW one, or the `GLFW_INCLUDE_NONE` macro
|
||||
(described below) should be defined.
|
||||
be included _before_ the GLFW one.
|
||||
|
||||
@code
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
Alternatively the @ref GLFW_INCLUDE_NONE macro (described below) can be used to
|
||||
prevent the GLFW header from including the OpenGL header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glad/glad.h>
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection build_macros GLFW header option macros
|
||||
@@ -58,52 +71,67 @@ either be included _before_ the GLFW one, or the `GLFW_INCLUDE_NONE` macro
|
||||
These macros may be defined before the inclusion of the GLFW header and affect
|
||||
its behavior.
|
||||
|
||||
`GLFW_DLL` is required on Windows when using the GLFW DLL, to tell the compiler
|
||||
that the GLFW functions are defined in a DLL.
|
||||
@anchor GLFW_DLL
|
||||
__GLFW_DLL__ is required on Windows when using the GLFW DLL, to tell the
|
||||
compiler that the GLFW functions are defined in a DLL.
|
||||
|
||||
The following macros control which OpenGL or OpenGL ES API header is included.
|
||||
Only one of these may be defined at a time.
|
||||
|
||||
`GLFW_INCLUDE_GLCOREARB` makes the GLFW header include the modern
|
||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on OS X) instead of the regular OpenGL
|
||||
@anchor GLFW_INCLUDE_GLCOREARB
|
||||
__GLFW_INCLUDE_GLCOREARB__ makes the GLFW header include the modern
|
||||
`GL/glcorearb.h` header (`OpenGL/gl3.h` on macOS) instead of the regular OpenGL
|
||||
header.
|
||||
|
||||
`GLFW_INCLUDE_ES1` makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
|
||||
@anchor GLFW_INCLUDE_ES1
|
||||
__GLFW_INCLUDE_ES1__ makes the GLFW header include the OpenGL ES 1.x `GLES/gl.h`
|
||||
header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_ES2` makes the GLFW header include the OpenGL ES 2.0 `GLES2/gl2.h`
|
||||
header instead of the regular OpenGL header.
|
||||
@anchor GLFW_INCLUDE_ES2
|
||||
__GLFW_INCLUDE_ES2__ makes the GLFW header include the OpenGL ES 2.0
|
||||
`GLES2/gl2.h` header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_ES3` makes the GLFW header include the OpenGL ES 3.0 `GLES3/gl3.h`
|
||||
header instead of the regular OpenGL header.
|
||||
@anchor GLFW_INCLUDE_ES3
|
||||
__GLFW_INCLUDE_ES3__ makes the GLFW header include the OpenGL ES 3.0
|
||||
`GLES3/gl3.h` header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_ES31` makes the GLFW header include the OpenGL ES 3.1 `GLES3/gl31.h`
|
||||
header instead of the regular OpenGL header.
|
||||
@anchor GLFW_INCLUDE_ES31
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.1
|
||||
`GLES3/gl31.h` header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_VULKAN` makes the GLFW header include the Vulkan `vulkan/vulkan.h`
|
||||
header instead of the regular OpenGL header.
|
||||
@anchor GLFW_INCLUDE_ES32
|
||||
__GLFW_INCLUDE_ES31__ makes the GLFW header include the OpenGL ES 3.2
|
||||
`GLES3/gl32.h` header instead of the regular OpenGL header.
|
||||
|
||||
`GLFW_INCLUDE_NONE` makes the GLFW header not include any OpenGL or OpenGL ES API
|
||||
header. This is useful in combination with an extension loading library.
|
||||
@anchor GLFW_INCLUDE_NONE
|
||||
__GLFW_INCLUDE_NONE__ makes the GLFW header not include any OpenGL or OpenGL ES
|
||||
API header. This is useful in combination with an extension loading library.
|
||||
|
||||
If none of the above inclusion macros are defined, the standard OpenGL `GL/gl.h`
|
||||
header (`OpenGL/gl.h` on OS X) is included.
|
||||
header (`OpenGL/gl.h` on macOS) is included.
|
||||
|
||||
The following macros control the inclusion of additional API headers. Any
|
||||
number of these may be defined simultaneously, and/or together with one of the
|
||||
above macros.
|
||||
|
||||
`GLFW_INCLUDE_GLEXT` makes the GLFW header include the appropriate extension
|
||||
@anchor GLFW_INCLUDE_VULKAN
|
||||
__GLFW_INCLUDE_VULKAN__ makes the GLFW header include the Vulkan
|
||||
`vulkan/vulkan.h` header in addition to any selected OpenGL or OpenGL ES header.
|
||||
|
||||
@anchor GLFW_INCLUDE_GLEXT
|
||||
__GLFW_INCLUDE_GLEXT__ makes the GLFW header include the appropriate extension
|
||||
header for the OpenGL or OpenGL ES header selected above after and in addition
|
||||
to that header.
|
||||
|
||||
`GLFW_INCLUDE_GLU` makes the header include the GLU header in addition to the
|
||||
@anchor GLFW_INCLUDE_GLU
|
||||
__GLFW_INCLUDE_GLU__ makes the header include the GLU header in addition to the
|
||||
header selected above. This should only be used with the standard OpenGL header
|
||||
and only for compatibility with legacy code. GLU has been deprecated and should
|
||||
not be used in new code.
|
||||
|
||||
@note GLFW does not provide any of the API headers mentioned above. They must
|
||||
be provided by your development environment or your OpenGL or OpenGL ES SDK.
|
||||
be provided by your development environment or your OpenGL, OpenGL ES or Vulkan
|
||||
SDK.
|
||||
|
||||
@note None of these macros may be defined during the compilation of GLFW itself.
|
||||
If your build includes GLFW and you define any these in your build files, make
|
||||
@@ -118,7 +146,7 @@ a shared library / dynamic library / DLL then it takes care of these links.
|
||||
However, if you are using GLFW as a static library then your executable will
|
||||
need to link against these libraries.
|
||||
|
||||
On Windows and OS X, the list of system libraries is static and can be
|
||||
On Windows and macOS, the list of system libraries is static and can be
|
||||
hard-coded into your build environment. See the section for your development
|
||||
environment below. On Linux and other Unix-like operating systems, the list
|
||||
varies but can be retrieved in various ways as described below.
|
||||
@@ -140,9 +168,9 @@ set of default libraries along with other dependencies like `user32` and
|
||||
`kernel32`. If you are using GLU, you must also link with `glu32`.
|
||||
|
||||
The link library for the GLFW DLL is named `glfw3dll`. When compiling an
|
||||
application that uses the DLL version of GLFW, you need to define the `GLFW_DLL`
|
||||
macro _before_ any inclusion of the GLFW header. This can be done either with
|
||||
a compiler switch or by defining it in your source code.
|
||||
application that uses the DLL version of GLFW, you need to define the @ref
|
||||
GLFW_DLL macro _before_ any inclusion of the GLFW header. This can be done
|
||||
either with a compiler switch or by defining it in your source code.
|
||||
|
||||
An application using the GLFW DLL does not need to link against any of its
|
||||
dependencies, but you still have to link against `opengl32` if your application
|
||||
@@ -177,28 +205,43 @@ add_subdirectory(path/to/glfw)
|
||||
|
||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
||||
the include directory for the GLFW header and, when applicable, the
|
||||
[GLFW_DLL](@ref build_macros) macro.
|
||||
the include directory for the GLFW header and, when applicable, the @ref
|
||||
GLFW_DLL macro.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp glfw)
|
||||
@endcode
|
||||
|
||||
Note that it does not include GLU, as GLFW does not use it. If your application
|
||||
needs GLU, you can find it by requiring the OpenGL package.
|
||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
||||
If your application calls OpenGL directly, instead of using a modern
|
||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
||||
the OpenGL package.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If GLU is found, the `OPENGL_GLU_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
||||
@endcode
|
||||
|
||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_cmake_package With CMake and installed GLFW binaries
|
||||
|
||||
@@ -210,33 +253,48 @@ With just a few changes to your `CMakeLists.txt`, you can locate the package and
|
||||
target files generated when GLFW is installed.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(glfw3 3.2 REQUIRED)
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
@endcode
|
||||
|
||||
Once GLFW has been located, link against it with the `glfw` target. This adds
|
||||
all link-time dependencies of GLFW as it is currently configured, the include
|
||||
directory for the GLFW header and, when applicable, the
|
||||
[GLFW_DLL](@ref build_macros) macro.
|
||||
Once GLFW has been added to the project, link against it with the `glfw` target.
|
||||
This adds all link-time dependencies of GLFW as it is currently configured,
|
||||
the include directory for the GLFW header and, when applicable, the @ref
|
||||
GLFW_DLL macro.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp glfw)
|
||||
@endcode
|
||||
|
||||
Note that it does not include GLU, as GLFW does not use it. If your application
|
||||
needs GLU, you can find it by requiring the OpenGL package.
|
||||
Note that the dependencies do not include OpenGL or GLU, as GLFW loads any
|
||||
OpenGL, OpenGL ES or Vulkan libraries it needs at runtime and does not use GLU.
|
||||
If your application calls OpenGL directly, instead of using a modern
|
||||
[extension loader library](@ref context_glext_auto) you can find it by requiring
|
||||
the OpenGL package.
|
||||
|
||||
@code{.cmake}
|
||||
find_package(OpenGL REQUIRED)
|
||||
@endcode
|
||||
|
||||
If GLU is found, the `OPENGL_GLU_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
If OpenGL is found, the `OPENGL_FOUND` variable is true and the
|
||||
`OPENGL_INCLUDE_DIR` and `OPENGL_gl_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_include_directories(myapp ${OPENGL_INCLUDE_DIR})
|
||||
target_link_libraries(myapp ${OPENGL_gl_LIBRARY})
|
||||
@endcode
|
||||
|
||||
The OpenGL CMake package also looks for GLU. If GLU is found, the
|
||||
`OPENGL_GLU_FOUND` variable is true and the `OPENGL_INCLUDE_DIR` and
|
||||
`OPENGL_glu_LIBRARY` cache variables can be used.
|
||||
|
||||
@code{.cmake}
|
||||
target_link_libraries(myapp ${OPENGL_glu_LIBRARY})
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
|
||||
@subsection build_link_pkgconfig With makefiles and pkg-config on Unix
|
||||
|
||||
@@ -268,8 +326,9 @@ You can also use the `glfw3.pc` file without installing it first, by using the
|
||||
env PKG_CONFIG_PATH=path/to/glfw/src cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3`
|
||||
@endcode
|
||||
|
||||
The dependencies do not include GLU, as GLFW does not use it. On OS X, GLU is
|
||||
built into the OpenGL framework, so if you need GLU you don't need to do
|
||||
The dependencies do not include OpenGL or GLU, as GLFW loads any OpenGL, OpenGL
|
||||
ES or Vulkan libraries it needs at runtime and does not use GLU. On macOS, GLU
|
||||
is built into the OpenGL framework, so if you need GLU you don't need to do
|
||||
anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||
`glu` pkg-config package.
|
||||
|
||||
@@ -277,6 +336,10 @@ anything extra. If you need GLU and are using Linux or BSD, you should add the
|
||||
cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --libs glfw3 glu`
|
||||
@endcode
|
||||
|
||||
@note GLU has been deprecated and should not be used in new code, but some
|
||||
legacy code requires it. See the [section on GLU](@ref moving_glu) in the
|
||||
transition guide for suggested replacements.
|
||||
|
||||
If you are using the static version of the GLFW library, make sure you don't
|
||||
link statically against GLU.
|
||||
|
||||
@@ -285,7 +348,7 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection build_link_xcode With Xcode on OS X
|
||||
@subsection build_link_xcode With Xcode on macOS
|
||||
|
||||
If you are using the dynamic library version of GLFW, simply add it to the
|
||||
project dependencies.
|
||||
@@ -295,10 +358,10 @@ OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can
|
||||
all be found in `/System/Library/Frameworks`.
|
||||
|
||||
|
||||
@subsection build_link_osx With command-line on OS X
|
||||
@subsection build_link_osx With command-line on macOS
|
||||
|
||||
It is recommended that you use [pkg-config](@ref build_link_pkgconfig) when
|
||||
building from the command line on OS X. That way you will get any new
|
||||
building from the command line on macOS. That way you will get any new
|
||||
dependencies added automatically. If you still wish to build manually, you need
|
||||
to add the required frameworks and libraries to your command-line yourself using
|
||||
the `-l` and `-framework` switches.
|
||||
@@ -318,6 +381,6 @@ against it from the command-line.
|
||||
The OpenGL framework contains both the OpenGL and GLU APIs, so there is nothing
|
||||
special to do when using GLU. Also note that even though your machine may have
|
||||
`libGL`-style OpenGL libraries, they are for use with the X Window System and
|
||||
will _not_ work with the OS X native version of GLFW.
|
||||
will _not_ work with the macOS native version of GLFW.
|
||||
|
||||
*/
|
||||
|
||||
+21
-14
@@ -76,6 +76,10 @@ GLFW uses the Xkb extension and detectable auto-repeat to provide keyboard
|
||||
input. If the running X server does not support this extension, a non-Xkb
|
||||
fallback path is used.
|
||||
|
||||
GLFW uses the XInput2 extension to provide raw, non-accelerated mouse motion
|
||||
when the cursor is disabled. If the running X server does not support this
|
||||
extension, regular accelerated mouse motion will be used.
|
||||
|
||||
|
||||
@section compat_glx GLX extensions
|
||||
|
||||
@@ -160,21 +164,21 @@ extensions to provide support for sRGB framebuffers. Where both of these
|
||||
extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
|
||||
|
||||
|
||||
@section compat_osx OpenGL 3.2 and later on OS X
|
||||
@section compat_osx OpenGL on macOS
|
||||
|
||||
Support for OpenGL 3.2 and above was introduced with OS X 10.7 and even then
|
||||
only forward-compatible, core profile contexts are supported. Support for
|
||||
OpenGL 4.1 was introduced with OS X 10.9, also limited to forward-compatible,
|
||||
core profile contexts. There is also still no mechanism for requesting debug
|
||||
contexts. Versions of Mac OS X earlier than 10.7 support at most OpenGL
|
||||
version 2.1.
|
||||
contexts or no-error contexts. Versions of Mac OS X earlier than 10.7 support
|
||||
at most OpenGL version 2.1.
|
||||
|
||||
Because of this, on OS X 10.7 and later, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will cause @ref glfwCreateWindow to fail if
|
||||
given version 3.0 or 3.1, the `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
|
||||
given version 3.0 or 3.1. The `GLFW_OPENGL_FORWARD_COMPAT` hint must be set to
|
||||
`GLFW_TRUE` and the `GLFW_OPENGL_PROFILE` hint must be set to
|
||||
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts and the
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` hint is ignored.
|
||||
`GLFW_OPENGL_CORE_PROFILE` when creating OpenGL 3.2 and later contexts. The
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` and `GLFW_CONTEXT_NO_ERROR` hints are ignored.
|
||||
|
||||
Also, on Mac OS X 10.6 and below, the `GLFW_CONTEXT_VERSION_MAJOR` and
|
||||
`GLFW_CONTEXT_VERSION_MINOR` hints will fail if given a version above 2.1,
|
||||
@@ -185,10 +189,12 @@ a non-default value will cause @ref glfwCreateWindow to fail and the
|
||||
|
||||
@section compat_vulkan Vulkan loader and API
|
||||
|
||||
GLFW uses the standard system-wside Vulkan loader to access the Vulkan API.
|
||||
This should be installed by graphics drivers and Vulkan SDKs. If this is not
|
||||
available, @ref glfwVulkanSupported will return `GLFW_FALSE` and all other
|
||||
Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE error.
|
||||
By default, GLFW uses the standard system-wide Vulkan loader to access the
|
||||
Vulkan API on all platforms except macOS. This is installed by both graphics
|
||||
drivers and Vulkan SDKs. If either the loader or at least one minimally
|
||||
functional ICD is missing, @ref glfwVulkanSupported will return `GLFW_FALSE` and
|
||||
all other Vulkan-related functions will fail with an @ref GLFW_API_UNAVAILABLE
|
||||
error.
|
||||
|
||||
|
||||
@section compat_wsi Vulkan WSI extensions
|
||||
@@ -201,6 +207,11 @@ surfaces on Microsoft Windows. If any of these extensions are not available,
|
||||
@ref glfwGetRequiredInstanceExtensions will return an empty list and window
|
||||
surface creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create
|
||||
surfaces on macOS. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or
|
||||
`VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface`
|
||||
or both `VK_KHR_xlib_surface` and `VK_KHR_xcb_surface` are not available, @ref
|
||||
@@ -217,8 +228,4 @@ surfaces on Mir. If any of these extensions are not available, @ref
|
||||
glfwGetRequiredInstanceExtensions will return an empty list and window surface
|
||||
creation will fail.
|
||||
|
||||
GLFW does not support any extensions for window surface creation on OS X,
|
||||
meaning@ref glfwGetRequiredInstanceExtensions will return an empty list and
|
||||
window surface creation will fail.
|
||||
|
||||
*/
|
||||
|
||||
+49
-51
@@ -14,7 +14,8 @@ GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles
|
||||
for a particular development environment. If you are on a Unix-like system such
|
||||
as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or
|
||||
Homebrew, you can simply install its CMake package. If not, you can download
|
||||
installers for Windows and OS X from the [CMake website](http://www.cmake.org/).
|
||||
installers for Windows and macOS from the
|
||||
[CMake website](http://www.cmake.org/).
|
||||
|
||||
@note CMake only generates project files or makefiles. It does not compile the
|
||||
actual GLFW library. To compile GLFW, first generate these files for your
|
||||
@@ -76,11 +77,11 @@ the CMake wiki.
|
||||
Once you have this set up, move on to @ref compile_generate.
|
||||
|
||||
|
||||
@subsubsection compile_deps_xcode Dependencies for Xcode on OS X
|
||||
@subsubsection compile_deps_xcode Dependencies for Xcode on macOS
|
||||
|
||||
Xcode comes with all necessary tools except for CMake. The required headers
|
||||
and libraries are included in the core OS X frameworks. Xcode can be downloaded
|
||||
from the Mac App Store or from the ADC Member Center.
|
||||
and libraries are included in the core macOS frameworks. Xcode can be
|
||||
downloaded from the Mac App Store or from the ADC Member Center.
|
||||
|
||||
Once you have Xcode installed, move on to @ref compile_generate.
|
||||
|
||||
@@ -96,6 +97,17 @@ Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_deps_osmesa Dependencies for Linux and OSMesa
|
||||
|
||||
To compile GLFW for OSMesa, you need to install the OSMesa library and header
|
||||
packages. For example, on Ubuntu and other distributions based on Debian
|
||||
GNU/Linux, you need to install the `libosmesa6-dev` package. The OSMesa library
|
||||
is required at runtime for context creation and is loaded on demand.
|
||||
|
||||
Once you have installed the necessary packages, move on to @ref
|
||||
compile_generate.
|
||||
|
||||
|
||||
@subsection compile_generate Generating build files with CMake
|
||||
|
||||
Once you have all necessary dependencies it is time to generate the project
|
||||
@@ -181,44 +193,41 @@ cmake -DBUILD_SHARED_LIBS=ON .
|
||||
|
||||
@subsubsection compile_options_shared Shared CMake options
|
||||
|
||||
`BUILD_SHARED_LIBS` determines whether GLFW is built as a static
|
||||
@anchor BUILD_SHARED_LIBS
|
||||
__BUILD_SHARED_LIBS__ determines whether GLFW is built as a static
|
||||
library or as a DLL / shared library / dynamic library.
|
||||
|
||||
`LIB_SUFFIX` affects where the GLFW shared /dynamic library is installed. If it
|
||||
is empty, it is installed to `${CMAKE_INSTALL_PREFIX}/lib`. If it is set to
|
||||
@anchor LIB_SUFFIX
|
||||
__LIB_SUFFIX__ affects where the GLFW shared /dynamic library is installed. If
|
||||
it is empty, it is installed to `${CMAKE_INSTALL_PREFIX}/lib`. If it is set to
|
||||
`64`, it is installed to `${CMAKE_INSTALL_PREFIX}/lib64`.
|
||||
|
||||
`GLFW_BUILD_EXAMPLES` determines whether the GLFW examples are built
|
||||
@anchor GLFW_BUILD_EXAMPLES
|
||||
__GLFW_BUILD_EXAMPLES__ determines whether the GLFW examples are built
|
||||
along with the library.
|
||||
|
||||
`GLFW_BUILD_TESTS` determines whether the GLFW test programs are
|
||||
@anchor GLFW_BUILD_TESTS
|
||||
__GLFW_BUILD_TESTS__ determines whether the GLFW test programs are
|
||||
built along with the library.
|
||||
|
||||
`GLFW_BUILD_DOCS` determines whether the GLFW documentation is built along with
|
||||
the library.
|
||||
@anchor GLFW_BUILD_DOCS
|
||||
__GLFW_BUILD_DOCS__ determines whether the GLFW documentation is built along
|
||||
with the library.
|
||||
|
||||
|
||||
@subsubsection compile_options_osx OS X specific CMake options
|
||||
|
||||
`GLFW_USE_CHDIR` determines whether `glfwInit` changes the current
|
||||
directory of bundled applications to the `Contents/Resources` directory.
|
||||
|
||||
`GLFW_USE_MENUBAR` determines whether the first call to
|
||||
`glfwCreateWindow` sets up a minimal menu bar.
|
||||
|
||||
`GLFW_USE_RETINA` determines whether windows will use the full resolution of
|
||||
Retina displays.
|
||||
@anchor GLFW_VULKAN_STATIC
|
||||
__GLFW_VULKAN_STATIC__ determines whether to use the Vulkan loader linked
|
||||
statically into the application.
|
||||
|
||||
|
||||
@subsubsection compile_options_win32 Windows specific CMake options
|
||||
|
||||
`USE_MSVC_RUNTIME_LIBRARY_DLL` determines whether to use the DLL version or the
|
||||
@anchor USE_MSVC_RUNTIME_LIBRARY_DLL
|
||||
__USE_MSVC_RUNTIME_LIBRARY_DLL__ determines whether to use the DLL version or the
|
||||
static library version of the Visual C++ runtime library. If set to `ON`, the
|
||||
DLL version of the Visual C++ library is used. It is recommended to set this to
|
||||
`ON`, as this keeps the executable smaller and benefits from security and bug
|
||||
fix updates of the Visual C++ runtime.
|
||||
DLL version of the Visual C++ library is used.
|
||||
|
||||
`GLFW_USE_HYBRID_HPG` determines whether to export the `NvOptimusEnablement` and
|
||||
@anchor GLFW_USE_HYBRID_HPG
|
||||
__GLFW_USE_HYBRID_HPG__ determines whether to export the `NvOptimusEnablement` and
|
||||
`AmdPowerXpressRequestHighPerformance` symbols, which force the use of the
|
||||
high-performance GPU on Nvidia Optimus and AMD PowerXpress systems. These symbols
|
||||
need to be exported by the EXE to be detected by the driver, so the override
|
||||
@@ -235,43 +244,32 @@ features.
|
||||
|
||||
When building with CMake, the `glfw_config.h` configuration header is generated
|
||||
based on the current platform and CMake options. The GLFW CMake environment
|
||||
defines `_GLFW_USE_CONFIG_H`, which causes this header to be included by
|
||||
defines @b GLFW_USE_CONFIG_H, which causes this header to be included by
|
||||
`internal.h`. Without this macro, GLFW will expect the necessary configuration
|
||||
macros to be defined on the command-line.
|
||||
|
||||
The window creation API is used to create windows, handle input, monitors, gamma
|
||||
ramps and clipboard. The options are:
|
||||
|
||||
- `_GLFW_COCOA` to use the Cocoa frameworks
|
||||
- `_GLFW_WIN32` to use the Win32 API
|
||||
- `_GLFW_X11` to use the X Window System
|
||||
- `_GLFW_WAYLAND` to use the Wayland API (experimental and incomplete)
|
||||
- `_GLFW_MIR` to use the Mir API (experimental and incomplete)
|
||||
- @b _GLFW_COCOA to use the Cocoa frameworks
|
||||
- @b _GLFW_WIN32 to use the Win32 API
|
||||
- @b _GLFW_X11 to use the X Window System
|
||||
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
|
||||
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
|
||||
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
|
||||
|
||||
If you are building GLFW as a shared library / dynamic library / DLL then you
|
||||
must also define `_GLFW_BUILD_DLL`. Otherwise, you must not define it.
|
||||
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.
|
||||
|
||||
If you are linking the Vulkan loader statically into your application then you
|
||||
must also define @b _GLFW_VULKAN_STATIC. Otherwise, GLFW will attempt to use the
|
||||
external version.
|
||||
|
||||
For the EGL context creation API, the following options are available:
|
||||
|
||||
- `_GLFW_USE_EGLPLATFORM_H` to use `EGL/eglplatform.h` for native handle
|
||||
- @b _GLFW_USE_EGLPLATFORM_H to use `EGL/eglplatform.h` for native handle
|
||||
definitions (fallback)
|
||||
|
||||
If you are using the X11 window creation API, support for the following X11
|
||||
extensions can be enabled:
|
||||
|
||||
- `_GLFW_HAS_XF86VM` to use Xxf86vm as a fallback when RandR gamma is broken
|
||||
(recommended)
|
||||
|
||||
If you are using the Cocoa window creation API, the following options are
|
||||
available:
|
||||
|
||||
- `_GLFW_USE_CHDIR` to `chdir` to the `Resources` subdirectory of the
|
||||
application bundle during @ref glfwInit (recommended)
|
||||
- `_GLFW_USE_MENUBAR` to create and populate the menu bar when the first window
|
||||
is created (recommended)
|
||||
- `_GLFW_USE_RETINA` to have windows use the full resolution of Retina displays
|
||||
(recommended)
|
||||
|
||||
@note None of the @ref build_macros may be defined during the compilation of
|
||||
GLFW. If you define any of these in your build files, make sure they are not
|
||||
applied to the GLFW sources.
|
||||
|
||||
+12
-14
@@ -5,9 +5,8 @@
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the OpenGL and OpenGL ES context related functions of
|
||||
GLFW. For details on a specific function, see the
|
||||
[reference documentation](@ref context). There are also guides for the other
|
||||
areas of the GLFW API.
|
||||
GLFW. For details on a specific function in this category, see the @ref
|
||||
context. There are also guides for the other areas of the GLFW API.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
@@ -31,8 +30,8 @@ the `glfwinfo` test program.
|
||||
|
||||
@note Vulkan does not have a context and the Vulkan instance is created via the
|
||||
Vulkan API itself. If you will be using Vulkan to render to a window, disable
|
||||
context creation by setting the [GLFW_CLIENT_API](@ref window_hints_ctx) hint to
|
||||
`GLFW_NO_API`. For more information, see the @ref vulkan_guide.
|
||||
context creation by setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
|
||||
hint to `GLFW_NO_API`. For more information, see the @ref vulkan_guide.
|
||||
|
||||
|
||||
@subsection context_hints Context creation hints
|
||||
@@ -69,7 +68,7 @@ GLFW comes with a simple object sharing test program called `sharing`.
|
||||
|
||||
GLFW doesn't support creating contexts without an associated window. However,
|
||||
contexts with hidden windows can be created with the
|
||||
[GLFW_VISIBLE](@ref window_hints_wnd) window hint.
|
||||
[GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
@@ -85,17 +84,16 @@ objects are recommended for rendering with such contexts.
|
||||
You should still [process events](@ref events) as long as you have at least one
|
||||
window, even if none of them are visible.
|
||||
|
||||
__OS X:__ The first time a window is created the menu bar is populated with
|
||||
common commands like Hide, Quit and About. This is not desirable for example
|
||||
when writing a command-line only application. The menu bar setup can be
|
||||
disabled with a [compile-time option](@ref compile_options_osx).
|
||||
@macos The first time a window is created the menu bar is created. This is not
|
||||
desirable for example when writing a command-line only application. Menu bar
|
||||
creation can be disabled with the @ref GLFW_COCOA_MENUBAR init hint.
|
||||
|
||||
|
||||
@subsection context_less Windows without contexts
|
||||
|
||||
You can disable context creation by setting the
|
||||
[GLFW_CLIENT_API](@ref window_hints_ctx) hint to `GLFW_NO_API`. Windows without
|
||||
contexts must not be passed to @ref glfwMakeContextCurrent or @ref
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`. Windows
|
||||
without contexts must not be passed to @ref glfwMakeContextCurrent or @ref
|
||||
glfwSwapBuffers.
|
||||
|
||||
|
||||
@@ -267,8 +265,8 @@ supports. These have names like `PFNGLGETDEBUGMESSAGELOGARBPROC` (for
|
||||
`glGetDebugMessageLogARB`), i.e. the name is made uppercase and `PFN` (pointer
|
||||
to function) and `PROC` (procedure) are added to the ends.
|
||||
|
||||
To include the extension header, define [GLFW_INCLUDE_GLEXT](@ref build_macros)
|
||||
before including the GLFW header.
|
||||
To include the extension header, define @ref GLFW_INCLUDE_GLEXT before including
|
||||
the GLFW header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_GLEXT
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+27
-1
@@ -76,8 +76,17 @@
|
||||
border:2px solid desaturate(darken(@base-color, 10%), 20%);
|
||||
}
|
||||
|
||||
.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover {
|
||||
background:none;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
|
||||
.sm-dox ul a:hover {
|
||||
background:@header-footer-link-color;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
#main-nav,#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code {
|
||||
background:none;
|
||||
}
|
||||
|
||||
@@ -183,6 +192,13 @@ address.footer {
|
||||
background:@header-footer-link-color;
|
||||
}
|
||||
|
||||
#main-nav {
|
||||
max-width:960px;
|
||||
min-width:800px;
|
||||
margin:0 auto;
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
#navrow1,#navrow2,#navrow3,#navrow4 {
|
||||
max-width:920px;
|
||||
min-width:800px;
|
||||
@@ -190,6 +206,15 @@ address.footer {
|
||||
font-size:13px;
|
||||
}
|
||||
|
||||
.memtitle {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.memproto,.memname {
|
||||
font-weight:bold;
|
||||
text-shadow:none;
|
||||
}
|
||||
|
||||
.tablist {
|
||||
height:36px;
|
||||
display:block;
|
||||
@@ -222,6 +247,7 @@ table.doxtable th,dl.reflist dt {
|
||||
background:linear-gradient(to bottom,@table-background-color2 0%,@table-background-color1 100%);
|
||||
box-shadow:inset 0 0 32px @table-background-color1;
|
||||
text-shadow:0 -1px 1px darken(@table-background-color1, 15%);
|
||||
text-align:left;
|
||||
color:@table-text-color;
|
||||
}
|
||||
|
||||
|
||||
+279
-47
@@ -5,19 +5,19 @@
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the input related functions of GLFW. For details on
|
||||
a specific function, see the [reference documentation](@ref input). There are
|
||||
also guides for the other areas of GLFW.
|
||||
a specific function in this category, see the @ref input. There are also guides
|
||||
for the other areas of GLFW.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref monitor_guide
|
||||
|
||||
GLFW provides many kinds of input. While some can only be polled, like time, or
|
||||
only received via callbacks, like scrolling, there are those that provide both
|
||||
callbacks and polling. Where a callback is provided, that is the recommended
|
||||
way to receive that kind of input. The more you can use callbacks the less time
|
||||
your users' machines will need to spend polling.
|
||||
only received via callbacks, like scrolling, many provide both callbacks and
|
||||
polling. Callbacks are more work to use than polling but is less CPU intensive
|
||||
and guarantees that you do not miss state changes.
|
||||
|
||||
All input callbacks receive a window handle. By using the
|
||||
[window user pointer](@ref window_userptr), you can access non-global structures
|
||||
@@ -31,14 +31,14 @@ information.
|
||||
|
||||
@section events Event processing
|
||||
|
||||
GLFW needs to communicate regularly with the window system both in order to
|
||||
receive events and to show that the application hasn't locked up. Event
|
||||
processing must be done regularly while you have any windows and is normally
|
||||
done each frame after [buffer swapping](@ref buffer_swap). Even when you have
|
||||
no windows, event polling needs to be done in order to receive monitor
|
||||
connection events.
|
||||
GLFW needs to poll the window system for events both to provide input to the
|
||||
application and to prove to the window system that the application hasn't locked
|
||||
up. Event processing is normally done each frame after
|
||||
[buffer swapping](@ref buffer_swap). Even when you have no windows, event
|
||||
polling needs to be done in order to receive monitor and joystick connection
|
||||
events.
|
||||
|
||||
There are two functions for processing pending events. @ref glfwPollEvents,
|
||||
There are three functions for processing pending events. @ref glfwPollEvents,
|
||||
processes only those events that have already been received and then returns
|
||||
immediately.
|
||||
|
||||
@@ -46,7 +46,7 @@ immediately.
|
||||
glfwPollEvents();
|
||||
@endcode
|
||||
|
||||
This is the best choice when rendering continually, like most games do.
|
||||
This is the best choice when rendering continuously, like most games do.
|
||||
|
||||
If you only need to update the contents of the window when you receive new
|
||||
input, @ref glfwWaitEvents is a better choice.
|
||||
@@ -60,8 +60,8 @@ processes all received events. This saves a great deal of CPU cycles and is
|
||||
useful for, for example, editing tools. There must be at least one GLFW window
|
||||
for this function to sleep.
|
||||
|
||||
If you want to wait for events but have UI elements that need periodic updates,
|
||||
call @ref glfwWaitEventsTimeout.
|
||||
If you want to wait for events but have UI elements or other tasks that need
|
||||
periodic updates, @ref glfwWaitEventsTimeout lets you specify a timeout.
|
||||
|
||||
@code
|
||||
glfwWaitEventsTimeout(0.7);
|
||||
@@ -79,10 +79,17 @@ glfwPostEmptyEvent.
|
||||
glfwPostEmptyEvent();
|
||||
@endcode
|
||||
|
||||
Do not assume that callbacks will _only_ be called through either of the above
|
||||
functions. While it is necessary to process events in the event queue, some
|
||||
window systems will send some events directly to the application, which in turn
|
||||
causes callbacks to be called outside of regular event processing.
|
||||
Do not assume that callbacks will _only_ be called in response to the above
|
||||
functions. While it is necessary to process events in one or more of the ways
|
||||
above, window systems that require GLFW to register callbacks of its own can
|
||||
pass events to GLFW in response to many window system function calls. GLFW will
|
||||
pass those events on to the application callbacks before returning.
|
||||
|
||||
For example, on Windows the system function that @ref glfwSetWindowSize is
|
||||
implemented with will send window size events directly to the event callback
|
||||
that every window has and that GLFW implements for its windows. If you have set
|
||||
a [window size callback](@ref window_size) GLFW will call it in turn with the
|
||||
new size before everything returns back out of the @ref glfwSetWindowSize call.
|
||||
|
||||
|
||||
@section input_keyboard Keyboard input
|
||||
@@ -124,21 +131,31 @@ _E-mail_ and _Play_ keys.
|
||||
The scancode is unique for every key, regardless of whether it has a key token.
|
||||
Scancodes are platform-specific but consistent over time, so keys will have
|
||||
different scancodes depending on the platform but they are safe to save to disk.
|
||||
You can query the scancode for any [named key](@ref keys) on the current
|
||||
platform with @ref glfwGetKeyScancode.
|
||||
|
||||
Key states for [named keys](@ref keys) are also saved in per-window state arrays
|
||||
that can be polled with @ref glfwGetKey.
|
||||
@code
|
||||
const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
|
||||
set_key_mapping(scancode, swap_weapons);
|
||||
@endcode
|
||||
|
||||
The last reported state for every [named key](@ref keys) is also saved in
|
||||
per-window state arrays that can be polled with @ref glfwGetKey.
|
||||
|
||||
@code
|
||||
int state = glfwGetKey(window, GLFW_KEY_E);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
activate_airship();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
|
||||
This function only returns cached key event state. It does not poll the
|
||||
system for the current state of the key.
|
||||
system for the current physical state of the key.
|
||||
|
||||
@anchor GLFW_STICKY_KEYS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed key is released again before you poll its state, you will have
|
||||
missed the key press. The recommended solution for this is to use a
|
||||
@@ -164,12 +181,10 @@ GLFW supports text input in the form of a stream of
|
||||
operating system text input system. Unlike key input, text input obeys keyboard
|
||||
layouts and modifier keys and supports composing characters using
|
||||
[dead keys](https://en.wikipedia.org/wiki/Dead_key). Once received, you can
|
||||
encode the code points into
|
||||
[UTF-8](https://en.wikipedia.org/wiki/UTF-8) or any other encoding you prefer.
|
||||
encode the code points into UTF-8 or any other encoding you prefer.
|
||||
|
||||
Because an `unsigned int` is 32 bits long on all platforms supported by GLFW,
|
||||
you can treat the code point argument as native endian
|
||||
[UTF-32](https://en.wikipedia.org/wiki/UTF-32).
|
||||
you can treat the code point argument as native endian UTF-32.
|
||||
|
||||
There are two callbacks for receiving Unicode code points. If you wish to
|
||||
offer regular text input, set a character callback.
|
||||
@@ -257,8 +272,9 @@ glfwGetCursorPos(window, &xpos, &ypos);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection cursor_mode Cursor modes
|
||||
@subsection cursor_mode Cursor mode
|
||||
|
||||
@anchor GLFW_CURSOR
|
||||
The `GLFW_CURSOR` input mode provides several cursor modes for special forms of
|
||||
mouse motion input. By default, the cursor mode is `GLFW_CURSOR_NORMAL`,
|
||||
meaning the regular arrow cursor (or another cursor set with @ref glfwSetCursor)
|
||||
@@ -328,8 +344,8 @@ If cursor creation fails, `NULL` will be returned, so it is necessary to check
|
||||
the return value.
|
||||
|
||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||
per channel. The pixels are arranged canonically as sequential rows, starting
|
||||
from the top-left corner.
|
||||
per channel with the red channel first. The pixels are arranged canonically as
|
||||
sequential rows, starting from the top-left corner.
|
||||
|
||||
|
||||
@subsubsection cursor_standard Standard cursor creation
|
||||
@@ -353,8 +369,10 @@ When a cursor is no longer needed, destroy it with @ref glfwDestroyCursor.
|
||||
glfwDestroyCursor(cursor);
|
||||
@endcode
|
||||
|
||||
Cursor destruction always succeeds. All cursors remaining when @ref
|
||||
glfwTerminate is called are destroyed as well.
|
||||
Cursor destruction always succeeds. If the cursor is current for any window,
|
||||
that window will revert to the default cursor. This does not affect the cursor
|
||||
mode. All remaining cursors remaining are destroyed when @ref glfwTerminate is
|
||||
called.
|
||||
|
||||
|
||||
@subsubsection cursor_set Cursor setting
|
||||
@@ -371,14 +389,14 @@ to `GLFW_CURSOR_NORMAL`.
|
||||
|
||||
A single cursor may be set for any number of windows.
|
||||
|
||||
To remove a cursor from a window, set the cursor of that window to `NULL`.
|
||||
To revert to the default cursor, set the cursor of that window to `NULL`.
|
||||
|
||||
@code
|
||||
glfwSetCursor(window, NULL);
|
||||
@endcode
|
||||
|
||||
When a cursor is destroyed, it is removed from any window where it is set. This
|
||||
does not affect the cursor modes of those windows.
|
||||
When a cursor is destroyed, any window that has it set will revert to the
|
||||
default cursor. This does not affect the cursor mode.
|
||||
|
||||
|
||||
@subsection cursor_enter Cursor enter/leave events
|
||||
@@ -435,7 +453,9 @@ per-window state arrays that can be polled with @ref glfwGetMouseButton.
|
||||
@code
|
||||
int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
|
||||
if (state == GLFW_PRESS)
|
||||
{
|
||||
upgrade_cow();
|
||||
}
|
||||
@endcode
|
||||
|
||||
The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
@@ -443,6 +463,7 @@ The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
|
||||
This function only returns cached mouse button event state. It does not poll
|
||||
the system for the current state of the mouse button.
|
||||
|
||||
@anchor GLFW_STICKY_MOUSE_BUTTONS
|
||||
Whenever you poll state, you risk missing the state change you are looking for.
|
||||
If a pressed mouse button is released again before you poll its state, you will have
|
||||
missed the button press. The recommended solution for this is to use a
|
||||
@@ -487,21 +508,27 @@ A simple mouse wheel, being vertical, provides offsets along the Y-axis.
|
||||
|
||||
The joystick functions expose connected joysticks and controllers, with both
|
||||
referred to as joysticks. It supports up to sixteen joysticks, ranging from
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to `GLFW_JOYSTICK_LAST`. You can test
|
||||
whether a [joystick](@ref joysticks) is present with @ref glfwJoystickPresent.
|
||||
`GLFW_JOYSTICK_1`, `GLFW_JOYSTICK_2` up to and including `GLFW_JOYSTICK_16` or
|
||||
`GLFW_JOYSTICK_LAST`. You can test whether a [joystick](@ref joysticks) is
|
||||
present with @ref glfwJoystickPresent.
|
||||
|
||||
@code
|
||||
int present = glfwJoystickPresent(GLFW_JOYSTICK_1);
|
||||
@endcode
|
||||
|
||||
When GLFW is initialized, detected joysticks are added to to the beginning of
|
||||
the array, starting with `GLFW_JOYSTICK_1`. Once a joystick is detected, it
|
||||
keeps its assigned index until it is disconnected, so as joysticks are connected
|
||||
and disconnected, they will become spread out.
|
||||
the array. Once a joystick is detected, it keeps its assigned ID until it is
|
||||
disconnected or the library is terminated, so as joysticks are connected and
|
||||
disconnected, there may appear gaps in the IDs.
|
||||
|
||||
Joystick state is updated as needed when a joystick function is called and does
|
||||
not require a window to be created or @ref glfwPollEvents or @ref glfwWaitEvents
|
||||
to be called.
|
||||
Joystick axis, button and hat state is updated when polled and does not require
|
||||
a window to be created or events to be processed. However, if you want joystick
|
||||
connection and disconnection events reliably delivered to the
|
||||
[joystick callback](@ref joystick_event) then you must
|
||||
[process events](@ref events).
|
||||
|
||||
To see all the properties of all connected joysticks in real-time, run the
|
||||
`joysticks` test program.
|
||||
|
||||
|
||||
@subsection joystick_axis Joystick axis states
|
||||
@@ -512,7 +539,7 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
|
||||
const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_5, &count);
|
||||
@endcode
|
||||
|
||||
Each element in the returned array is a value between -1.0 and 1.0.
|
||||
@@ -526,11 +553,55 @@ returned array.
|
||||
|
||||
@code
|
||||
int count;
|
||||
const unsigned char* axes = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
|
||||
const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_3, &count);
|
||||
@endcode
|
||||
|
||||
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
|
||||
|
||||
@@ -539,7 +610,7 @@ glfwGetJoystickName. See the reference documentation for the lifetime of the
|
||||
returned string.
|
||||
|
||||
@code
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_1);
|
||||
const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4);
|
||||
@endcode
|
||||
|
||||
Joystick names are not guaranteed to be unique. Two joysticks of the same model
|
||||
@@ -560,7 +631,7 @@ The callback function receives the ID of the joystick that has been connected
|
||||
and disconnected and the event that occurred.
|
||||
|
||||
@code
|
||||
void joystick_callback(int joy, int event)
|
||||
void joystick_callback(int jid, int event)
|
||||
{
|
||||
if (event == GLFW_CONNECTED)
|
||||
{
|
||||
@@ -573,6 +644,165 @@ void joystick_callback(int joy, int event)
|
||||
}
|
||||
@endcode
|
||||
|
||||
For joystick connection and disconnection events to be delivered on all
|
||||
platforms, you need to call one of the [event processing](@ref events)
|
||||
functions. Joystick disconnection may also be detected and the callback
|
||||
called by joystick functions. The function will then return whatever it
|
||||
returns for a disconnected joystick.
|
||||
|
||||
|
||||
@subsection gamepad Gamepad input
|
||||
|
||||
The joystick functions provide unlabeled axes, buttons and hats, with no
|
||||
indication of where they are located on the device. Their order may also vary
|
||||
between platforms even with the same device.
|
||||
|
||||
To solve this problem the SDL community crowdsourced the
|
||||
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) project,
|
||||
a database of mappings from many different devices to an Xbox-like gamepad.
|
||||
|
||||
GLFW supports this mapping format and contains a copy of the mappings
|
||||
available at the time of release. See @ref gamepad_mapping for how to update
|
||||
this at runtime. Mappings will be assigned to joysticks automatically any time
|
||||
a joystick is connected or the mappings are updated.
|
||||
|
||||
You can check whether a joystick is both present and has a gamepad mapping with
|
||||
@ref glfwJoystickIsGamepad.
|
||||
|
||||
@code
|
||||
if (glfwJoystickIsGamepad(GLFW_JOYSTICK_2))
|
||||
{
|
||||
// Use as gamepad
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you are only interested in gamepad input you can use this function instead of
|
||||
@ref glfwJoystickPresent.
|
||||
|
||||
You can query the human-readable name provided by the gamepad mapping with @ref
|
||||
glfwGetGamepadName. This may or may not be the same as the
|
||||
[joystick name](@ref joystick_name).
|
||||
|
||||
@code
|
||||
const char* name = glfwGetGamepadName(GLFW_JOYSTICK_7);
|
||||
@endcode
|
||||
|
||||
To retrieve the gamepad state of a joystick, call @ref glfwGetGamepadState.
|
||||
|
||||
@code
|
||||
GLFWgamepadstate state;
|
||||
|
||||
if (glfwGetGamepadState(GLFW_JOYSTICK_3, &state))
|
||||
{
|
||||
if (state.buttons[GLFW_GAMEPAD_BUTTON_A])
|
||||
{
|
||||
input_jump();
|
||||
}
|
||||
|
||||
input_speed(state.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The @ref GLFWgamepadstate struct has two arrays; one for button states and one
|
||||
for axis states. The values for each button and axis are the same as for the
|
||||
@ref glfwGetJoystickButtons and @ref glfwGetJoystickAxes functions, i.e.
|
||||
`GLFW_PRESS` or `GLFW_RELEASE` for buttons and -1.0 to 1.0 inclusive for axes.
|
||||
|
||||
The sizes of the arrays and the positions within each array are fixed.
|
||||
|
||||
The [button indices](@ref gamepad_buttons) are `GLFW_GAMEPAD_BUTTON_A`,
|
||||
`GLFW_GAMEPAD_BUTTON_B`, `GLFW_GAMEPAD_BUTTON_X`, `GLFW_GAMEPAD_BUTTON_Y`,
|
||||
`GLFW_GAMEPAD_BUTTON_LEFT_BUMPER`, `GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER`,
|
||||
`GLFW_GAMEPAD_BUTTON_BACK`, `GLFW_GAMEPAD_BUTTON_START`,
|
||||
`GLFW_GAMEPAD_BUTTON_GUIDE`, `GLFW_GAMEPAD_BUTTON_LEFT_THUMB`,
|
||||
`GLFW_GAMEPAD_BUTTON_RIGHT_THUMB`, `GLFW_GAMEPAD_BUTTON_DPAD_UP`,
|
||||
`GLFW_GAMEPAD_BUTTON_DPAD_RIGHT`, `GLFW_GAMEPAD_BUTTON_DPAD_DOWN` and
|
||||
`GLFW_GAMEPAD_BUTTON_DPAD_LEFT`.
|
||||
|
||||
For those who prefer, there are also the `GLFW_GAMEPAD_BUTTON_CROSS`,
|
||||
`GLFW_GAMEPAD_BUTTON_CIRCLE`, `GLFW_GAMEPAD_BUTTON_SQUARE` and
|
||||
`GLFW_GAMEPAD_BUTTON_TRIANGLE` aliases for the A, B, X and Y button indices.
|
||||
|
||||
The [axis indices](@ref gamepad_axes) are `GLFW_GAMEPAD_AXIS_LEFT_X`,
|
||||
`GLFW_GAMEPAD_AXIS_LEFT_Y`, `GLFW_GAMEPAD_AXIS_RIGHT_X`,
|
||||
`GLFW_GAMEPAD_AXIS_RIGHT_Y`, `GLFW_GAMEPAD_AXIS_LEFT_TRIGGER` and
|
||||
`GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER`.
|
||||
|
||||
The `GLFW_GAMEPAD_BUTTON_LAST` and `GLFW_GAMEPAD_AXIS_LAST` constants equal
|
||||
the largest available index for each array.
|
||||
|
||||
|
||||
@subsection gamepad_mapping Gamepad mappings
|
||||
|
||||
GLFW contains a copy of the mappings available in
|
||||
[SDL_GameControllerDB](https://github.com/gabomdq/SDL_GameControllerDB) at the
|
||||
time of release. Newer ones can be added at runtime with @ref
|
||||
glfwUpdateGamepadMappings.
|
||||
|
||||
@code
|
||||
const char* mappings = load_file_contents("gamecontrollerdb.txt");
|
||||
|
||||
glfwUpdateGamepadMappings(mappings);
|
||||
@endcode
|
||||
|
||||
This function supports everything from single lines up to and including the
|
||||
unmodified contents of the whole `gamecontrollerdb.txt` file.
|
||||
|
||||
Below is a description of the mapping format. Please keep in mind that __this
|
||||
description is not authoritative__. The format is defined by the SDL and
|
||||
SDL_GameControllerDB projects and their documentation and code takes precedence.
|
||||
|
||||
Each mapping is a single line of comma-separated values describing the GUID,
|
||||
name and layout of the gamepad. Lines that do not begin with a hexadecimal
|
||||
digit are ignored.
|
||||
|
||||
The first value is always the gamepad GUID, a 32 character long hexadecimal
|
||||
string that typically identifies its make, model, revision and the type of
|
||||
connection to the computer. When this information is not available, the GUID is
|
||||
generated using the gamepad name. GLFW uses the SDL 2.0.5+ GUID format but can
|
||||
convert from the older formats.
|
||||
|
||||
The second value is always the human-readable name of the gamepad.
|
||||
|
||||
All subsequent values are in the form `<field>:<value>` and describe the layout
|
||||
of the mapping. These fields may not all be present and may occur in any order.
|
||||
|
||||
The button fields are `a`, `b`, `c`, `d`, `back`, `start`, `guide`, `dpup`,
|
||||
`dpright`, `dpdown`, `dpleft`, `leftshoulder`, `rightshoulder`, `leftstick` and
|
||||
`rightstick`.
|
||||
|
||||
The axis fields are `leftx`, `lefty`, `rightx`, `righty`, `lefttrigger` and
|
||||
`righttrigger`.
|
||||
|
||||
The value of an axis or button field can be a joystick button, a joystick axis,
|
||||
a hat bitmask or empty. Joystick buttons are specified as `bN`, for example
|
||||
`b2` for the third button. Joystick axes are specified as `aN`, for example
|
||||
`a7` for the eighth button. Joystick hat bit masks are specified as `hN.N`, for
|
||||
example `h0.8` for left on the first hat. More than one bit may be set in the
|
||||
mask.
|
||||
|
||||
The hat bit mask match the [hat states](@ref hat_state) in the joystick
|
||||
functions.
|
||||
|
||||
There is also the special `platform` field that specifies which platform the
|
||||
mapping is valid for. Possible values are `Windows`, `Mac OS X` and `Linux`.
|
||||
Mappings without this field will always be considered valid.
|
||||
|
||||
Below is an example of what a gamepad mapping might look like. It is the
|
||||
one built into GLFW for Xbox controllers accessed via the XInput API on Windows.
|
||||
This example has been broken into several lines to fit on the page, but real
|
||||
gamepad mappings must be a single line.
|
||||
|
||||
@code{.unparsed}
|
||||
78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,
|
||||
b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,
|
||||
rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,
|
||||
righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
|
||||
@endcode
|
||||
|
||||
@note GLFW does not yet support the range and inversion modifiers `+`, `-` and
|
||||
`~` that were recently added to SDL.
|
||||
|
||||
|
||||
@section time Time input
|
||||
|
||||
@@ -619,7 +849,9 @@ reference documentation for the lifetime of the returned string.
|
||||
@code
|
||||
const char* text = glfwGetClipboardString(window);
|
||||
if (text)
|
||||
{
|
||||
insert_text(text);
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the clipboard is empty or if its contents could not be converted, `NULL` is
|
||||
|
||||
+1
-1
@@ -111,6 +111,6 @@ which is generated from the `glfw_config.h.in` file by CMake.
|
||||
Configuration macros the same style as tokens in the public interface, except
|
||||
with a leading underscore.
|
||||
|
||||
Examples: `_GLFW_HAS_XF86VM`
|
||||
Examples: `_GLFW_USE_HYBRID_HPG`
|
||||
|
||||
*/
|
||||
|
||||
+137
-43
@@ -4,10 +4,10 @@
|
||||
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the basic concepts of GLFW and describes initialization reference
|
||||
This guide introduces the basic concepts of GLFW and describes initialization,
|
||||
error handling and API guarantees and limitations. For a broad but shallow
|
||||
tutorial, see @ref quick_guide instead. For details on a specific function, see the
|
||||
[reference documentation](@ref init).
|
||||
tutorial, see @ref quick_guide instead. For details on a specific function in
|
||||
this category, see the @ref init.
|
||||
|
||||
There are also guides for the other areas of GLFW.
|
||||
|
||||
@@ -30,12 +30,15 @@ successfully initialized, and only from the main thread.
|
||||
|
||||
- @ref glfwGetVersion
|
||||
- @ref glfwGetVersionString
|
||||
- @ref glfwGetError
|
||||
- @ref glfwSetErrorCallback
|
||||
- @ref glfwInitHint
|
||||
- @ref glfwInitHintString
|
||||
- @ref glfwInit
|
||||
- @ref glfwTerminate
|
||||
|
||||
Calling any other function before that time will cause a @ref
|
||||
GLFW_NOT_INITIALIZED error.
|
||||
Calling any other function before successful initialization will cause a @ref
|
||||
GLFW_NOT_INITIALIZED error.
|
||||
|
||||
|
||||
@subsection intro_init_init Initializing GLFW
|
||||
@@ -50,13 +53,72 @@ if (!glfwInit())
|
||||
}
|
||||
@endcode
|
||||
|
||||
If any part of initialization fails, all remaining bits are terminated as if
|
||||
@ref glfwTerminate was called. The library only needs to be initialized once
|
||||
and additional calls to an already initialized library will simply return
|
||||
If any part of initialization fails, any parts that succeeded are terminated as
|
||||
if @ref glfwTerminate had been called. The library only needs to be initialized
|
||||
once and additional calls to an already initialized library will simply return
|
||||
`GLFW_TRUE` immediately.
|
||||
|
||||
Once the library has been successfully initialized, it should be terminated
|
||||
before the application exits.
|
||||
before the application exits. Modern systems are very good at freeing resources
|
||||
allocated by programs that simply exit, but GLFW sometimes has to change global
|
||||
system settings and these might not be restored without termination.
|
||||
|
||||
|
||||
@subsection init_hints Initialization hints
|
||||
|
||||
Initialization hints are set before @ref glfwInit and affect how the library
|
||||
behaves until termination. Integer type hints are set with @ref glfwInitHint
|
||||
and string type hints with @ref glfwInitHintString.
|
||||
|
||||
@code
|
||||
glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
The values you set hints to are never reset by GLFW, but they only take effect
|
||||
during initialization. Once GLFW has been initialized, any values you set will
|
||||
be ignored until the library is terminated and initialized again.
|
||||
|
||||
Some hints are platform specific. These may be set on any platform but they
|
||||
will only affect their specific platform. Other platforms will simply ignore
|
||||
them. Setting these hints requires no platform specific headers or functions.
|
||||
|
||||
@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. Set this with @ref glfwInitHint.
|
||||
|
||||
|
||||
@subsubsection init_hints_osx macOS specific init hints
|
||||
|
||||
@anchor GLFW_COCOA_CHDIR_RESOURCES
|
||||
__GLFW_COCOA_CHDIR_RESOURCES__ specifies whether to set the current directory to
|
||||
the application to the `Contents/Resources` subdirectory of the application's
|
||||
bundle, if present. Set this with @ref glfwInitHint.
|
||||
|
||||
@anchor GLFW_COCOA_MENUBAR
|
||||
__GLFW_COCOA_MENUBAR__ specifies whether to create a basic menu bar, either from
|
||||
a nib or manually, when the first window is created, which is when AppKit is
|
||||
initialized. Set this with @ref glfwInitHint.
|
||||
|
||||
|
||||
@subsubsection init_hints_x11 X11 specific init hints
|
||||
|
||||
@anchor GLFW_X11_WM_CLASS_NAME
|
||||
@anchor GLFW_X11_WM_CLASS_CLASS
|
||||
__GLFW_X11_WM_CLASS_NAME__ and __GLFW_X11_WM_CLASS_CLASS__ specifies the desired
|
||||
ASCII encoded name and class parts of the ICCCM `WM_CLASS` hint for all windows.
|
||||
Set this with @ref glfwInitHintString.
|
||||
|
||||
|
||||
@subsubsection init_hints_values Supported and default 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_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
@ref GLFW_X11_WM_CLASS_NAME | `""` | An ASCII encoded `WM_CLASS` name
|
||||
@ref GLFW_X11_WM_CLASS_CLASS | `""` | An ASCII encoded `WM_CLASS` class
|
||||
|
||||
|
||||
@subsection intro_init_terminate Terminating GLFW
|
||||
@@ -70,7 +132,7 @@ glfwTerminate();
|
||||
|
||||
This will destroy any remaining window, monitor and cursor objects, restore any
|
||||
modified gamma ramps, re-enable the screensaver if it had been disabled and free
|
||||
any resources allocated by GLFW.
|
||||
any other resources allocated by GLFW.
|
||||
|
||||
Once the library is terminated, it is as if it had never been initialized and
|
||||
you will need to initialize it again before being able to use GLFW. If the
|
||||
@@ -81,41 +143,76 @@ immediately.
|
||||
@section error_handling Error handling
|
||||
|
||||
Some GLFW functions have return values that indicate an error, but this is often
|
||||
not very helpful when trying to figure out _why_ the error occurred. Some
|
||||
functions also return otherwise valid values on error. Finally, far from all
|
||||
GLFW functions have return values.
|
||||
not very helpful when trying to figure out what happened or why it occurred.
|
||||
Other functions have no return value reserved for errors, so error notification
|
||||
needs a separate channel. Finally, far from all GLFW functions have return
|
||||
values.
|
||||
|
||||
This is where the error callback comes in. This callback is called whenever an
|
||||
error occurs. It is set with @ref glfwSetErrorCallback, a function that may be
|
||||
called regardless of whether GLFW is initialized.
|
||||
The last [error code](@ref errors) for the calling thread can be queried at any
|
||||
time with @ref glfwGetError.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
int code = glfwGetError(NULL);
|
||||
|
||||
if (code != GLFW_NO_ERROR)
|
||||
handle_error(code);
|
||||
@endcode
|
||||
|
||||
The error callback receives a human-readable description of the error and (when
|
||||
possible) its cause. The description encoded as UTF-8. The callback is also
|
||||
provided with an [error code](@ref errors).
|
||||
|
||||
@code
|
||||
void error_callback(int error, const char* description)
|
||||
{
|
||||
puts(description);
|
||||
}
|
||||
@endcode
|
||||
If no error has occurred since the last call, @ref GLFW_NO_ERROR (zero) is
|
||||
returned. The error is cleared before the function returns.
|
||||
|
||||
The error code indicates the general category of the error. Some error codes,
|
||||
such as @ref GLFW_NOT_INITIALIZED has only a single meaning, whereas others like
|
||||
@ref GLFW_PLATFORM_ERROR are used for many different errors.
|
||||
|
||||
The description string is only valid until the error callback returns, as it may
|
||||
have been generated specifically for that error. This lets GLFW provide much
|
||||
more specific error descriptions but means you must make a copy if you want to
|
||||
keep the description string.
|
||||
GLFW often has more information about an error than its general category. You
|
||||
can retrieve a UTF-8 encoded human-readable description along with the error
|
||||
code. If no error has occurred since the last call, the description is set to
|
||||
`NULL`.
|
||||
|
||||
@note Relying on erroneous behavior is not forward compatible. In other words,
|
||||
do not rely on a currently invalid call to generate a specific error, as that
|
||||
same call may in future versions generate a different error or become valid.
|
||||
@code
|
||||
const char* description;
|
||||
int code = glfwGetError(&description);
|
||||
|
||||
if (description)
|
||||
display_error_message(code, description);
|
||||
@endcode
|
||||
|
||||
The retrieved description string is only valid until the next error occurs.
|
||||
This means you must make a copy of it if you want to keep it.
|
||||
|
||||
You can also set an error callback, which will be called each time an error
|
||||
occurs. It is set with @ref glfwSetErrorCallback.
|
||||
|
||||
@code
|
||||
glfwSetErrorCallback(error_callback);
|
||||
@endcode
|
||||
|
||||
The error callback receives the same error code and human-readable description
|
||||
returned by @ref glfwGetError.
|
||||
|
||||
@code
|
||||
void error_callback(int code, const char* description)
|
||||
{
|
||||
display_error_message(code, description);
|
||||
}
|
||||
@endcode
|
||||
|
||||
The error callback is called after the error is stored, so calling @ref
|
||||
glfwGetError from within the error callback returns the same values as the
|
||||
callback argument.
|
||||
|
||||
The description string passed to the callback is only valid until the error
|
||||
callback returns. This means you must make a copy of it if you want to keep it.
|
||||
|
||||
__Reported errors are never fatal.__ As long as GLFW was successfully
|
||||
initialized, it will remain initialized and in a safe state until terminated
|
||||
regardless of how many errors occur. If an error occurs during initialization
|
||||
that causes @ref glfwInit to fail, any part of the library that was initialized
|
||||
will be safely terminated.
|
||||
|
||||
Do not rely on a currently invalid call to generate a specific error, as in the
|
||||
future that same call may generate a different error or become valid.
|
||||
|
||||
|
||||
@section coordinate_systems Coordinate systems
|
||||
@@ -186,14 +283,10 @@ releases.
|
||||
|
||||
@subsection reentrancy Reentrancy
|
||||
|
||||
GLFW event processing and object creation and destruction are not reentrant.
|
||||
This means that the following functions must not be called from any callback
|
||||
function:
|
||||
GLFW event processing and object destruction are not reentrant. This means that
|
||||
the following functions must not be called from any callback function:
|
||||
|
||||
- @ref glfwCreateWindow
|
||||
- @ref glfwDestroyWindow
|
||||
- @ref glfwCreateCursor
|
||||
- @ref glfwCreateStandardCursor
|
||||
- @ref glfwDestroyCursor
|
||||
- @ref glfwPollEvents
|
||||
- @ref glfwWaitEvents
|
||||
@@ -282,9 +375,10 @@ allow calls from any thread in future releases.
|
||||
|
||||
@subsection compatibility Version compatibility
|
||||
|
||||
GLFW guarantees binary backward compatibility with earlier minor versions of the
|
||||
API. This means that you can drop in a newer version of the GLFW DLL / shared
|
||||
library / dynamic library and existing applications will continue to run.
|
||||
GLFW guarantees source and binary backward compatibility with earlier minor
|
||||
versions of the API. This means that you can drop in a newer version of the
|
||||
library and existing programs will continue to compile and existing binaries
|
||||
will continue to run.
|
||||
|
||||
Once a function or constant has been added, the signature of that function or
|
||||
value of that constant will remain unchanged until the next major version of
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ GLFW is a free, Open Source, multi-platform library for OpenGL, OpenGL ES and
|
||||
Vulkan application development. It provides a simple, platform-independent API
|
||||
for creating windows, contexts and surfaces, reading input, handling events, etc.
|
||||
|
||||
See @ref news_32 for release highlights or the
|
||||
See @ref news_33 for highlights or the
|
||||
[version history](http://www.glfw.org/changelog.html) for details.
|
||||
|
||||
@ref quick_guide is a guide for users new to GLFW. It takes you through how to
|
||||
|
||||
+13
-4
@@ -5,12 +5,13 @@
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the monitor related functions of GLFW. For details on
|
||||
a specific function, see the [reference documentation](@ref monitor). There are
|
||||
also guides for the other areas of GLFW.
|
||||
a specific function in this category, see the @ref monitor. There are also
|
||||
guides for the other areas of GLFW.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@@ -194,8 +195,8 @@ glfwSetGammaRamp(monitor, &ramp);
|
||||
The gamma ramp data is copied before the function returns, so there is no need
|
||||
to keep it around once the ramp has been set.
|
||||
|
||||
@note It is recommended to use gamma ramps of size 256, as that is the size
|
||||
supported by all graphics cards on all platforms.
|
||||
It is recommended that your gamma ramp have the same size as the current gamma
|
||||
ramp for that monitor.
|
||||
|
||||
The current gamma ramp for a monitor is returned by @ref glfwGetGammaRamp. See
|
||||
the reference documentation for the lifetime of the returned structure.
|
||||
@@ -212,4 +213,12 @@ glfwSetGammaRamp with the resulting ramp.
|
||||
glfwSetGamma(monitor, 1.0);
|
||||
@endcode
|
||||
|
||||
To experiment with gamma correction via the @ref glfwSetGamma function, run the
|
||||
`gamma` test program.
|
||||
|
||||
@note The software controlled gamma ramp is applied _in addition_ to the
|
||||
hardware gamma correction, which today is usually an approximation of sRGB
|
||||
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
|
||||
produce the default (usually sRGB-like) behavior.
|
||||
|
||||
*/
|
||||
|
||||
+8
-1
@@ -434,7 +434,7 @@ GLFW 3 does not by default include the GLU header and GLU itself has been
|
||||
deprecated by [Khronos](https://en.wikipedia.org/wiki/Khronos_Group). __New
|
||||
projects should not use GLU__, but if you need it for legacy code that
|
||||
has been moved to GLFW 3, you can request that the GLFW header includes it by
|
||||
defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
|
||||
defining @ref GLFW_INCLUDE_GLU before the inclusion of the GLFW header.
|
||||
|
||||
@par Old syntax
|
||||
@code
|
||||
@@ -447,6 +447,13 @@ defining `GLFW_INCLUDE_GLU` before the inclusion of the GLFW header.
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
There are many libraries that offer replacements for the functionality offered
|
||||
by GLU. For the matrix helper functions, see math libraries like
|
||||
[GLM](https://github.com/g-truc/glm) (for C++),
|
||||
[linmath.h](https://github.com/datenwolf/linmath.h) (for C) and others. For the
|
||||
tessellation functions, see for example
|
||||
[libtess2](https://github.com/memononen/libtess2).
|
||||
|
||||
|
||||
@section moving_tables Name change tables
|
||||
|
||||
|
||||
+161
-43
@@ -1,8 +1,124 @@
|
||||
/*!
|
||||
|
||||
@page news New features
|
||||
@page news Release notes
|
||||
|
||||
@section news_32 New features in 3.2
|
||||
@section news_33 Release notes for 3.3
|
||||
|
||||
|
||||
@subsection news_33_geterror Error query
|
||||
|
||||
GLFW now supports querying the last error code for the calling thread and its
|
||||
human-readable description with @ref glfwGetError.
|
||||
|
||||
@see @ref error_handling
|
||||
|
||||
|
||||
@subsection news_33_gamepad SDL_GameControllerDB support and gamepad input
|
||||
|
||||
GLFW now supports remapping of gamepads and controllers to a 360-like controller
|
||||
layout with @ref glfwJoystickIsGamepad, @ref glfwGetJoystickGUID, @ref
|
||||
glfwGetGamepadName, @ref glfwGetGamepadState and @ref glfwUpdateGamepadMappings,
|
||||
and the input state struct @ref GLFWgamepadstate.
|
||||
|
||||
@sa @ref gamepad
|
||||
|
||||
|
||||
@subsection news_33_attention User attention request
|
||||
|
||||
GLFW now supports requesting user attention to a specific window (on macOS to
|
||||
the application as a whole) with @ref glfwRequestWindowAttention.
|
||||
|
||||
@see @ref window_attention
|
||||
|
||||
|
||||
@subsection news_33_maximize Window maximization callback
|
||||
|
||||
GLFW now supports notifying the application that the window has been maximized
|
||||
@ref glfwSetWindowMaximizeCallback.
|
||||
|
||||
@see @ref window_maximize
|
||||
|
||||
|
||||
@subsection news_33_keyscancode Platform-specific key scancode query
|
||||
|
||||
GLFW now supports querying the platform dependent scancode of any physical key
|
||||
with @ref glfwGetKeyScancode.
|
||||
|
||||
@see @ref input_key
|
||||
|
||||
|
||||
@subsection news_33_setwindowattrib Support for updating window attributes
|
||||
|
||||
GLFW now supports changing the [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
|
||||
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
|
||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) attributes for existing
|
||||
windows with @ref glfwSetWindowAttrib.
|
||||
|
||||
@see @ref window_attribs
|
||||
|
||||
|
||||
@subsection news_33_inithint Support for initialization hints
|
||||
|
||||
GLFW now supports setting library initialization hints with @ref glfwInitHint
|
||||
or @ref glfwInitHintString. These must be set before initialization to take
|
||||
effect.
|
||||
|
||||
@see @ref init_hints
|
||||
|
||||
|
||||
@subsection news_33_platformhints Support for platform specific hints
|
||||
|
||||
GLFW now supports platform specific init and window hints to control system
|
||||
features that are only available on a single platform.
|
||||
|
||||
@see @ref init_hints_osx
|
||||
@see @ref window_hints_osx
|
||||
|
||||
|
||||
@subsection news_33_joyhats Support for joystick hats
|
||||
|
||||
GLFW now supports querying the hats (or POVs or D-pads) of a joystick with @ref
|
||||
glfwGetJoystickHats. Hats are by default also exposed as buttons, but this can
|
||||
be disabled with the @ref GLFW_JOYSTICK_HAT_BUTTONS init hint.
|
||||
|
||||
@see @ref joystick_hat
|
||||
|
||||
|
||||
@subsection news_33_centercursor Cursor centering window hint
|
||||
|
||||
GLFW now supports controlling whether the cursor is centered over newly created
|
||||
full screen windows with the [GLFW_CENTER_CURSOR](@ref GLFW_CENTER_CURSOR_hint)
|
||||
window hint. It is enabled by default.
|
||||
|
||||
|
||||
@subsection news_33_rawmotion Support for raw mouse motion
|
||||
|
||||
GLFW now uses raw (unscaled and unaccelerated) mouse motion in disabled cursor
|
||||
mode on platforms where this is available, specifically Windows and X11.
|
||||
|
||||
|
||||
@subsection news_33_moltenvk Support for Vulkan on macOS via MoltenVK
|
||||
|
||||
GLFW now supports the `VK_MVK_macos_surface` window surface creation extension
|
||||
provided by [MoltenVK](https://moltengl.com/moltenvk/).
|
||||
|
||||
@see @ref vulkan_guide
|
||||
|
||||
|
||||
@subsection news_33_osmesa OSMesa backend for headless software rendering
|
||||
|
||||
GLFW now supports creating offscreen OpenGL contexts using
|
||||
[OSMesa](https://www.mesa3d.org/osmesa.html) by setting
|
||||
[GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint) to
|
||||
`GLFW_OSMESA_CONTEXT_API`.
|
||||
|
||||
There is also a new null backend that uses OSMesa as its native context
|
||||
creation API, intended for automated testing. This backend does not provide
|
||||
input.
|
||||
|
||||
|
||||
@section news_32 Release notes for 3.2
|
||||
|
||||
|
||||
@subsection news_32_vulkan Support for Vulkan
|
||||
@@ -11,7 +127,7 @@ GLFW now supports basic integration with Vulkan with @ref glfwVulkanSupported,
|
||||
@ref glfwGetRequiredInstanceExtensions, @ref glfwGetInstanceProcAddress, @ref
|
||||
glfwGetPhysicalDevicePresentationSupport and @ref glfwCreateWindowSurface.
|
||||
Vulkan header inclusion can be selected with
|
||||
[GLFW_INCLUDE_VULKAN](@ref build_macros).
|
||||
@ref GLFW_INCLUDE_VULKAN.
|
||||
|
||||
|
||||
@subsection news_32_setwindowmonitor Window mode switching
|
||||
@@ -24,7 +140,7 @@ the monitor and desired resolution and refresh rate of full screen windows with
|
||||
@subsection news_32_maximize Window maxmimization support
|
||||
|
||||
GLFW now supports window maximization with @ref glfwMaximizeWindow and the
|
||||
[GLFW_MAXIMIZED](@ref window_attribs_wnd) window hint and attribute.
|
||||
@ref GLFW_MAXIMIZED window hint and attribute.
|
||||
|
||||
|
||||
@subsection news_32_focus Window input focus control
|
||||
@@ -69,21 +185,21 @@ with @ref glfwSetJoystickCallback.
|
||||
|
||||
@subsection news_32_noapi Context-less windows
|
||||
|
||||
GLFW now supports creating windows without a OpenGL or OpenGL ES context with
|
||||
[GLFW_NO_API](@ref window_hints_ctx).
|
||||
GLFW now supports creating windows without a OpenGL or OpenGL ES context by
|
||||
setting the [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
|
||||
|
||||
|
||||
@subsection news_32_contextapi Run-time context creation API selection
|
||||
|
||||
GLFW now supports selecting the context creation API at run-time with the
|
||||
[GLFW_CONTEXT_CREATION_API](@ref window_hints_ctx) window hint value.
|
||||
GLFW now supports selecting and querying the context creation API at run-time
|
||||
with the @ref GLFW_CONTEXT_CREATION_API hint and attribute.
|
||||
|
||||
|
||||
@subsection news_32_noerror Error-free context creation
|
||||
|
||||
GLFW now supports creating OpenGL and OpenGL ES contexts that do not emit errors
|
||||
with the [GLFW_CONTEXT_NO_ERROR](@ref window_hints_ctx) window hint, provided
|
||||
the machine supports the `GL_KHR_no_error` extension.
|
||||
GLFW now supports creating and querying OpenGL and OpenGL ES contexts that do
|
||||
not emit errors with the @ref GLFW_CONTEXT_NO_ERROR hint, provided the machine
|
||||
supports the `GL_KHR_no_error` extension.
|
||||
|
||||
|
||||
@subsection news_32_cmake CMake config-file package support
|
||||
@@ -93,7 +209,7 @@ GLFW now supports being used as a
|
||||
easy linking with the library and its dependencies.
|
||||
|
||||
|
||||
@section news_31 New features in 3.1
|
||||
@section news_31 Release notes for 3.1
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
@@ -137,21 +253,21 @@ client area of a window, with @ref glfwGetWindowFrameSize.
|
||||
@subsection news_31_autoiconify Simultaneous multi-monitor rendering
|
||||
|
||||
GLFW now supports disabling auto-iconification of full screen windows with
|
||||
the [GLFW_AUTO_ICONIFY](@ref window_hints_wnd) window hint. This is intended
|
||||
for people building multi-monitor installations, where you need windows to stay
|
||||
in full screen despite losing input focus.
|
||||
the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint. This is
|
||||
intended for people building multi-monitor installations, where you need windows
|
||||
to stay in full screen despite losing input focus.
|
||||
|
||||
|
||||
@subsection news_31_floating Floating windows
|
||||
|
||||
GLFW now supports floating windows, also called topmost or always on top, for
|
||||
easier debugging with the [GLFW_FLOATING](@ref window_hints_wnd) window hint.
|
||||
easier debugging with the @ref GLFW_FLOATING window hint and attribute.
|
||||
|
||||
|
||||
@subsection news_31_focused Initially unfocused windows
|
||||
|
||||
GLFW now supports preventing a windowed mode window from gaining input focus on
|
||||
creation, with the [GLFW_FOCUSED](@ref window_hints_wnd) window hint.
|
||||
creation, with the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint.
|
||||
|
||||
|
||||
@subsection news_31_direct Direct access for window attributes and cursor position
|
||||
@@ -172,24 +288,24 @@ being input, for example if the Control key is held down.
|
||||
|
||||
@subsection news_31_single Single buffered framebuffers
|
||||
|
||||
GLFW now supports the creation of single buffered windows, with the
|
||||
[GLFW_DOUBLEBUFFER](@ref window_hints_fb) window hint.
|
||||
GLFW now supports the creation of single buffered windows, with the @ref
|
||||
GLFW_DOUBLEBUFFER hint.
|
||||
|
||||
|
||||
@subsection news_31_glext Macro for including extension header
|
||||
|
||||
GLFW now includes the extension header appropriate for the chosen OpenGL or
|
||||
OpenGL ES header when [GLFW_INCLUDE_GLEXT](@ref build_macros) is defined. GLFW
|
||||
does not provide these headers. They must be provided by your development
|
||||
environment or your OpenGL or OpenGL ES SDK.
|
||||
OpenGL ES header when @ref GLFW_INCLUDE_GLEXT is defined. GLFW does not provide
|
||||
these headers. They must be provided by your development environment or your
|
||||
OpenGL or OpenGL ES SDK.
|
||||
|
||||
|
||||
@subsection news_31_release Context release behaviors
|
||||
|
||||
GLFW now supports controlling whether the pipeline is flushed when a context is
|
||||
made non-current, with the
|
||||
[GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint, provided the
|
||||
machine supports the `GL_KHR_context_flush_control` extension.
|
||||
GLFW now supports controlling and querying whether the pipeline is flushed when
|
||||
a context is made non-current, with the @ref GLFW_CONTEXT_RELEASE_BEHAVIOR hint
|
||||
and attribute, provided the machine supports the `GL_KHR_context_flush_control`
|
||||
extension.
|
||||
|
||||
|
||||
@subsection news_31_wayland (Experimental) Wayland support
|
||||
@@ -204,7 +320,7 @@ GLFW now has an _experimental_ Mir display server backend that can be selected
|
||||
on Linux with a CMake option.
|
||||
|
||||
|
||||
@section news_30 New features in 3.0
|
||||
@section news_30 Release notes for 3.0
|
||||
|
||||
These are the release highlights. For a full list of changes see the
|
||||
[version history](http://www.glfw.org/changelog.html).
|
||||
@@ -264,11 +380,11 @@ glfwSetGamma, which generates a ramp from a gamma value and then sets it.
|
||||
@subsection news_30_gles OpenGL ES support
|
||||
|
||||
GLFW now supports the creation of OpenGL ES contexts, by setting the
|
||||
`GLFW_CLIENT_API` window hint to `GLFW_OPENGL_ES_API`, where creation of such
|
||||
contexts are supported. Note that GLFW _does not implement_ OpenGL ES, so your
|
||||
driver must provide support in a way usable by GLFW. Modern Nvidia and Intel
|
||||
drivers support creation of OpenGL ES context using the GLX and WGL APIs, while
|
||||
AMD provides an EGL implementation instead.
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_OPENGL_ES_API`, where
|
||||
creation of such contexts are supported. Note that GLFW _does not implement_
|
||||
OpenGL ES, so your driver must provide support in a way usable by GLFW. Modern
|
||||
Nvidia and Intel drivers support creation of OpenGL ES context using the GLX and
|
||||
WGL APIs, while AMD provides an EGL implementation instead.
|
||||
|
||||
|
||||
@subsection news_30_egl (Experimental) EGL support
|
||||
@@ -279,11 +395,12 @@ through CMake options.
|
||||
|
||||
@subsection news_30_hidpi High-DPI support
|
||||
|
||||
GLFW now supports high-DPI monitors on both Windows and OS X, giving windows full
|
||||
resolution framebuffers where other UI elements are scaled up. To achieve this,
|
||||
@ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have been
|
||||
added. These work with pixels, while the rest of the GLFW API works with screen
|
||||
coordinates. This is important as OpenGL uses pixels, not screen coordinates.
|
||||
GLFW now supports high-DPI monitors on both Windows and macOS, giving windows
|
||||
full resolution framebuffers where other UI elements are scaled up. To achieve
|
||||
this, @ref glfwGetFramebufferSize and @ref glfwSetFramebufferSizeCallback have
|
||||
been added. These work with pixels, while the rest of the GLFW API works with
|
||||
screen coordinates. This is important as OpenGL uses pixels, not screen
|
||||
coordinates.
|
||||
|
||||
|
||||
@subsection news_30_error Error callback
|
||||
@@ -338,16 +455,17 @@ to @ref glfwCreateWindow.
|
||||
@subsection news_30_hidden Hidden windows
|
||||
|
||||
Windows can now be hidden with @ref glfwHideWindow, shown using @ref
|
||||
glfwShowWindow and created initially hidden with the `GLFW_VISIBLE` window hint.
|
||||
This allows for off-screen rendering in a way compatible with most drivers, as
|
||||
well as moving a window to a specific position before showing it.
|
||||
glfwShowWindow and created initially hidden with the @ref GLFW_VISIBLE window
|
||||
hint and attribute. This allows for off-screen rendering in a way compatible
|
||||
with most drivers, as well as moving a window to a specific position before
|
||||
showing it.
|
||||
|
||||
|
||||
@subsection news_30_undecorated Undecorated windows
|
||||
|
||||
Windowed mode windows can now be created without decorations, i.e. things like
|
||||
a frame, a title bar, with the `GLFW_DECORATED` window hint. This allows for
|
||||
the creation of things like splash screens.
|
||||
Windowed mode windows can now be created without decorations, e.g. things like
|
||||
a frame, a title bar, with the @ref GLFW_DECORATED window hint and attribute.
|
||||
This allows for the creation of things like splash screens.
|
||||
|
||||
|
||||
@subsection news_30_keymods Modifier key bit masks
|
||||
|
||||
+1
-1
@@ -340,7 +340,7 @@ The program above can be found in the
|
||||
[source package](http://www.glfw.org/download.html) as `examples/simple.c`
|
||||
and is compiled along with all other examples when you build GLFW. If you
|
||||
built GLFW from the source package then already have this as `simple.exe` on
|
||||
Windows, `simple` on Linux or `simple.app` on OS X.
|
||||
Windows, `simple` on Linux or `simple.app` on macOS.
|
||||
|
||||
This tutorial used only a few of the many functions GLFW provides. There are
|
||||
guides for each of the areas covered by GLFW. Each guide will introduce all the
|
||||
|
||||
+39
-15
@@ -11,16 +11,22 @@ with Vulkan concepts like loaders, devices, queues and surfaces and leaves it to
|
||||
the Vulkan documentation to explain the details of Vulkan functions.
|
||||
|
||||
To develop for Vulkan you should install an SDK for your platform, for example
|
||||
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/). Apart from the headers and
|
||||
libraries, it also provides the validation layers necessary for development.
|
||||
the [LunarG Vulkan SDK](https://vulkan.lunarg.com/) for Windows and Linux or
|
||||
[MoltenVK](https://moltengl.com/moltenvk/) for macOS. Apart from headers and
|
||||
link libraries, they should also provide the validation layers necessary for
|
||||
development.
|
||||
|
||||
The GLFW library does not need the Vulkan SDK to enable support for Vulkan.
|
||||
However, any Vulkan-specific test and example programs are built only if the
|
||||
CMake files find a Vulkan SDK.
|
||||
|
||||
For details on a specific function, see the
|
||||
[reference documentation](@ref vulkan). There are also guides for the other
|
||||
areas of the GLFW API.
|
||||
@macos Because MoltenVK is typically not installed system-wide, you will need to
|
||||
point CMake to it using the `CMAKE_FRAMEWORK_PATH` variable when configuring the
|
||||
GLFW source tree. Set this variable to the `MoltenVK/macOS` subdirectory of the
|
||||
SDK, either on the command-line or in the CMake GUI.
|
||||
|
||||
For details on a specific function in this category, see the @ref vulkan. There
|
||||
are also guides for the other areas of the GLFW API.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref window_guide
|
||||
@@ -29,18 +35,36 @@ areas of the GLFW API.
|
||||
- @ref input_guide
|
||||
|
||||
|
||||
@section vulkan_loader Linking against the Vulkan loader
|
||||
|
||||
By default, GLFW will look for the Vulkan loader on demand at runtime via its
|
||||
standard name (`vulkan-1.dll` on Windows, `libvulkan.so.1` on Linux and other
|
||||
Unix-like systems and `libMoltenVK.dylib` on macOS). This means that GLFW does
|
||||
not need to be linked against the loader. However, it also means that if you
|
||||
are using the static library form of the Vulkan loader GLFW will either fail to
|
||||
find it or (worse) use the wrong one.
|
||||
|
||||
The @ref GLFW_VULKAN_STATIC CMake option makes GLFW link directly against the
|
||||
static library form. Not linking against the Vulkan loader will then be
|
||||
a compile-time error.
|
||||
|
||||
@macos When using the static library form of MoltenVK (i.e. `MetalVK.framework`
|
||||
and not `libMoltenVK.dylib`) you must also link against its dependencies: the
|
||||
`Cocoa`, `Metal` and `QuartzCore` system frameworks and the `libc++` library.
|
||||
|
||||
|
||||
@section vulkan_include Including the Vulkan and GLFW header files
|
||||
|
||||
To include the Vulkan header, define [GLFW_INCLUDE_VULKAN](@ref build_macros)
|
||||
before including the GLFW header.
|
||||
To include the Vulkan header, define @ref GLFW_INCLUDE_VULKAN before including
|
||||
the GLFW header.
|
||||
|
||||
@code
|
||||
#define GLFW_INCLUDE_VULKAN
|
||||
#include <GLFW/glfw3.h>
|
||||
@endcode
|
||||
|
||||
If you want to include the Vulkan header from a custom location or use your own
|
||||
custom Vulkan header then you need to include them before the GLFW header.
|
||||
If you instead want to include the Vulkan header from a custom location or use
|
||||
your own custom Vulkan header then do this before the GLFW header.
|
||||
|
||||
@code
|
||||
#include <path/to/vulkan.h>
|
||||
@@ -61,7 +85,7 @@ section. The canonical desktop loader library exports all Vulkan core and
|
||||
Khronos extension functions, allowing them to be called directly.
|
||||
|
||||
If you are loading the Vulkan loader dynamically instead of linking directly
|
||||
against it, you can check for the availability of a loader with @ref
|
||||
against it, you can check for the availability of a loader and ICD with @ref
|
||||
glfwVulkanSupported.
|
||||
|
||||
@code
|
||||
@@ -71,11 +95,11 @@ if (glfwVulkanSupported())
|
||||
}
|
||||
@endcode
|
||||
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader was found. This check is
|
||||
performed by @ref glfwInit.
|
||||
This function returns `GLFW_TRUE` if the Vulkan loader and any minimally
|
||||
functional ICD was found.
|
||||
|
||||
If no loader was found, calling any other Vulkan related GLFW function will
|
||||
generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
If if one or both were not found, calling any other Vulkan related GLFW function
|
||||
will generate a @ref GLFW_API_UNAVAILABLE error.
|
||||
|
||||
|
||||
@subsection vulkan_proc Querying Vulkan function pointers
|
||||
@@ -182,7 +206,7 @@ an existing Vulkan surface.
|
||||
|
||||
Unless you will be using OpenGL or OpenGL ES with the same window as Vulkan,
|
||||
there is no need to create a context. You can disable context creation with the
|
||||
[GLFW_CLIENT_API](@ref window_hints_ctx) hint.
|
||||
[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
|
||||
+421
-180
@@ -5,11 +5,12 @@
|
||||
@tableofcontents
|
||||
|
||||
This guide introduces the window related functions of GLFW. For details on
|
||||
a specific function, see the [reference documentation](@ref window). There are
|
||||
also guides for the other areas of GLFW.
|
||||
a specific function in this category, see the @ref window. There are also
|
||||
guides for the other areas of GLFW.
|
||||
|
||||
- @ref intro_guide
|
||||
- @ref context_guide
|
||||
- @ref vulkan_guide
|
||||
- @ref monitor_guide
|
||||
- @ref input_guide
|
||||
|
||||
@@ -70,22 +71,26 @@ Video mode field | Corresponds to
|
||||
----------------------- | ------------------------
|
||||
GLFWvidmode.width | `width` parameter
|
||||
GLFWvidmode.height | `height` parameter
|
||||
GLFWvidmode.redBits | `GLFW_RED_BITS` hint
|
||||
GLFWvidmode.greenBits | `GLFW_GREEN_BITS` hint
|
||||
GLFWvidmode.blueBits | `GLFW_BLUE_BITS` hint
|
||||
GLFWvidmode.refreshRate | `GLFW_REFRESH_RATE` hint
|
||||
GLFWvidmode.redBits | @ref GLFW_RED_BITS hint
|
||||
GLFWvidmode.greenBits | @ref GLFW_GREEN_BITS hint
|
||||
GLFWvidmode.blueBits | @ref GLFW_BLUE_BITS hint
|
||||
GLFWvidmode.refreshRate | @ref GLFW_REFRESH_RATE hint
|
||||
|
||||
Once you have a full screen window, you can change its resolution, refresh rate
|
||||
and monitor with @ref glfwSetWindowMonitor. If you just need change its
|
||||
resolution you can also call @ref glfwSetWindowSize. In all cases, the new
|
||||
video mode will be selected the same way as the video mode chosen by @ref
|
||||
glfwCreateWindow.
|
||||
glfwCreateWindow. If the window has an OpenGL or OpenGL ES context, it will be
|
||||
unaffected.
|
||||
|
||||
By default, the original video mode of the monitor will be restored and the
|
||||
window iconified if it loses input focus, to allow the user to switch back to
|
||||
the desktop. This behavior can be disabled with the `GLFW_AUTO_ICONIFY` window
|
||||
hint, for example if you wish to simultaneously cover multiple windows with full
|
||||
screen windows.
|
||||
the desktop. This behavior can be disabled with the
|
||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you
|
||||
wish to simultaneously cover multiple windows with full screen windows.
|
||||
|
||||
If a monitor is disconnected, any window that is full screen on that monitor
|
||||
will be forced into windowed mode. See @ref monitor_event for more information.
|
||||
|
||||
|
||||
@subsubsection window_windowed_full_screen "Windowed full screen" windows
|
||||
@@ -144,6 +149,11 @@ context. These hints are set to their default values each time the library is
|
||||
initialized with @ref glfwInit, can be set individually with @ref glfwWindowHint
|
||||
and reset all at once to their defaults with @ref glfwDefaultWindowHints.
|
||||
|
||||
Some hints are platform specific. These are always valid to set on any
|
||||
platform but they will only affect their specific platform. Other platforms
|
||||
will simply ignore them. Setting these hints requires no platform specific
|
||||
headers or calls.
|
||||
|
||||
Note that hints need to be set _before_ the creation of the window and context
|
||||
you wish to have the specified attributes.
|
||||
|
||||
@@ -156,128 +166,187 @@ that are not hard constraints are matched as closely as possible, but the
|
||||
resulting context and framebuffer may differ from what these hints requested.
|
||||
|
||||
The following hints are always hard constraints:
|
||||
- `GLFW_STEREO`
|
||||
- `GLFW_DOUBLEBUFFER`
|
||||
- `GLFW_CLIENT_API`
|
||||
- `GLFW_CONTEXT_CREATION_API`
|
||||
- @ref GLFW_STEREO
|
||||
- @ref GLFW_DOUBLEBUFFER
|
||||
- [GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint)
|
||||
- [GLFW_CONTEXT_CREATION_API](@ref GLFW_CONTEXT_CREATION_API_hint)
|
||||
|
||||
The following additional hints are hard constraints when requesting an OpenGL
|
||||
context, but are ignored when requesting an OpenGL ES context:
|
||||
- `GLFW_OPENGL_FORWARD_COMPAT`
|
||||
- `GLFW_OPENGL_PROFILE`
|
||||
- [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
|
||||
- [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint)
|
||||
|
||||
|
||||
@subsubsection window_hints_wnd Window related hints
|
||||
|
||||
`GLFW_RESIZABLE` specifies whether the windowed mode window will be resizable
|
||||
@anchor GLFW_RESIZABLE_hint
|
||||
__GLFW_RESIZABLE__ specifies whether the windowed mode window will be resizable
|
||||
_by the user_. The window will still be resizable using the @ref
|
||||
glfwSetWindowSize function. This hint is ignored for full screen windows.
|
||||
glfwSetWindowSize function. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
This hint is ignored for full screen and undecorated windows.
|
||||
|
||||
`GLFW_VISIBLE` specifies whether the windowed mode window will be initially
|
||||
visible. This hint is ignored for full screen windows.
|
||||
|
||||
`GLFW_DECORATED` specifies whether the windowed mode window will have window
|
||||
decorations such as a border, a close widget, etc. An undecorated window may
|
||||
still allow the user to generate close events on some platforms. This hint is
|
||||
@anchor GLFW_VISIBLE_hint
|
||||
__GLFW_VISIBLE__ specifies whether the windowed mode window will be initially
|
||||
visible. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
|
||||
ignored for full screen windows.
|
||||
|
||||
`GLFW_FOCUSED` specifies whether the windowed mode window will be given input
|
||||
focus when created. This hint is ignored for full screen and initially hidden
|
||||
windows.
|
||||
@anchor GLFW_DECORATED_hint
|
||||
__GLFW_DECORATED__ specifies whether the windowed mode window will have window
|
||||
decorations such as a border, a close widget, etc. An undecorated window will
|
||||
not be resizable by the user but will still allow the user to generate close
|
||||
events on some platforms. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
This hint is ignored for full screen windows.
|
||||
|
||||
`GLFW_AUTO_ICONIFY` specifies whether the full screen window will
|
||||
@anchor GLFW_FOCUSED_hint
|
||||
__GLFW_FOCUSED__ specifies whether the windowed mode window will be given input
|
||||
focus when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
|
||||
hint is ignored for full screen and initially hidden windows.
|
||||
|
||||
@anchor GLFW_AUTO_ICONIFY_hint
|
||||
__GLFW_AUTO_ICONIFY__ specifies whether the full screen window will
|
||||
automatically iconify and restore the previous video mode on input focus loss.
|
||||
This hint is ignored for windowed mode windows.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is ignored for
|
||||
windowed mode windows.
|
||||
|
||||
`GLFW_FLOATING` specifies whether the windowed mode window will be floating
|
||||
@anchor GLFW_FLOATING_hint
|
||||
__GLFW_FLOATING__ specifies whether the windowed mode window will be floating
|
||||
above other regular windows, also called topmost or always-on-top. This is
|
||||
intended primarily for debugging purposes and cannot be used to implement proper
|
||||
full screen windows. This hint is ignored for full screen windows.
|
||||
full screen windows. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This
|
||||
hint is ignored for full screen windows.
|
||||
|
||||
`GLFW_MAXIMIZED` specifies whether the windowed mode window will be maximized
|
||||
when created. This hint is ignored for full screen windows.
|
||||
@anchor GLFW_MAXIMIZED_hint
|
||||
__GLFW_MAXIMIZED__ specifies whether the windowed mode window will be maximized
|
||||
when created. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This hint is
|
||||
ignored for full screen windows.
|
||||
|
||||
@anchor GLFW_CENTER_CURSOR_hint
|
||||
__GLFW_CENTER_CURSOR__ specifies whether the cursor should be centered over
|
||||
newly created full screen windows. Possible values are `GLFW_TRUE` and
|
||||
`GLFW_FALSE`. This hint is ignored for windowed mode windows.
|
||||
|
||||
|
||||
@subsubsection window_hints_fb Framebuffer related hints
|
||||
|
||||
`GLFW_RED_BITS`, `GLFW_GREEN_BITS`, `GLFW_BLUE_BITS`, `GLFW_ALPHA_BITS`,
|
||||
`GLFW_DEPTH_BITS` and `GLFW_STENCIL_BITS` specify the desired bit depths of the
|
||||
various components of the default framebuffer. `GLFW_DONT_CARE` means the
|
||||
application has no preference.
|
||||
@anchor GLFW_RED_BITS
|
||||
@anchor GLFW_GREEN_BITS
|
||||
@anchor GLFW_BLUE_BITS
|
||||
@anchor GLFW_ALPHA_BITS
|
||||
@anchor GLFW_DEPTH_BITS
|
||||
@anchor GLFW_STENCIL_BITS
|
||||
__GLFW_RED_BITS__, __GLFW_GREEN_BITS__, __GLFW_BLUE_BITS__, __GLFW_ALPHA_BITS__,
|
||||
__GLFW_DEPTH_BITS__ and __GLFW_STENCIL_BITS__ specify the desired bit depths of
|
||||
the various components of the default framebuffer. A value of `GLFW_DONT_CARE`
|
||||
means the application has no preference.
|
||||
|
||||
`GLFW_ACCUM_RED_BITS`, `GLFW_ACCUM_GREEN_BITS`, `GLFW_ACCUM_BLUE_BITS` and
|
||||
`GLFW_ACCUM_ALPHA_BITS` specify the desired bit depths of the various components
|
||||
of the accumulation buffer. `GLFW_DONT_CARE` means the application has no
|
||||
preference.
|
||||
@anchor GLFW_ACCUM_RED_BITS
|
||||
@anchor GLFW_ACCUM_GREEN_BITS
|
||||
@anchor GLFW_ACCUM_BLUE_BITS
|
||||
@anchor GLFW_ACCUM_ALPHA_BITS
|
||||
__GLFW_ACCUM_RED_BITS__, __GLFW_ACCUM_GREEN_BITS__, __GLFW_ACCUM_BLUE_BITS__ and
|
||||
__GLFW_ACCUM_ALPHA_BITS__ specify the desired bit depths of the various
|
||||
components of the accumulation buffer. A value of `GLFW_DONT_CARE` means the
|
||||
application has no preference.
|
||||
|
||||
@par
|
||||
Accumulation buffers are a legacy OpenGL feature and should not be used in new
|
||||
code.
|
||||
|
||||
`GLFW_AUX_BUFFERS` specifies the desired number of auxiliary buffers.
|
||||
`GLFW_DONT_CARE` means the application has no preference.
|
||||
@anchor GLFW_AUX_BUFFERS
|
||||
__GLFW_AUX_BUFFERS__ specifies the desired number of auxiliary buffers. A value
|
||||
of `GLFW_DONT_CARE` means the application has no preference.
|
||||
|
||||
@par
|
||||
Auxiliary buffers are a legacy OpenGL feature and should not be used in new
|
||||
code.
|
||||
|
||||
`GLFW_STEREO` specifies whether to use stereoscopic rendering. This is a hard
|
||||
constraint.
|
||||
@anchor GLFW_STEREO
|
||||
__GLFW_STEREO__ specifies whether to use OpenGL stereoscopic rendering.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is a hard constraint.
|
||||
|
||||
`GLFW_SAMPLES` specifies the desired number of samples to use for multisampling.
|
||||
Zero disables multisampling. `GLFW_DONT_CARE` means the application has no
|
||||
preference.
|
||||
@anchor GLFW_SAMPLES
|
||||
__GLFW_SAMPLES__ specifies the desired number of samples to use for
|
||||
multisampling. Zero disables multisampling. A value of `GLFW_DONT_CARE` means
|
||||
the application has no preference.
|
||||
|
||||
`GLFW_SRGB_CAPABLE` specifies whether the framebuffer should be sRGB capable.
|
||||
If supported, a created OpenGL context will support the `GL_FRAMEBUFFER_SRGB`
|
||||
enable, also called `GL_FRAMEBUFFER_SRGB_EXT`) for controlling sRGB rendering
|
||||
and a created OpenGL ES context will always have sRGB rendering enabled.
|
||||
@anchor GLFW_SRGB_CAPABLE
|
||||
__GLFW_SRGB_CAPABLE__ specifies whether the framebuffer should be sRGB capable.
|
||||
Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
|
||||
`GLFW_DOUBLEBUFFER` specifies whether the framebuffer should be double buffered.
|
||||
You nearly always want to use double buffering. This is a hard constraint.
|
||||
@par
|
||||
__OpenGL:__ If enabled and supported by the system, the `GL_FRAMEBUFFER_SRGB`
|
||||
enable will control sRGB rendering. By default, sRGB rendering will be
|
||||
disabled.
|
||||
|
||||
@par
|
||||
__OpenGL ES:__ If enabled and supported by the system, the context will always
|
||||
have sRGB rendering enabled.
|
||||
|
||||
@anchor GLFW_DOUBLEBUFFER
|
||||
__GLFW_DOUBLEBUFFER__ specifies whether the framebuffer should be double
|
||||
buffered. You nearly always want to use double buffering. This is a hard
|
||||
constraint. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||
|
||||
|
||||
@subsubsection window_hints_mtr Monitor related hints
|
||||
|
||||
`GLFW_REFRESH_RATE` specifies the desired refresh rate for full screen windows.
|
||||
If set to `GLFW_DONT_CARE`, the highest available refresh rate will be used.
|
||||
This hint is ignored for windowed mode windows.
|
||||
@anchor GLFW_REFRESH_RATE
|
||||
__GLFW_REFRESH_RATE__ specifies the desired refresh rate for full screen
|
||||
windows. A value of `GLFW_DONT_CARE` means the highest available refresh rate
|
||||
will be used. This hint is ignored for windowed mode windows.
|
||||
|
||||
|
||||
@subsubsection window_hints_ctx Context related hints
|
||||
|
||||
`GLFW_CLIENT_API` specifies which client API to create the context for.
|
||||
@anchor GLFW_CLIENT_API_hint
|
||||
__GLFW_CLIENT_API__ specifies which client API to create the context for.
|
||||
Possible values are `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` and `GLFW_NO_API`.
|
||||
This is a hard constraint.
|
||||
|
||||
`GLFW_CONTEXT_CREATION_API` specifies which context creation API to use to
|
||||
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API` and
|
||||
`GLFW_EGL_CONTEXT_API`. This is a hard constraint. If no client API is
|
||||
requested, this hint is ignored.
|
||||
@anchor GLFW_CONTEXT_CREATION_API_hint
|
||||
__GLFW_CONTEXT_CREATION_API__ specifies which context creation API to use to
|
||||
create the context. Possible values are `GLFW_NATIVE_CONTEXT_API`,
|
||||
`GLFW_EGL_CONTEXT_API` and `GLFW_OSMESA_CONTEXT_API`. This is a hard
|
||||
constraint. If no client API is requested, this hint is ignored.
|
||||
|
||||
@par
|
||||
__OS X:__ The EGL API is not available on this platform and requests to use it
|
||||
@macos The EGL API is not available on this platform and requests to use it
|
||||
will fail.
|
||||
|
||||
@par
|
||||
__Wayland, Mir:__ The EGL API _is_ the native context creation API, so this hint
|
||||
will have no effect.
|
||||
|
||||
@par
|
||||
__OSMesa:__ As its name implies, an OpenGL context created with OSMesa does not
|
||||
update the window contents when its buffers are swapped. Use OpenGL functions
|
||||
or the OSMesa native access functions @ref glfwGetOSMesaColorBuffer and @ref
|
||||
glfwGetOSMesaDepthBuffer to retrieve the framebuffer contents.
|
||||
|
||||
@note An OpenGL extension loader library that assumes it knows which context
|
||||
creation API is used on a given platform may fail if you change this hint. This
|
||||
can be resolved by having it load via @ref glfwGetProcAddress, which always uses
|
||||
the selected API.
|
||||
|
||||
`GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` specify the client
|
||||
API version that the created context must be compatible with. The exact
|
||||
@bug On some Linux systems, creating contexts via both the native and EGL APIs
|
||||
in a single process will cause the application to segfault. Stick to one API or
|
||||
the other on Linux for now.
|
||||
|
||||
@anchor GLFW_CONTEXT_VERSION_MAJOR_hint
|
||||
@anchor GLFW_CONTEXT_VERSION_MINOR_hint
|
||||
__GLFW_CONTEXT_VERSION_MAJOR__ and __GLFW_CONTEXT_VERSION_MINOR__ specify the
|
||||
client API version that the created context must be compatible with. The exact
|
||||
behavior of these hints depend on the requested client API.
|
||||
|
||||
@note Do not confuse these hints with `GLFW_VERSION_MAJOR` and
|
||||
`GLFW_VERSION_MINOR`, which provide the API version of the GLFW header.
|
||||
|
||||
@par
|
||||
__OpenGL:__ `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` are
|
||||
not hard constraints, but creation will fail if the OpenGL version of the
|
||||
created context is less than the one requested. It is therefore perfectly safe
|
||||
to use the default of version 1.0 for legacy code and you will still get
|
||||
backwards-compatible contexts of version 3.0 and above when available.
|
||||
__OpenGL:__ These hints are not hard constraints, but creation will fail if the
|
||||
OpenGL version of the created context is less than the one requested. It is
|
||||
therefore perfectly safe to use the default of version 1.0 for legacy code and
|
||||
you will still get backwards-compatible contexts of version 3.0 and above when
|
||||
available.
|
||||
|
||||
@par
|
||||
While there is no way to ask the driver for a context of the highest supported
|
||||
@@ -285,14 +354,21 @@ version, GLFW will attempt to provide this when you ask for a version 1.0
|
||||
context, which is the default for these hints.
|
||||
|
||||
@par
|
||||
__OpenGL ES:__ `GLFW_CONTEXT_VERSION_MAJOR` and `GLFW_CONTEXT_VERSION_MINOR` are
|
||||
not hard constraints, but creation will fail if the OpenGL ES version of the
|
||||
created context is less than the one requested. Additionally, OpenGL ES 1.x
|
||||
cannot be returned if 2.0 or later was requested, and vice versa. This is
|
||||
because OpenGL ES 3.x is backward compatible with 2.0, but OpenGL ES 2.0 is not
|
||||
backward compatible with 1.x.
|
||||
__OpenGL ES:__ These hints are not hard constraints, but creation will fail if
|
||||
the OpenGL ES version of the created context is less than the one requested.
|
||||
Additionally, OpenGL ES 1.x cannot be returned if 2.0 or later was requested,
|
||||
and vice versa. This is because OpenGL ES 3.x is backward compatible with 2.0,
|
||||
but OpenGL ES 2.0 is not backward compatible with 1.x.
|
||||
|
||||
`GLFW_OPENGL_FORWARD_COMPAT` specifies whether the OpenGL context should be
|
||||
@note @macos The OS only supports forward-compatible core profile contexts for
|
||||
OpenGL versions 3.2 and later. Before creating an OpenGL context of version
|
||||
3.2 or later you must set the
|
||||
[GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and
|
||||
[GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly. OpenGL
|
||||
3.0 and 3.1 contexts are not supported at all on macOS.
|
||||
|
||||
@anchor GLFW_OPENGL_FORWARD_COMPAT_hint
|
||||
__GLFW_OPENGL_FORWARD_COMPAT__ specifies whether the OpenGL context should be
|
||||
forward-compatible, i.e. one where all functionality deprecated in the requested
|
||||
version of OpenGL is removed. This must only be used if the requested OpenGL
|
||||
version is 3.0 or above. If OpenGL ES is requested, this hint is ignored.
|
||||
@@ -301,27 +377,32 @@ version is 3.0 or above. If OpenGL ES is requested, this hint is ignored.
|
||||
Forward-compatibility is described in detail in the
|
||||
[OpenGL Reference Manual](https://www.opengl.org/registry/).
|
||||
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` specifies whether to create a debug OpenGL context,
|
||||
which may have additional error and performance issue reporting functionality.
|
||||
If OpenGL ES is requested, this hint is ignored.
|
||||
@anchor GLFW_OPENGL_DEBUG_CONTEXT_hint
|
||||
__GLFW_OPENGL_DEBUG_CONTEXT__ specifies whether to create a debug OpenGL
|
||||
context, which may have additional error and performance issue reporting
|
||||
functionality. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If OpenGL ES
|
||||
is requested, this hint is ignored.
|
||||
|
||||
`GLFW_OPENGL_PROFILE` specifies which OpenGL profile to create the context for.
|
||||
Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or
|
||||
@anchor GLFW_OPENGL_PROFILE_hint
|
||||
__GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context
|
||||
for. Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or
|
||||
`GLFW_OPENGL_COMPAT_PROFILE`, or `GLFW_OPENGL_ANY_PROFILE` to not request
|
||||
a specific profile. If requesting an OpenGL version below 3.2,
|
||||
`GLFW_OPENGL_ANY_PROFILE` must be used. If OpenGL ES is requested,
|
||||
this hint is ignored.
|
||||
`GLFW_OPENGL_ANY_PROFILE` must be used. If OpenGL ES is requested, this hint
|
||||
is ignored.
|
||||
|
||||
@par
|
||||
OpenGL profiles are described in detail in the
|
||||
[OpenGL Reference Manual](https://www.opengl.org/registry/).
|
||||
|
||||
`GLFW_CONTEXT_ROBUSTNESS` specifies the robustness strategy to be used by the
|
||||
@anchor GLFW_CONTEXT_ROBUSTNESS_hint
|
||||
__GLFW_CONTEXT_ROBUSTNESS__ specifies the robustness strategy to be used by the
|
||||
context. This can be one of `GLFW_NO_RESET_NOTIFICATION` or
|
||||
`GLFW_LOSE_CONTEXT_ON_RESET`, or `GLFW_NO_ROBUSTNESS` to not request
|
||||
a robustness strategy.
|
||||
|
||||
`GLFW_CONTEXT_RELEASE_BEHAVIOR` specifies the release behavior to be
|
||||
@anchor GLFW_CONTEXT_RELEASE_BEHAVIOR_hint
|
||||
__GLFW_CONTEXT_RELEASE_BEHAVIOR__ specifies the release behavior to be
|
||||
used by the context. Possible values are one of `GLFW_ANY_RELEASE_BEHAVIOR`,
|
||||
`GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`. If the
|
||||
behavior is `GLFW_ANY_RELEASE_BEHAVIOR`, the default behavior of the context
|
||||
@@ -335,60 +416,88 @@ Context release behaviors are described in detail by the
|
||||
[GL_KHR_context_flush_control](https://www.opengl.org/registry/specs/KHR/context_flush_control.txt)
|
||||
extension.
|
||||
|
||||
`GLFW_CONTEXT_NO_ERROR` specifies whether errors should be generated by the
|
||||
context. If enabled, situations that would have generated errors instead cause
|
||||
undefined behavior.
|
||||
@anchor GLFW_CONTEXT_NO_ERROR_hint
|
||||
__GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the
|
||||
context. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If enabled,
|
||||
situations that would have generated errors instead cause undefined behavior.
|
||||
|
||||
@par
|
||||
The no error mode for OpenGL and OpenGL ES is described in detail by the
|
||||
[GL_KHR_no_error](https://www.opengl.org/registry/specs/KHR/no_error.txt)
|
||||
extension.
|
||||
|
||||
@note This hint is experimental in its current state. There are currently
|
||||
(October 2015) no corresponding WGL or GLX extensions. That makes this hint
|
||||
a [hard constraint](@ref window_hints_hard) for those backends, as creation will
|
||||
fail if unsupported context flags are requested. Once the extensions are
|
||||
available, they will be required and creation of `GL_KHR_no_error` contexts may
|
||||
fail on early drivers where this flag is supported without those extensions
|
||||
being listed.
|
||||
|
||||
@subsubsection window_hints_osx macOS specific window hints
|
||||
|
||||
@anchor GLFW_COCOA_RETINA_FRAMEBUFFER_hint
|
||||
__GLFW_COCOA_RETINA_FRAMEBUFFER__ specifies whether to use full resolution
|
||||
framebuffers on Retina displays. Possible values are `GLFW_TRUE` and
|
||||
`GLFW_FALSE`. This is ignored on other platforms.
|
||||
|
||||
@anchor GLFW_COCOA_FRAME_AUTOSAVE_hint
|
||||
__GLFW_COCOA_FRAME_AUTOSAVE__ specifies whether to activate frame autosaving
|
||||
using the window title specified at window creation. Possible values are
|
||||
`GLFW_TRUE` and `GLFW_FALSE`. This is ignored on other platforms.
|
||||
|
||||
@anchor GLFW_COCOA_GRAPHICS_SWITCHING_hint
|
||||
__GLFW_COCOA_GRAPHICS_SWITCHING__ specifies whether to in Automatic Graphics
|
||||
Switching, i.e. to allow the system to choose the integrated GPU for the OpenGL
|
||||
context and move it between GPUs if necessary or whether to force it to always
|
||||
run on the discrete GPU. This only affects systems with both integrated and
|
||||
discrete GPUs. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. This is
|
||||
ignored on other platforms.
|
||||
|
||||
@par
|
||||
Simpler programs and tools may want to enable this to save power, while games
|
||||
and other applications performing advanced rendering will want to leave it
|
||||
disabled.
|
||||
|
||||
@par
|
||||
A bundled application that wishes to participate in Automatic Graphics Switching
|
||||
should also declare this in its `Info.plist` by setting the
|
||||
`NSSupportsAutomaticGraphicsSwitching` key to `true`.
|
||||
|
||||
|
||||
@subsubsection window_hints_values Supported and default values
|
||||
|
||||
Window hint | Default value | Supported values
|
||||
------------------------------- | --------------------------- | ----------------
|
||||
`GLFW_RESIZABLE` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_VISIBLE` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_DECORATED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_FOCUSED` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_AUTO_ICONIFY` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_FLOATING` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_MAXIMIZED` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_ALPHA_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_DEPTH_BITS` | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_STENCIL_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_ACCUM_RED_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_ACCUM_GREEN_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_ACCUM_BLUE_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_ACCUM_ALPHA_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_AUX_BUFFERS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_SAMPLES` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_REFRESH_RATE` | `GLFW_DONT_CARE` | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
`GLFW_STEREO` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_SRGB_CAPABLE` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_DOUBLEBUFFER` | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
|
||||
`GLFW_CONTEXT_CREATION_API` | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API` or `GLFW_EGL_CONTEXT_API`
|
||||
`GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API
|
||||
`GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API
|
||||
`GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
|
||||
`GLFW_CONTEXT_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`
|
||||
`GLFW_OPENGL_FORWARD_COMPAT` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
`GLFW_OPENGL_PROFILE` | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
|
||||
Window hint | Default value | Supported values
|
||||
----------------------------- | --------------------------- | ----------------
|
||||
GLFW_RESIZABLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_VISIBLE | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_DECORATED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_FOCUSED | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_AUTO_ICONIFY | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_FLOATING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_MAXIMIZED | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_ALPHA_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_DEPTH_BITS | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_STENCIL_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_ACCUM_RED_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_ACCUM_GREEN_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_ACCUM_BLUE_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_ACCUM_ALPHA_BITS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_AUX_BUFFERS | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_SAMPLES | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_REFRESH_RATE | `GLFW_DONT_CARE` | 0 to `INT_MAX` or `GLFW_DONT_CARE`
|
||||
GLFW_STEREO | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_SRGB_CAPABLE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_DOUBLEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_CLIENT_API | `GLFW_OPENGL_API` | `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`
|
||||
GLFW_CONTEXT_CREATION_API | `GLFW_NATIVE_CONTEXT_API` | `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API` or `GLFW_OSMESA_CONTEXT_API`
|
||||
GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major version number of the chosen client API
|
||||
GLFW_CONTEXT_VERSION_MINOR | 0 | Any valid minor version number of the chosen client API
|
||||
GLFW_CONTEXT_ROBUSTNESS | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET`
|
||||
GLFW_CONTEXT_RELEASE_BEHAVIOR | `GLFW_ANY_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`
|
||||
GLFW_OPENGL_FORWARD_COMPAT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_OPENGL_DEBUG_CONTEXT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_OPENGL_PROFILE | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE`
|
||||
GLFW_COCOA_RETINA_FRAMEBUFFER | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_COCOA_FRAME_AUTOSAVE | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
GLFW_COCOA_GRAPHICS_SWITCHING | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||
|
||||
|
||||
@section window_events Window event processing
|
||||
@@ -645,7 +754,7 @@ As long as your source file is encoded as UTF-8, you can use any Unicode
|
||||
characters directly in the source.
|
||||
|
||||
@code
|
||||
glfwSetWindowTitle(window, "星を追う子ども");
|
||||
glfwSetWindowTitle(window, "ラストエグザイル");
|
||||
@endcode
|
||||
|
||||
If you are using C++11 or C11, you can use a UTF-8 string literal.
|
||||
@@ -668,6 +777,10 @@ images[1] = load_icon("my_icon_small.png");
|
||||
glfwSetWindowIcon(window, 2, images);
|
||||
@endcode
|
||||
|
||||
The image data is 32-bit, little-endian, non-premultiplied RGBA, i.e. eight bits
|
||||
per channel with the red channel first. The pixels are arranged canonically as
|
||||
sequential rows, starting from the top-left corner.
|
||||
|
||||
To revert to the default window icon, pass in an empty image array.
|
||||
|
||||
@code
|
||||
@@ -724,7 +837,8 @@ glfwIconifyWindow(window);
|
||||
When a full screen window is iconified, the original video mode of its monitor
|
||||
is restored until the user or application restores the window.
|
||||
|
||||
Iconified windows can be restored with @ref glfwRestoreWindow.
|
||||
Iconified windows can be restored with @ref glfwRestoreWindow. This function
|
||||
also restores windows from maximization.
|
||||
|
||||
@code
|
||||
glfwRestoreWindow(window);
|
||||
@@ -763,6 +877,62 @@ int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection window_maximize Window maximization
|
||||
|
||||
Windows can be maximized (i.e. zoomed) with @ref glfwMaximizeWindow.
|
||||
|
||||
@code
|
||||
glfwMaximizeWindow(window);
|
||||
@endcode
|
||||
|
||||
Full screen windows cannot be maximized and passing a full screen window to this
|
||||
function does nothing.
|
||||
|
||||
Maximized windows can be restored with @ref glfwRestoreWindow. This function
|
||||
also restores windows from iconification.
|
||||
|
||||
@code
|
||||
glfwRestoreWindow(window);
|
||||
@endcode
|
||||
|
||||
If you wish to be notified when a window is maximized or restored, whether by
|
||||
the user, system or your own code, set a maximize callback.
|
||||
|
||||
@code
|
||||
glfwSetWindowMaximizeCallback(window, window_maximize_callback);
|
||||
@endcode
|
||||
|
||||
The callback function receives changes in the maximization state of the window.
|
||||
|
||||
@code
|
||||
void window_maximize_callback(GLFWwindow* window, int maximized)
|
||||
{
|
||||
if (maximized)
|
||||
{
|
||||
// The window was maximized
|
||||
}
|
||||
else
|
||||
{
|
||||
// The window was restored
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
You can also get the current maximization state with @ref glfwGetWindowAttrib.
|
||||
|
||||
@code
|
||||
int maximized = glfwGetWindowAttrib(window, GLFW_MAXIMIZED);
|
||||
@endcode
|
||||
|
||||
By default, newly created windows are not maximized. You can change this
|
||||
behavior by setting the [GLFW_MAXIMIZED](@ref GLFW_MAXIMIZED_hint) window hint
|
||||
before creating the window.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection window_hide Window visibility
|
||||
|
||||
Windowed mode windows can be hidden with @ref glfwHideWindow.
|
||||
@@ -781,11 +951,6 @@ Hidden windows can be shown with @ref glfwShowWindow.
|
||||
glfwShowWindow(window);
|
||||
@endcode
|
||||
|
||||
Windowed mode windows can be created initially hidden with the `GLFW_VISIBLE`
|
||||
[window hint](@ref window_hints_wnd). Windows created hidden are completely
|
||||
invisible to the user until shown. This can be useful if you need to set up
|
||||
your window further before showing it, for example moving it to a specific
|
||||
location.
|
||||
|
||||
You can also get the current visibility state with @ref glfwGetWindowAttrib.
|
||||
|
||||
@@ -793,6 +958,18 @@ You can also get the current visibility state with @ref glfwGetWindowAttrib.
|
||||
int visible = glfwGetWindowAttrib(window, GLFW_VISIBLE);
|
||||
@endcode
|
||||
|
||||
By default, newly created windows are visible. You can change this behavior by
|
||||
setting the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window hint before creating
|
||||
the window.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
Windows created hidden are completely invisible to the user until shown. This
|
||||
can be useful if you need to set up your window further before showing it, for
|
||||
example moving it to a specific location.
|
||||
|
||||
|
||||
@subsection window_focus Window input focus
|
||||
|
||||
@@ -803,6 +980,10 @@ glfwFocusWindow.
|
||||
glfwFocusWindow(window);
|
||||
@endcode
|
||||
|
||||
Keep in mind that it can be very disruptive to the user when a window is forced
|
||||
to the top. For a less disruptive way of getting the user's attention, see
|
||||
[attention requests](@ref window_attention).
|
||||
|
||||
If you wish to be notified when a window gains or loses input focus, whether by
|
||||
the user, system or your own code, set a focus callback.
|
||||
|
||||
@@ -832,6 +1013,28 @@ You can also get the current input focus state with @ref glfwGetWindowAttrib.
|
||||
int focused = glfwGetWindowAttrib(window, GLFW_FOCUSED);
|
||||
@endcode
|
||||
|
||||
By default, newly created windows are given input focus. You can change this
|
||||
behavior by setting the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) window hint
|
||||
before creating the window.
|
||||
|
||||
@code
|
||||
glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection window_attention Window attention request
|
||||
|
||||
If you wish to notify the user of an event without interrupting, you can request
|
||||
attention with @ref glfwRequestWindowAttention.
|
||||
|
||||
@code
|
||||
glfwRequestWindowAttention(window);
|
||||
@endcode
|
||||
|
||||
The system will highlight the specified window, or on platforms where this is
|
||||
not supported, the application as a whole. Once the user has given it
|
||||
attention, the system will automatically end the request.
|
||||
|
||||
|
||||
@subsection window_refresh Window damage and refresh
|
||||
|
||||
@@ -861,10 +1064,10 @@ the window or framebuffer is resized.
|
||||
@subsection window_attribs Window attributes
|
||||
|
||||
Windows have a number of attributes that can be returned using @ref
|
||||
glfwGetWindowAttrib. Some reflect state that may change during the lifetime of
|
||||
the window, while others reflect the corresponding hints and are fixed at the
|
||||
time of creation. Some are related to the actual window and others to its
|
||||
context.
|
||||
glfwGetWindowAttrib. Some reflect state that may change as a result of user
|
||||
interaction, (e.g. whether it has input focus), while others reflect inherent
|
||||
properties of the window (e.g. what kind of border it has). Some are related to
|
||||
the window and others to its OpenGL or OpenGL ES context.
|
||||
|
||||
@code
|
||||
if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
|
||||
@@ -873,65 +1076,103 @@ if (glfwGetWindowAttrib(window, GLFW_FOCUSED))
|
||||
}
|
||||
@endcode
|
||||
|
||||
The [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
|
||||
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
|
||||
[GLFW_FLOATING](@ref GLFW_FLOATING_attrib) and
|
||||
[GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) window attributes can be
|
||||
changed with @ref glfwSetWindowAttrib.
|
||||
|
||||
@code
|
||||
glfwSetWindowAttrib(window, GLFW_RESIZABLE, GLFW_FALSE);
|
||||
@endcode
|
||||
|
||||
|
||||
|
||||
@subsubsection window_attribs_wnd Window related attributes
|
||||
|
||||
`GLFW_FOCUSED` indicates whether the specified window has input focus. Initial
|
||||
input focus is controlled by the [window hint](@ref window_hints_wnd) with the
|
||||
same name.
|
||||
@anchor GLFW_FOCUSED_attrib
|
||||
__GLFW_FOCUSED__ indicates whether the specified window has input focus. See
|
||||
@ref window_focus for details.
|
||||
|
||||
`GLFW_ICONIFIED` indicates whether the specified window is iconified, whether by
|
||||
the user or with @ref glfwIconifyWindow.
|
||||
@anchor GLFW_ICONIFIED_attrib
|
||||
__GLFW_ICONIFIED__ indicates whether the specified window is iconified.
|
||||
See @ref window_iconify for details.
|
||||
|
||||
`GLFW_MAXIMIZED` indicates whether the specified window is maximized, whether by
|
||||
the user or with @ref glfwMaximizeWindow.
|
||||
@anchor GLFW_MAXIMIZED_attrib
|
||||
__GLFW_MAXIMIZED__ indicates whether the specified window is maximized. See
|
||||
@ref window_maximize for details.
|
||||
|
||||
`GLFW_VISIBLE` indicates whether the specified window is visible. Window
|
||||
visibility can be controlled with @ref glfwShowWindow and @ref glfwHideWindow
|
||||
and initial visibility is controlled by the [window hint](@ref window_hints_wnd)
|
||||
with the same name.
|
||||
@anchor GLFW_VISIBLE_attrib
|
||||
__GLFW_VISIBLE__ indicates whether the specified window is visible. See @ref
|
||||
window_hide for details.
|
||||
|
||||
`GLFW_RESIZABLE` indicates whether the specified window is resizable _by the
|
||||
user_. This is set on creation with the [window hint](@ref window_hints_wnd)
|
||||
with the same name.
|
||||
@anchor GLFW_RESIZABLE_attrib
|
||||
__GLFW_RESIZABLE__ indicates whether the specified window is resizable _by the
|
||||
user_. This can be set before creation with the
|
||||
[GLFW_RESIZABLE](@ref GLFW_RESIZABLE_hint) window hint or after with @ref
|
||||
glfwSetWindowAttrib.
|
||||
|
||||
`GLFW_DECORATED` indicates whether the specified window has decorations such as
|
||||
a border, a close widget, etc. This is set on creation with the
|
||||
[window hint](@ref window_hints_wnd) with the same name.
|
||||
@anchor GLFW_DECORATED_attrib
|
||||
__GLFW_DECORATED__ indicates whether the specified window has decorations such
|
||||
as a border, a close widget, etc. This can be set before creation with the
|
||||
[GLFW_DECORATED](@ref GLFW_DECORATED_hint) window hint or after with @ref
|
||||
glfwSetWindowAttrib.
|
||||
|
||||
`GLFW_FLOATING` indicates whether the specified window is floating, also called
|
||||
topmost or always-on-top. This is controlled by the
|
||||
[window hint](@ref window_hints_wnd) with the same name.
|
||||
@anchor GLFW_AUTO_ICONIFY_attrib
|
||||
__GLFW_AUTO_ICONIFY__ indicates whether the specified full screen window is
|
||||
iconified on focus loss, a close widget, etc. This can be set before creation
|
||||
with the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint or after
|
||||
with @ref glfwSetWindowAttrib.
|
||||
|
||||
@anchor GLFW_FLOATING_attrib
|
||||
__GLFW_FLOATING__ indicates whether the specified window is floating, also
|
||||
called topmost or always-on-top. This can be set before creation with the
|
||||
[GLFW_FLOATING](@ref GLFW_FLOATING_hint) window hint or after with @ref
|
||||
glfwSetWindowAttrib.
|
||||
|
||||
|
||||
@subsubsection window_attribs_ctx Context related attributes
|
||||
|
||||
`GLFW_CLIENT_API` indicates the client API provided by the window's context;
|
||||
@anchor GLFW_CLIENT_API_attrib
|
||||
__GLFW_CLIENT_API__ indicates the client API provided by the window's context;
|
||||
either `GLFW_OPENGL_API`, `GLFW_OPENGL_ES_API` or `GLFW_NO_API`.
|
||||
|
||||
`GLFW_CONTEXT_CREATION_API` indicates the context creation API used to create
|
||||
the window's context; either `GLFW_NATIVE_CONTEXT_API` or
|
||||
`GLFW_EGL_CONTEXT_API`.
|
||||
@anchor GLFW_CONTEXT_CREATION_API_attrib
|
||||
__GLFW_CONTEXT_CREATION_API__ indicates the context creation API used to create
|
||||
the window's context; either `GLFW_NATIVE_CONTEXT_API`, `GLFW_EGL_CONTEXT_API`
|
||||
or `GLFW_OSMESA_CONTEXT_API`.
|
||||
|
||||
`GLFW_CONTEXT_VERSION_MAJOR`, `GLFW_CONTEXT_VERSION_MINOR` and
|
||||
`GLFW_CONTEXT_REVISION` indicate the client API version of the window's context.
|
||||
@anchor GLFW_CONTEXT_VERSION_MAJOR_attrib
|
||||
@anchor GLFW_CONTEXT_VERSION_MINOR_attrib
|
||||
@anchor GLFW_CONTEXT_REVISION_attrib
|
||||
__GLFW_CONTEXT_VERSION_MAJOR__, __GLFW_CONTEXT_VERSION_MINOR__ and
|
||||
__GLFW_CONTEXT_REVISION__ indicate the client API version of the window's
|
||||
context.
|
||||
|
||||
`GLFW_OPENGL_FORWARD_COMPAT` is `GLFW_TRUE` if the window's context is an OpenGL
|
||||
forward-compatible one, or `GLFW_FALSE` otherwise.
|
||||
@note Do not confuse these attributes with `GLFW_VERSION_MAJOR`,
|
||||
`GLFW_VERSION_MINOR` and `GLFW_VERSION_REVISION` which provide the API version
|
||||
of the GLFW header.
|
||||
|
||||
`GLFW_OPENGL_DEBUG_CONTEXT` is `GLFW_TRUE` if the window's context is an OpenGL
|
||||
debug context, or `GLFW_FALSE` otherwise.
|
||||
@anchor GLFW_OPENGL_FORWARD_COMPAT_attrib
|
||||
__GLFW_OPENGL_FORWARD_COMPAT__ is `GLFW_TRUE` if the window's context is an
|
||||
OpenGL forward-compatible one, or `GLFW_FALSE` otherwise.
|
||||
|
||||
`GLFW_OPENGL_PROFILE` indicates the OpenGL profile used by the context. This is
|
||||
`GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context uses
|
||||
a known profile, or `GLFW_OPENGL_ANY_PROFILE` if the OpenGL profile is unknown
|
||||
or the context is an OpenGL ES context. Note that the returned profile may not
|
||||
match the profile bits of the context flags, as GLFW will try other means of
|
||||
detecting the profile when no bits are set.
|
||||
@anchor GLFW_OPENGL_DEBUG_CONTEXT_attrib
|
||||
__GLFW_OPENGL_DEBUG_CONTEXT__ is `GLFW_TRUE` if the window's context is an
|
||||
OpenGL debug context, or `GLFW_FALSE` otherwise.
|
||||
|
||||
`GLFW_CONTEXT_ROBUSTNESS` indicates the robustness strategy used by the context.
|
||||
This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION` if the
|
||||
window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
|
||||
@anchor GLFW_OPENGL_PROFILE_attrib
|
||||
__GLFW_OPENGL_PROFILE__ indicates the OpenGL profile used by the context. This
|
||||
is `GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context
|
||||
uses a known profile, or `GLFW_OPENGL_ANY_PROFILE` if the OpenGL profile is
|
||||
unknown or the context is an OpenGL ES context. Note that the returned profile
|
||||
may not match the profile bits of the context flags, as GLFW will try other
|
||||
means of detecting the profile when no bits are set.
|
||||
|
||||
@anchor GLFW_CONTEXT_ROBUSTNESS_attrib
|
||||
__GLFW_CONTEXT_ROBUSTNESS__ indicates the robustness strategy used by the
|
||||
context. This is `GLFW_LOSE_CONTEXT_ON_RESET` or `GLFW_NO_RESET_NOTIFICATION`
|
||||
if the window's context supports robustness, or `GLFW_NO_ROBUSTNESS` otherwise.
|
||||
|
||||
|
||||
@subsubsection window_attribs_fb Framebuffer related attributes
|
||||
|
||||
+14
-6
@@ -1,9 +1,9 @@
|
||||
|
||||
link_libraries(glfw)
|
||||
|
||||
include_directories(${glfw_INCLUDE_DIRS})
|
||||
include_directories(${glfw_INCLUDE_DIRS} "${GLFW_SOURCE_DIR}/deps")
|
||||
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if (MATH_LIBRARY)
|
||||
link_libraries("${MATH_LIBRARY}")
|
||||
endif()
|
||||
|
||||
@@ -11,14 +11,16 @@ if (MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories("${GLFW_SOURCE_DIR}/deps")
|
||||
if (GLFW_USE_OSMESA)
|
||||
add_definitions(-DUSE_NATIVE_OSMESA)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(ICON glfw.rc)
|
||||
elseif (APPLE)
|
||||
set(ICON glfw.icns)
|
||||
set_source_files_properties(glfw.icns PROPERTIES
|
||||
MAXOSX_PACKAGE_LOCATION "Resources")
|
||||
MACOSX_PACKAGE_LOCATION "Resources")
|
||||
endif()
|
||||
|
||||
set(GLAD "${GLFW_SOURCE_DIR}/deps/glad/glad.h"
|
||||
@@ -31,16 +33,22 @@ set(TINYCTHREAD "${GLFW_SOURCE_DIR}/deps/tinycthread.h"
|
||||
add_executable(boing WIN32 MACOSX_BUNDLE boing.c ${ICON} ${GLAD})
|
||||
add_executable(gears WIN32 MACOSX_BUNDLE gears.c ${ICON} ${GLAD})
|
||||
add_executable(heightmap WIN32 MACOSX_BUNDLE heightmap.c ${ICON} ${GLAD})
|
||||
add_executable(offscreen offscreen.c ${ICON} ${GLAD})
|
||||
add_executable(particles WIN32 MACOSX_BUNDLE particles.c ${ICON} ${TINYCTHREAD} ${GETOPT} ${GLAD})
|
||||
add_executable(simple WIN32 MACOSX_BUNDLE simple.c ${ICON} ${GLAD})
|
||||
add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD})
|
||||
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD})
|
||||
|
||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}" "${RT_LIBRARY}")
|
||||
target_link_libraries(particles "${CMAKE_THREAD_LIBS_INIT}")
|
||||
if (RT_LIBRARY)
|
||||
target_link_libraries(particles "${RT_LIBRARY}")
|
||||
endif()
|
||||
|
||||
set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
|
||||
set(CONSOLE_BINARIES offscreen)
|
||||
|
||||
set_target_properties(${WINDOWS_BINARIES} PROPERTIES FOLDER "GLFW3/Examples")
|
||||
set_target_properties(${WINDOWS_BINARIES} ${CONSOLE_BINARIES} PROPERTIES
|
||||
FOLDER "GLFW3/Examples")
|
||||
|
||||
if (MSVC)
|
||||
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* - Slightly modified camera that should work better for stereo viewing
|
||||
*
|
||||
*
|
||||
* Camilla Berglund:
|
||||
* Camilla Löwy:
|
||||
* - Removed FPS counter (this is not a benchmark)
|
||||
* - Added a few comments
|
||||
* - Enabled vsync
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
//========================================================================
|
||||
// Offscreen rendering example
|
||||
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
#define GLFW_EXPOSE_NATIVE_OSMESA
|
||||
#include <GLFW/glfw3native.h>
|
||||
#endif
|
||||
|
||||
#include "linmath.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
float x, y;
|
||||
float r, g, b;
|
||||
} vertices[3] =
|
||||
{
|
||||
{ -0.6f, -0.4f, 1.f, 0.f, 0.f },
|
||||
{ 0.6f, -0.4f, 0.f, 1.f, 0.f },
|
||||
{ 0.f, 0.6f, 0.f, 0.f, 1.f }
|
||||
};
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"#version 110\n"
|
||||
"uniform mat4 MVP;\n"
|
||||
"attribute vec3 vCol;\n"
|
||||
"attribute vec2 vPos;\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
|
||||
" color = vCol;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"#version 110\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(color, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static void error_callback(int error, const char* description)
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", description);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
GLFWwindow* window;
|
||||
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
|
||||
GLint mvp_location, vpos_location, vcol_location;
|
||||
float ratio;
|
||||
int width, height;
|
||||
mat4x4 mvp;
|
||||
char* buffer;
|
||||
|
||||
glfwSetErrorCallback(error_callback);
|
||||
|
||||
glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
|
||||
|
||||
if (!glfwInit())
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
|
||||
if (!window)
|
||||
{
|
||||
glfwTerminate();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
|
||||
|
||||
// NOTE: OpenGL error checks have been omitted for brevity
|
||||
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
mvp_location = glGetUniformLocation(program, "MVP");
|
||||
vpos_location = glGetAttribLocation(program, "vPos");
|
||||
vcol_location = glGetAttribLocation(program, "vCol");
|
||||
|
||||
glEnableVertexAttribArray(vpos_location);
|
||||
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) 0);
|
||||
glEnableVertexAttribArray(vcol_location);
|
||||
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
|
||||
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
|
||||
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
ratio = width / (float) height;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
mat4x4_ortho(mvp, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
|
||||
|
||||
glUseProgram(program);
|
||||
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
glfwGetOSMesaColorBuffer(window, &width, &height, NULL, (void**) &buffer);
|
||||
#else
|
||||
buffer = calloc(4, width * height);
|
||||
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
#endif
|
||||
|
||||
// Write image Y-flipped because OpenGL
|
||||
stbi_write_png("offscreen.png",
|
||||
width, height, 4,
|
||||
buffer + (width * 4 * (height - 1)),
|
||||
-width * 4);
|
||||
|
||||
#if USE_NATIVE_OSMESA
|
||||
// Here is where there's nothing
|
||||
#else
|
||||
free(buffer);
|
||||
#endif
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
||||
glfwTerminate();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// A simple particle engine with threaded physics
|
||||
// Copyright (c) Marcus Geelnard
|
||||
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -457,7 +457,9 @@ static void draw_particles(GLFWwindow* window, double t, float dt)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_nsec += 100000000;
|
||||
ts.tv_nsec += 100 * 1000 * 1000;
|
||||
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
|
||||
ts.tv_nsec %= 1000 * 1000 * 1000;
|
||||
cnd_timedwait(&thread_sync.p_done, &thread_sync.particles_lock, &ts);
|
||||
}
|
||||
|
||||
@@ -908,7 +910,9 @@ static int physics_thread_main(void* arg)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_nsec += 100000000;
|
||||
ts.tv_nsec += 100 * 1000 * 1000;
|
||||
ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
|
||||
ts.tv_nsec %= 1000 * 1000 * 1000;
|
||||
cnd_timedwait(&thread_sync.d_done, &thread_sync.particles_lock, &ts);
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
//========================================================================
|
||||
// Simple GLFW example
|
||||
// Copyright (c) Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -44,6 +44,7 @@ static const struct
|
||||
};
|
||||
|
||||
static const char* vertex_shader_text =
|
||||
"#version 110\n"
|
||||
"uniform mat4 MVP;\n"
|
||||
"attribute vec3 vCol;\n"
|
||||
"attribute vec2 vPos;\n"
|
||||
@@ -55,6 +56,7 @@ static const char* vertex_shader_text =
|
||||
"}\n";
|
||||
|
||||
static const char* fragment_shader_text =
|
||||
"#version 110\n"
|
||||
"varying vec3 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
@@ -124,10 +126,10 @@ int main(void)
|
||||
|
||||
glEnableVertexAttribArray(vpos_location);
|
||||
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(float) * 5, (void*) 0);
|
||||
sizeof(vertices[0]), (void*) 0);
|
||||
glEnableVertexAttribArray(vcol_location);
|
||||
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
|
||||
sizeof(float) * 5, (void*) (sizeof(float) * 2));
|
||||
sizeof(vertices[0]), (void*) (sizeof(float) * 2));
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
* Modified for GLFW by Sylvain Hellegouarch - sh@programmationworld.com
|
||||
* Modified for variable frame rate by Marcus Geelnard
|
||||
* 2003-Jan-31: Minor cleanups and speedups / MG
|
||||
* 2010-10-24: Formatting and cleanup - Camilla Berglund
|
||||
* 2010-10-24: Formatting and cleanup - Camilla Löwy
|
||||
*****************************************************************************/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
+1210
-237
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
||||
/*************************************************************************
|
||||
* GLFW 3.2 - www.glfw.org
|
||||
* GLFW 3.3 - www.glfw.org
|
||||
* A library for OpenGL, window and input
|
||||
*------------------------------------------------------------------------
|
||||
* Copyright (c) 2002-2006 Marcus Geelnard
|
||||
* Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
* Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
@@ -45,12 +45,13 @@ extern "C" {
|
||||
* more information.
|
||||
*/
|
||||
/*! @defgroup native Native access
|
||||
* @brief Functions related to accessing native handles.
|
||||
*
|
||||
* **By using the native access functions you assert that you know what you're
|
||||
* doing and how to fix problems caused by using them. If you don't, you
|
||||
* shouldn't be using them.**
|
||||
*
|
||||
* Before the inclusion of @ref glfw3native.h, you may define exactly one
|
||||
* Before the inclusion of @ref glfw3native.h, you may define zero or more
|
||||
* window system API macro and zero or more context creation API macros.
|
||||
*
|
||||
* The chosen backends must match those the library was compiled for. Failure
|
||||
@@ -68,6 +69,7 @@ extern "C" {
|
||||
* * `GLFW_EXPOSE_NATIVE_NSGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_GLX`
|
||||
* * `GLFW_EXPOSE_NATIVE_EGL`
|
||||
* * `GLFW_EXPOSE_NATIVE_OSMESA`
|
||||
*
|
||||
* These macros select which of the native access functions that are declared
|
||||
* and which platform-specific headers to include. It is then up your (by
|
||||
@@ -114,6 +116,9 @@ extern "C" {
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
#include <EGL/egl.h>
|
||||
#endif
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
#include <GL/osmesa.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
@@ -389,9 +394,9 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void);
|
||||
*/
|
||||
GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Returns the `MirSurface*` of the specified window.
|
||||
/*! @brief Returns the `MirWindow*` of the specified window.
|
||||
*
|
||||
* @return The `MirSurface*` of the specified window, or `NULL` if an
|
||||
* @return The `MirWindow*` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
@@ -401,7 +406,7 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);
|
||||
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_EGL)
|
||||
@@ -448,6 +453,64 @@ GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
|
||||
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
|
||||
/*! @brief Retrieves the color buffer associated with the specified window.
|
||||
*
|
||||
* @param[in] window The window whose color buffer to retrieve.
|
||||
* @param[out] width Where to store the width of the color buffer, or `NULL`.
|
||||
* @param[out] height Where to store the height of the color buffer, or `NULL`.
|
||||
* @param[out] format Where to store the OSMesa pixel format of the color
|
||||
* buffer, or `NULL`.
|
||||
* @param[out] buffer Where to store the address of the color buffer, or
|
||||
* `NULL`.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
|
||||
|
||||
/*! @brief Retrieves the depth buffer associated with the specified window.
|
||||
*
|
||||
* @param[in] window The window whose depth buffer to retrieve.
|
||||
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
|
||||
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
|
||||
* @param[out] bytesPerValue Where to store the number of bytes per depth
|
||||
* buffer element, or `NULL`.
|
||||
* @param[out] buffer Where to store the address of the depth buffer, or
|
||||
* `NULL`.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
|
||||
|
||||
/*! @brief Returns the `OSMesaContext` of the specified window.
|
||||
*
|
||||
* @return The `OSMesaContext` of the specified window, or `NULL` if an
|
||||
* [error](@ref error_handling) occurred.
|
||||
*
|
||||
* @thread_safety This function may be called from any thread. Access is not
|
||||
* synchronized.
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup native
|
||||
*/
|
||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+37
-19
@@ -1,5 +1,5 @@
|
||||
|
||||
set(common_HEADERS internal.h
|
||||
set(common_HEADERS internal.h mappings.h
|
||||
"${GLFW_BINARY_DIR}/src/glfw_config.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
|
||||
"${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
|
||||
@@ -7,29 +7,37 @@ set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
|
||||
|
||||
if (_GLFW_COCOA)
|
||||
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
|
||||
posix_tls.h nsgl_context.h)
|
||||
posix_thread.h nsgl_context.h egl_context.h osmesa_context.c)
|
||||
set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
|
||||
nsgl_context.m)
|
||||
cocoa_monitor.m cocoa_window.m cocoa_time.c posix_thread.c
|
||||
nsgl_context.m egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_WIN32)
|
||||
set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
|
||||
wgl_context.h egl_context.h)
|
||||
wgl_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
|
||||
win32_monitor.c win32_time.c win32_tls.c win32_window.c
|
||||
wgl_context.c egl_context.c)
|
||||
win32_monitor.c win32_time.c win32_thread.c win32_window.c
|
||||
wgl_context.c egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_X11)
|
||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
|
||||
linux_joystick.h posix_time.h posix_tls.h glx_context.h
|
||||
egl_context.h)
|
||||
set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h posix_time.h
|
||||
posix_thread.h glx_context.h egl_context.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
|
||||
xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
|
||||
glx_context.c egl_context.c)
|
||||
xkb_unicode.c posix_time.c posix_thread.c glx_context.c
|
||||
egl_context.c osmesa_context.c)
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
set(glfw_HEADERS ${glfw_HEADERS} linux_joystick.h)
|
||||
set(glfw_SOURCES ${glfw_SOURCES} linux_joystick.c)
|
||||
else()
|
||||
set(glfw_HEADERS ${glfw_HEADERS} null_joystick.h)
|
||||
set(glfw_SOURCES ${glfw_SOURCES} null_joystick.c)
|
||||
endif()
|
||||
elseif (_GLFW_WAYLAND)
|
||||
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_thread.h xkb_unicode.h egl_context.h
|
||||
osmesa_context.h)
|
||||
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
|
||||
egl_context.c)
|
||||
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||
egl_context.c osmesa_context.c)
|
||||
|
||||
ecm_add_wayland_client_protocol(glfw_SOURCES
|
||||
PROTOCOL
|
||||
@@ -41,10 +49,16 @@ elseif (_GLFW_WAYLAND)
|
||||
BASENAME pointer-constraints-unstable-v1)
|
||||
elseif (_GLFW_MIR)
|
||||
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_thread.h xkb_unicode.h egl_context.h
|
||||
osmesa_context.h)
|
||||
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
|
||||
egl_context.c)
|
||||
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
|
||||
egl_context.c osmesa_context.c)
|
||||
elseif (_GLFW_OSMESA)
|
||||
set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h
|
||||
posix_time.h posix_thread.h osmesa_context.h)
|
||||
set(glfw_SOURCES ${common_SOURCES} null_init.c null_monitor.c null_window.c
|
||||
null_joystick.c posix_time.c posix_thread.c osmesa_context.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
@@ -115,6 +129,10 @@ if (MSVC)
|
||||
endif()
|
||||
|
||||
if (GLFW_INSTALL)
|
||||
install(TARGETS glfw EXPORT glfwTargets DESTINATION lib${LIB_SUFFIX})
|
||||
install(TARGETS glfw
|
||||
EXPORT glfwTargets
|
||||
RUNTIME DESTINATION "bin"
|
||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
||||
LIBRARY DESTINATION "lib${LIB_SUFFIX}")
|
||||
endif()
|
||||
|
||||
|
||||
+127
-151
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -28,8 +28,6 @@
|
||||
#include <sys/param.h> // For MAXPATHLEN
|
||||
|
||||
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
|
||||
// Change to our application bundle's resources directory, if present
|
||||
//
|
||||
static void changeToResourcesDirectory(void)
|
||||
@@ -66,137 +64,135 @@ static void changeToResourcesDirectory(void)
|
||||
chdir(resourcesPath);
|
||||
}
|
||||
|
||||
#endif /* _GLFW_USE_CHDIR */
|
||||
|
||||
// Create key code translation tables
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
int scancode;
|
||||
|
||||
memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));
|
||||
memset(_glfw.ns.nativeKeys, -1, sizeof(_glfw.ns.nativeKeys));
|
||||
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
|
||||
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
|
||||
|
||||
_glfw.ns.publicKeys[0x1D] = GLFW_KEY_0;
|
||||
_glfw.ns.publicKeys[0x12] = GLFW_KEY_1;
|
||||
_glfw.ns.publicKeys[0x13] = GLFW_KEY_2;
|
||||
_glfw.ns.publicKeys[0x14] = GLFW_KEY_3;
|
||||
_glfw.ns.publicKeys[0x15] = GLFW_KEY_4;
|
||||
_glfw.ns.publicKeys[0x17] = GLFW_KEY_5;
|
||||
_glfw.ns.publicKeys[0x16] = GLFW_KEY_6;
|
||||
_glfw.ns.publicKeys[0x1A] = GLFW_KEY_7;
|
||||
_glfw.ns.publicKeys[0x1C] = GLFW_KEY_8;
|
||||
_glfw.ns.publicKeys[0x19] = GLFW_KEY_9;
|
||||
_glfw.ns.publicKeys[0x00] = GLFW_KEY_A;
|
||||
_glfw.ns.publicKeys[0x0B] = GLFW_KEY_B;
|
||||
_glfw.ns.publicKeys[0x08] = GLFW_KEY_C;
|
||||
_glfw.ns.publicKeys[0x02] = GLFW_KEY_D;
|
||||
_glfw.ns.publicKeys[0x0E] = GLFW_KEY_E;
|
||||
_glfw.ns.publicKeys[0x03] = GLFW_KEY_F;
|
||||
_glfw.ns.publicKeys[0x05] = GLFW_KEY_G;
|
||||
_glfw.ns.publicKeys[0x04] = GLFW_KEY_H;
|
||||
_glfw.ns.publicKeys[0x22] = GLFW_KEY_I;
|
||||
_glfw.ns.publicKeys[0x26] = GLFW_KEY_J;
|
||||
_glfw.ns.publicKeys[0x28] = GLFW_KEY_K;
|
||||
_glfw.ns.publicKeys[0x25] = GLFW_KEY_L;
|
||||
_glfw.ns.publicKeys[0x2E] = GLFW_KEY_M;
|
||||
_glfw.ns.publicKeys[0x2D] = GLFW_KEY_N;
|
||||
_glfw.ns.publicKeys[0x1F] = GLFW_KEY_O;
|
||||
_glfw.ns.publicKeys[0x23] = GLFW_KEY_P;
|
||||
_glfw.ns.publicKeys[0x0C] = GLFW_KEY_Q;
|
||||
_glfw.ns.publicKeys[0x0F] = GLFW_KEY_R;
|
||||
_glfw.ns.publicKeys[0x01] = GLFW_KEY_S;
|
||||
_glfw.ns.publicKeys[0x11] = GLFW_KEY_T;
|
||||
_glfw.ns.publicKeys[0x20] = GLFW_KEY_U;
|
||||
_glfw.ns.publicKeys[0x09] = GLFW_KEY_V;
|
||||
_glfw.ns.publicKeys[0x0D] = GLFW_KEY_W;
|
||||
_glfw.ns.publicKeys[0x07] = GLFW_KEY_X;
|
||||
_glfw.ns.publicKeys[0x10] = GLFW_KEY_Y;
|
||||
_glfw.ns.publicKeys[0x06] = GLFW_KEY_Z;
|
||||
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
|
||||
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
|
||||
_glfw.ns.keycodes[0x13] = GLFW_KEY_2;
|
||||
_glfw.ns.keycodes[0x14] = GLFW_KEY_3;
|
||||
_glfw.ns.keycodes[0x15] = GLFW_KEY_4;
|
||||
_glfw.ns.keycodes[0x17] = GLFW_KEY_5;
|
||||
_glfw.ns.keycodes[0x16] = GLFW_KEY_6;
|
||||
_glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
|
||||
_glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
|
||||
_glfw.ns.keycodes[0x19] = GLFW_KEY_9;
|
||||
_glfw.ns.keycodes[0x00] = GLFW_KEY_A;
|
||||
_glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
|
||||
_glfw.ns.keycodes[0x08] = GLFW_KEY_C;
|
||||
_glfw.ns.keycodes[0x02] = GLFW_KEY_D;
|
||||
_glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
|
||||
_glfw.ns.keycodes[0x03] = GLFW_KEY_F;
|
||||
_glfw.ns.keycodes[0x05] = GLFW_KEY_G;
|
||||
_glfw.ns.keycodes[0x04] = GLFW_KEY_H;
|
||||
_glfw.ns.keycodes[0x22] = GLFW_KEY_I;
|
||||
_glfw.ns.keycodes[0x26] = GLFW_KEY_J;
|
||||
_glfw.ns.keycodes[0x28] = GLFW_KEY_K;
|
||||
_glfw.ns.keycodes[0x25] = GLFW_KEY_L;
|
||||
_glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
|
||||
_glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
|
||||
_glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
|
||||
_glfw.ns.keycodes[0x23] = GLFW_KEY_P;
|
||||
_glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
|
||||
_glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
|
||||
_glfw.ns.keycodes[0x01] = GLFW_KEY_S;
|
||||
_glfw.ns.keycodes[0x11] = GLFW_KEY_T;
|
||||
_glfw.ns.keycodes[0x20] = GLFW_KEY_U;
|
||||
_glfw.ns.keycodes[0x09] = GLFW_KEY_V;
|
||||
_glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
|
||||
_glfw.ns.keycodes[0x07] = GLFW_KEY_X;
|
||||
_glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
|
||||
_glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
|
||||
|
||||
_glfw.ns.publicKeys[0x27] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.ns.publicKeys[0x2A] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.ns.publicKeys[0x2B] = GLFW_KEY_COMMA;
|
||||
_glfw.ns.publicKeys[0x18] = GLFW_KEY_EQUAL;
|
||||
_glfw.ns.publicKeys[0x32] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.ns.publicKeys[0x21] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.ns.publicKeys[0x1B] = GLFW_KEY_MINUS;
|
||||
_glfw.ns.publicKeys[0x2F] = GLFW_KEY_PERIOD;
|
||||
_glfw.ns.publicKeys[0x1E] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.ns.publicKeys[0x29] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.ns.publicKeys[0x2C] = GLFW_KEY_SLASH;
|
||||
_glfw.ns.publicKeys[0x0A] = GLFW_KEY_WORLD_1;
|
||||
_glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
|
||||
_glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
|
||||
_glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
|
||||
_glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
|
||||
_glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
|
||||
_glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
|
||||
|
||||
_glfw.ns.publicKeys[0x33] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.ns.publicKeys[0x39] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.ns.publicKeys[0x75] = GLFW_KEY_DELETE;
|
||||
_glfw.ns.publicKeys[0x7D] = GLFW_KEY_DOWN;
|
||||
_glfw.ns.publicKeys[0x77] = GLFW_KEY_END;
|
||||
_glfw.ns.publicKeys[0x24] = GLFW_KEY_ENTER;
|
||||
_glfw.ns.publicKeys[0x35] = GLFW_KEY_ESCAPE;
|
||||
_glfw.ns.publicKeys[0x7A] = GLFW_KEY_F1;
|
||||
_glfw.ns.publicKeys[0x78] = GLFW_KEY_F2;
|
||||
_glfw.ns.publicKeys[0x63] = GLFW_KEY_F3;
|
||||
_glfw.ns.publicKeys[0x76] = GLFW_KEY_F4;
|
||||
_glfw.ns.publicKeys[0x60] = GLFW_KEY_F5;
|
||||
_glfw.ns.publicKeys[0x61] = GLFW_KEY_F6;
|
||||
_glfw.ns.publicKeys[0x62] = GLFW_KEY_F7;
|
||||
_glfw.ns.publicKeys[0x64] = GLFW_KEY_F8;
|
||||
_glfw.ns.publicKeys[0x65] = GLFW_KEY_F9;
|
||||
_glfw.ns.publicKeys[0x6D] = GLFW_KEY_F10;
|
||||
_glfw.ns.publicKeys[0x67] = GLFW_KEY_F11;
|
||||
_glfw.ns.publicKeys[0x6F] = GLFW_KEY_F12;
|
||||
_glfw.ns.publicKeys[0x69] = GLFW_KEY_F13;
|
||||
_glfw.ns.publicKeys[0x6B] = GLFW_KEY_F14;
|
||||
_glfw.ns.publicKeys[0x71] = GLFW_KEY_F15;
|
||||
_glfw.ns.publicKeys[0x6A] = GLFW_KEY_F16;
|
||||
_glfw.ns.publicKeys[0x40] = GLFW_KEY_F17;
|
||||
_glfw.ns.publicKeys[0x4F] = GLFW_KEY_F18;
|
||||
_glfw.ns.publicKeys[0x50] = GLFW_KEY_F19;
|
||||
_glfw.ns.publicKeys[0x5A] = GLFW_KEY_F20;
|
||||
_glfw.ns.publicKeys[0x73] = GLFW_KEY_HOME;
|
||||
_glfw.ns.publicKeys[0x72] = GLFW_KEY_INSERT;
|
||||
_glfw.ns.publicKeys[0x7B] = GLFW_KEY_LEFT;
|
||||
_glfw.ns.publicKeys[0x3A] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.ns.publicKeys[0x3B] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.ns.publicKeys[0x38] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.ns.publicKeys[0x37] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.ns.publicKeys[0x6E] = GLFW_KEY_MENU;
|
||||
_glfw.ns.publicKeys[0x47] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.ns.publicKeys[0x79] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.ns.publicKeys[0x74] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.ns.publicKeys[0x7C] = GLFW_KEY_RIGHT;
|
||||
_glfw.ns.publicKeys[0x3D] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.ns.publicKeys[0x3E] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.ns.publicKeys[0x3C] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.ns.publicKeys[0x36] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.ns.publicKeys[0x31] = GLFW_KEY_SPACE;
|
||||
_glfw.ns.publicKeys[0x30] = GLFW_KEY_TAB;
|
||||
_glfw.ns.publicKeys[0x7E] = GLFW_KEY_UP;
|
||||
_glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
|
||||
_glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
|
||||
_glfw.ns.keycodes[0x77] = GLFW_KEY_END;
|
||||
_glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
|
||||
_glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
|
||||
_glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
|
||||
_glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
|
||||
_glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
|
||||
_glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
|
||||
_glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
|
||||
_glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
|
||||
_glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
|
||||
_glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
|
||||
_glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
|
||||
_glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
|
||||
_glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
|
||||
_glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
|
||||
_glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
|
||||
_glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
|
||||
_glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
|
||||
_glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
|
||||
_glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
|
||||
_glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
|
||||
_glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
|
||||
_glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
|
||||
_glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
|
||||
_glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
|
||||
_glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
|
||||
_glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
|
||||
_glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
|
||||
_glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
|
||||
_glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
|
||||
_glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
|
||||
|
||||
_glfw.ns.publicKeys[0x52] = GLFW_KEY_KP_0;
|
||||
_glfw.ns.publicKeys[0x53] = GLFW_KEY_KP_1;
|
||||
_glfw.ns.publicKeys[0x54] = GLFW_KEY_KP_2;
|
||||
_glfw.ns.publicKeys[0x55] = GLFW_KEY_KP_3;
|
||||
_glfw.ns.publicKeys[0x56] = GLFW_KEY_KP_4;
|
||||
_glfw.ns.publicKeys[0x57] = GLFW_KEY_KP_5;
|
||||
_glfw.ns.publicKeys[0x58] = GLFW_KEY_KP_6;
|
||||
_glfw.ns.publicKeys[0x59] = GLFW_KEY_KP_7;
|
||||
_glfw.ns.publicKeys[0x5B] = GLFW_KEY_KP_8;
|
||||
_glfw.ns.publicKeys[0x5C] = GLFW_KEY_KP_9;
|
||||
_glfw.ns.publicKeys[0x45] = GLFW_KEY_KP_ADD;
|
||||
_glfw.ns.publicKeys[0x41] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.ns.publicKeys[0x4B] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.ns.publicKeys[0x4C] = GLFW_KEY_KP_ENTER;
|
||||
_glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
|
||||
_glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
|
||||
_glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
|
||||
_glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
|
||||
_glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
|
||||
_glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
|
||||
_glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
|
||||
_glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
|
||||
_glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
|
||||
_glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
|
||||
_glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
|
||||
_glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
|
||||
_glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
{
|
||||
// Store the reverse translation for faster key name lookup
|
||||
if (_glfw.ns.publicKeys[scancode] >= 0)
|
||||
_glfw.ns.nativeKeys[_glfw.ns.publicKeys[scancode]] = scancode;
|
||||
if (_glfw.ns.keycodes[scancode] >= 0)
|
||||
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,9 +243,6 @@ static GLFWbool initializeTIS(void)
|
||||
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
||||
CFStringRef* kNotifySelectedKeyboardInputSourceChanged =
|
||||
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||
CFSTR("kTISNotifySelectedKeyboardInputSourceChanged"));
|
||||
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
||||
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
||||
@@ -261,7 +254,6 @@ static GLFWbool initializeTIS(void)
|
||||
CFSTR("LMGetKbdType"));
|
||||
|
||||
if (!kPropertyUnicodeKeyLayoutData ||
|
||||
!kNotifySelectedKeyboardInputSourceChanged ||
|
||||
!TISCopyCurrentKeyboardLayoutInputSource ||
|
||||
!TISGetInputSourceProperty ||
|
||||
!LMGetKbdType)
|
||||
@@ -273,8 +265,6 @@ static GLFWbool initializeTIS(void)
|
||||
|
||||
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
||||
*kPropertyUnicodeKeyLayoutData;
|
||||
_glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged =
|
||||
*kNotifySelectedKeyboardInputSourceChanged;
|
||||
|
||||
return updateUnicodeDataNS();
|
||||
}
|
||||
@@ -300,17 +290,16 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if (_glfw.hints.init.ns.chdir)
|
||||
changeToResourcesDirectory();
|
||||
|
||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||
[[NSDistributedNotificationCenter defaultCenter]
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:_glfw.ns.listener
|
||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
changeToResourcesDirectory();
|
||||
#endif
|
||||
|
||||
createKeyTables();
|
||||
|
||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
@@ -322,15 +311,10 @@ int _glfwPlatformInit(void)
|
||||
if (!initializeTIS())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitNSGL())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerNS();
|
||||
_glfwInitJoysticksNS();
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -358,10 +342,12 @@ void _glfwPlatformTerminate(void)
|
||||
|
||||
if (_glfw.ns.listener)
|
||||
{
|
||||
[[NSDistributedNotificationCenter defaultCenter]
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener
|
||||
name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener];
|
||||
[_glfw.ns.listener release];
|
||||
_glfw.ns.listener = nil;
|
||||
}
|
||||
@@ -373,7 +359,6 @@ void _glfwPlatformTerminate(void)
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateJoysticksNS();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
[_glfw.ns.autoreleasePool release];
|
||||
_glfw.ns.autoreleasePool = nil;
|
||||
@@ -382,15 +367,6 @@ void _glfwPlatformTerminate(void)
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
||||
#if defined(_GLFW_USE_CHDIR)
|
||||
" chdir"
|
||||
#endif
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
" menubar"
|
||||
#endif
|
||||
#if defined(_GLFW_USE_RETINA)
|
||||
" retina"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" dynamic"
|
||||
#endif
|
||||
|
||||
+10
-27
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Cocoa - www.glfw.org
|
||||
// GLFW 3.3 Cocoa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,44 +24,27 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_joystick_h_
|
||||
#define _glfw3_cocoa_joystick_h_
|
||||
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoystickNS ns_js
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickNS ns
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
|
||||
|
||||
// Cocoa-specific per-joystick data
|
||||
//
|
||||
typedef struct _GLFWjoydeviceNS
|
||||
{
|
||||
GLFWbool present;
|
||||
char name[256];
|
||||
|
||||
IOHIDDeviceRef deviceRef;
|
||||
|
||||
CFMutableArrayRef axisElements;
|
||||
CFMutableArrayRef buttonElements;
|
||||
CFMutableArrayRef hatElements;
|
||||
|
||||
float* axes;
|
||||
unsigned char* buttons;
|
||||
} _GLFWjoydeviceNS;
|
||||
|
||||
// Cocoa-specific joystick API data
|
||||
//
|
||||
typedef struct _GLFWjoystickNS
|
||||
{
|
||||
_GLFWjoydeviceNS js[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
IOHIDManagerRef managerRef;
|
||||
IOHIDDeviceRef device;
|
||||
CFMutableArrayRef axes;
|
||||
CFMutableArrayRef buttons;
|
||||
CFMutableArrayRef hats;
|
||||
} _GLFWjoystickNS;
|
||||
|
||||
|
||||
void _glfwInitJoysticksNS(void);
|
||||
void _glfwTerminateJoysticksNS(void);
|
||||
|
||||
#endif // _glfw3_cocoa_joystick_h_
|
||||
|
||||
+321
-373
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Cocoa - www.glfw.org
|
||||
// GLFW 3.3 Cocoa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
@@ -42,42 +42,164 @@
|
||||
//
|
||||
typedef struct _GLFWjoyelementNS
|
||||
{
|
||||
IOHIDElementRef elementRef;
|
||||
|
||||
long min;
|
||||
long max;
|
||||
|
||||
long minReport;
|
||||
long maxReport;
|
||||
IOHIDElementRef native;
|
||||
uint32_t usage;
|
||||
int index;
|
||||
long minimum;
|
||||
long maximum;
|
||||
|
||||
} _GLFWjoyelementNS;
|
||||
|
||||
|
||||
static void getElementsCFArrayHandler(const void* value, void* parameter);
|
||||
|
||||
// Adds an element to the specified joystick
|
||||
// Returns the value of the specified element of the specified joystick
|
||||
//
|
||||
static void addJoystickElement(_GLFWjoydeviceNS* js,
|
||||
IOHIDElementRef elementRef)
|
||||
static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
||||
{
|
||||
IOHIDElementType elementType;
|
||||
long usagePage, usage;
|
||||
CFMutableArrayRef elementsArray = NULL;
|
||||
IOHIDValueRef valueRef;
|
||||
long value = 0;
|
||||
|
||||
elementType = IOHIDElementGetType(elementRef);
|
||||
usagePage = IOHIDElementGetUsagePage(elementRef);
|
||||
usage = IOHIDElementGetUsage(elementRef);
|
||||
|
||||
if ((elementType != kIOHIDElementTypeInput_Axis) &&
|
||||
(elementType != kIOHIDElementTypeInput_Button) &&
|
||||
(elementType != kIOHIDElementTypeInput_Misc))
|
||||
if (js->ns.device)
|
||||
{
|
||||
return;
|
||||
if (IOHIDDeviceGetValue(js->ns.device,
|
||||
element->native,
|
||||
&valueRef) == kIOReturnSuccess)
|
||||
{
|
||||
value = IOHIDValueGetIntegerValue(valueRef);
|
||||
}
|
||||
}
|
||||
|
||||
switch (usagePage)
|
||||
return value;
|
||||
}
|
||||
|
||||
// Comparison function for matching the SDL element order
|
||||
//
|
||||
static CFComparisonResult compareElements(const void* fp, const void* sp, void* user)
|
||||
{
|
||||
const _GLFWjoyelementNS* fe = fp;
|
||||
const _GLFWjoyelementNS* se = sp;
|
||||
if (fe->usage < se->usage)
|
||||
return kCFCompareLessThan;
|
||||
if (fe->usage > se->usage)
|
||||
return kCFCompareGreaterThan;
|
||||
if (fe->index < se->index)
|
||||
return kCFCompareLessThan;
|
||||
if (fe->index > se->index)
|
||||
return kCFCompareGreaterThan;
|
||||
return kCFCompareEqualTo;
|
||||
}
|
||||
|
||||
// Removes the specified joystick
|
||||
//
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!js->present)
|
||||
return;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
|
||||
CFRelease(js->ns.axes);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
|
||||
CFRelease(js->ns.buttons);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
|
||||
CFRelease(js->ns.hats);
|
||||
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick addition
|
||||
//
|
||||
static void matchCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef device)
|
||||
{
|
||||
int jid;
|
||||
char name[256];
|
||||
char guid[33];
|
||||
CFIndex i;
|
||||
CFTypeRef property;
|
||||
uint32_t vendor = 0, product = 0, version = 0;
|
||||
_GLFWjoystick* js;
|
||||
CFMutableArrayRef axes, buttons, hats;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
case kHIDPage_GenericDesktop:
|
||||
if (_glfw.joysticks[jid].ns.device == device)
|
||||
return;
|
||||
}
|
||||
|
||||
axes = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
buttons = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
hats = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||
if (property)
|
||||
{
|
||||
CFStringGetCString(property,
|
||||
name,
|
||||
sizeof(name),
|
||||
kCFStringEncodingUTF8);
|
||||
}
|
||||
else
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &product);
|
||||
|
||||
property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
|
||||
if (property)
|
||||
CFNumberGetValue(property, kCFNumberSInt32Type, &version);
|
||||
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (vendor && product)
|
||||
{
|
||||
sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||
(uint8_t) vendor, (uint8_t) (vendor >> 8),
|
||||
(uint8_t) product, (uint8_t) (product >> 8),
|
||||
(uint8_t) version, (uint8_t) (version >> 8));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
CFArrayRef elements =
|
||||
IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(elements); i++)
|
||||
{
|
||||
IOHIDElementRef native = (IOHIDElementRef) CFArrayGetValueAtIndex(elements, i);
|
||||
if (CFGetTypeID(native) != IOHIDElementGetTypeID())
|
||||
continue;
|
||||
|
||||
const IOHIDElementType type = IOHIDElementGetType(native);
|
||||
if ((type != kIOHIDElementTypeInput_Axis) &&
|
||||
(type != kIOHIDElementTypeInput_Button) &&
|
||||
(type != kIOHIDElementTypeInput_Misc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CFMutableArrayRef target = NULL;
|
||||
|
||||
const uint32_t usage = IOHIDElementGetUsage(native);
|
||||
const uint32_t page = IOHIDElementGetUsagePage(native);
|
||||
if (page == kHIDPage_GenericDesktop)
|
||||
{
|
||||
switch (usage)
|
||||
{
|
||||
@@ -90,241 +212,48 @@ static void addJoystickElement(_GLFWjoydeviceNS* js,
|
||||
case kHIDUsage_GD_Slider:
|
||||
case kHIDUsage_GD_Dial:
|
||||
case kHIDUsage_GD_Wheel:
|
||||
elementsArray = js->axisElements;
|
||||
target = axes;
|
||||
break;
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
elementsArray = js->hatElements;
|
||||
target = hats;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else if (page == kHIDPage_Button)
|
||||
target = buttons;
|
||||
|
||||
case kHIDPage_Button:
|
||||
elementsArray = js->buttonElements;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (elementsArray)
|
||||
{
|
||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||
|
||||
CFArrayAppendValue(elementsArray, element);
|
||||
|
||||
element->elementRef = elementRef;
|
||||
|
||||
element->minReport = IOHIDElementGetLogicalMin(elementRef);
|
||||
element->maxReport = IOHIDElementGetLogicalMax(elementRef);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds an element to the specified joystick
|
||||
//
|
||||
static void getElementsCFArrayHandler(const void* value, void* parameter)
|
||||
{
|
||||
if (CFGetTypeID(value) == IOHIDElementGetTypeID())
|
||||
{
|
||||
addJoystickElement((_GLFWjoydeviceNS*) parameter,
|
||||
(IOHIDElementRef) value);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the value of the specified element of the specified joystick
|
||||
//
|
||||
static long getElementValue(_GLFWjoydeviceNS* js, _GLFWjoyelementNS* element)
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess;
|
||||
IOHIDValueRef valueRef;
|
||||
long value = 0;
|
||||
|
||||
if (js && element && js->deviceRef)
|
||||
{
|
||||
result = IOHIDDeviceGetValue(js->deviceRef,
|
||||
element->elementRef,
|
||||
&valueRef);
|
||||
|
||||
if (kIOReturnSuccess == result)
|
||||
if (target)
|
||||
{
|
||||
value = IOHIDValueGetIntegerValue(valueRef);
|
||||
|
||||
// Record min and max for auto calibration
|
||||
if (value < element->minReport)
|
||||
element->minReport = value;
|
||||
if (value > element->maxReport)
|
||||
element->maxReport = value;
|
||||
_GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
|
||||
element->native = native;
|
||||
element->usage = usage;
|
||||
element->index = (int) CFArrayGetCount(target);
|
||||
element->minimum = IOHIDElementGetLogicalMin(native);
|
||||
element->maximum = IOHIDElementGetLogicalMax(native);
|
||||
CFArrayAppendValue(target, element);
|
||||
}
|
||||
}
|
||||
|
||||
// Auto user scale
|
||||
return value;
|
||||
}
|
||||
CFRelease(elements);
|
||||
|
||||
// Removes the specified joystick
|
||||
//
|
||||
static void removeJoystick(_GLFWjoydeviceNS* js)
|
||||
{
|
||||
int i;
|
||||
CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
|
||||
compareElements, NULL);
|
||||
CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
|
||||
compareElements, NULL);
|
||||
CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
|
||||
compareElements, NULL);
|
||||
|
||||
if (!js->present)
|
||||
return;
|
||||
js = _glfwAllocJoystick(name, guid,
|
||||
CFArrayGetCount(axes),
|
||||
CFArrayGetCount(buttons),
|
||||
CFArrayGetCount(hats));
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
|
||||
CFArrayRemoveAllValues(js->axisElements);
|
||||
CFRelease(js->axisElements);
|
||||
js->ns.device = device;
|
||||
js->ns.axes = axes;
|
||||
js->ns.buttons = buttons;
|
||||
js->ns.hats = hats;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
|
||||
CFArrayRemoveAllValues(js->buttonElements);
|
||||
CFRelease(js->buttonElements);
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
||||
free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
|
||||
CFArrayRemoveAllValues(js->hatElements);
|
||||
CFRelease(js->hatElements);
|
||||
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
|
||||
memset(js, 0, sizeof(_GLFWjoydeviceNS));
|
||||
|
||||
_glfwInputJoystickChange(js - _glfw.ns_js.js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Polls for joystick axis events and updates GLFW state
|
||||
//
|
||||
static GLFWbool pollJoystickAxisEvents(_GLFWjoydeviceNS* js)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->axisElements, i);
|
||||
|
||||
long value = getElementValue(js, axis);
|
||||
long readScale = axis->maxReport - axis->minReport;
|
||||
|
||||
if (readScale == 0)
|
||||
js->axes[i] = value;
|
||||
else
|
||||
js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Polls for joystick button events and updates GLFW state
|
||||
//
|
||||
static GLFWbool pollJoystickButtonEvents(_GLFWjoydeviceNS* js)
|
||||
{
|
||||
CFIndex i;
|
||||
int buttonIndex = 0;
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->buttonElements, i);
|
||||
|
||||
if (getElementValue(js, button))
|
||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||
}
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->hatElements, i);
|
||||
|
||||
// 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, value = getElementValue(js, hat);
|
||||
if (value < 0 || value > 8)
|
||||
value = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (directions[value] & (1 << j))
|
||||
js->buttons[buttonIndex++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[buttonIndex++] = GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick addition
|
||||
//
|
||||
static void matchCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
{
|
||||
_GLFWjoydeviceNS* js;
|
||||
int joy;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
{
|
||||
if (_glfw.ns_js.js[joy].present && _glfw.ns_js.js[joy].deviceRef == deviceRef)
|
||||
return;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
{
|
||||
if (!_glfw.ns_js.js[joy].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
return;
|
||||
|
||||
js = _glfw.ns_js.js + joy;
|
||||
js->present = GLFW_TRUE;
|
||||
js->deviceRef = deviceRef;
|
||||
|
||||
CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
|
||||
CFSTR(kIOHIDProductKey));
|
||||
if (name)
|
||||
{
|
||||
CFStringGetCString(name,
|
||||
js->name,
|
||||
sizeof(js->name),
|
||||
kCFStringEncodingUTF8);
|
||||
}
|
||||
else
|
||||
strncpy(js->name, "Unknown", sizeof(js->name));
|
||||
|
||||
js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
|
||||
|
||||
CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
|
||||
NULL,
|
||||
kIOHIDOptionsTypeNone);
|
||||
CFRange range = { 0, CFArrayGetCount(arrayRef) };
|
||||
CFArrayApplyFunction(arrayRef,
|
||||
range,
|
||||
getElementsCFArrayHandler,
|
||||
(void*) js);
|
||||
|
||||
CFRelease(arrayRef);
|
||||
|
||||
js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
|
||||
js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
|
||||
CFArrayGetCount(js->hatElements) * 4, 1);
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
// Callback for user-initiated joystick removal
|
||||
@@ -332,60 +261,20 @@ static void matchCallback(void* context,
|
||||
static void removeCallback(void* context,
|
||||
IOReturn result,
|
||||
void* sender,
|
||||
IOHIDDeviceRef deviceRef)
|
||||
IOHIDDeviceRef device)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.ns_js.js[joy].deviceRef == deviceRef)
|
||||
if (_glfw.joysticks[jid].ns.device == device)
|
||||
{
|
||||
removeJoystick(_glfw.ns_js.js + joy);
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a dictionary to match against devices with the specified usage page
|
||||
// and usage
|
||||
//
|
||||
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
||||
long usage)
|
||||
{
|
||||
CFMutableDictionaryRef result =
|
||||
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
if (result)
|
||||
{
|
||||
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usagePage);
|
||||
if (pageRef)
|
||||
{
|
||||
CFDictionarySetValue(result,
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
pageRef);
|
||||
CFRelease(pageRef);
|
||||
|
||||
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usage);
|
||||
if (usageRef)
|
||||
{
|
||||
CFDictionarySetValue(result,
|
||||
CFSTR(kIOHIDDeviceUsageKey),
|
||||
usageRef);
|
||||
CFRelease(usageRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@@ -395,57 +284,74 @@ static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
|
||||
//
|
||||
void _glfwInitJoysticksNS(void)
|
||||
{
|
||||
CFMutableArrayRef matchingCFArrayRef;
|
||||
|
||||
_glfw.ns_js.managerRef = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||
kIOHIDOptionsTypeNone);
|
||||
|
||||
matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeArrayCallBacks);
|
||||
if (matchingCFArrayRef)
|
||||
CFMutableArrayRef matching;
|
||||
const long usages[] =
|
||||
{
|
||||
CFDictionaryRef matchingCFDictRef =
|
||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_Joystick);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
kHIDUsage_GD_Joystick,
|
||||
kHIDUsage_GD_GamePad,
|
||||
kHIDUsage_GD_MultiAxisController
|
||||
};
|
||||
|
||||
matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_GamePad);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
_glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
|
||||
kIOHIDOptionsTypeNone);
|
||||
|
||||
matchingCFDictRef =
|
||||
createMatchingDictionary(kHIDPage_GenericDesktop,
|
||||
kHIDUsage_GD_MultiAxisController);
|
||||
if (matchingCFDictRef)
|
||||
{
|
||||
CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
|
||||
CFRelease(matchingCFDictRef);
|
||||
}
|
||||
|
||||
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns_js.managerRef,
|
||||
matchingCFArrayRef);
|
||||
CFRelease(matchingCFArrayRef);
|
||||
matching = CFArrayCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeArrayCallBacks);
|
||||
if (!matching)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
|
||||
return;
|
||||
}
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns_js.managerRef,
|
||||
&matchCallback, NULL);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns_js.managerRef,
|
||||
&removeCallback, NULL);
|
||||
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||
{
|
||||
const long page = kHIDPage_GenericDesktop;
|
||||
|
||||
IOHIDManagerScheduleWithRunLoop(_glfw.ns_js.managerRef,
|
||||
CFMutableDictionaryRef dict =
|
||||
CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
if (!dict)
|
||||
continue;
|
||||
|
||||
CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&page);
|
||||
CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberLongType,
|
||||
&usages[i]);
|
||||
if (pageRef && usageRef)
|
||||
{
|
||||
CFDictionarySetValue(dict,
|
||||
CFSTR(kIOHIDDeviceUsagePageKey),
|
||||
pageRef);
|
||||
CFDictionarySetValue(dict,
|
||||
CFSTR(kIOHIDDeviceUsageKey),
|
||||
usageRef);
|
||||
CFArrayAppendValue(matching, dict);
|
||||
}
|
||||
|
||||
if (pageRef)
|
||||
CFRelease(pageRef);
|
||||
if (usageRef)
|
||||
CFRelease(usageRef);
|
||||
|
||||
CFRelease(dict);
|
||||
}
|
||||
|
||||
IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
|
||||
CFRelease(matching);
|
||||
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
|
||||
&matchCallback, NULL);
|
||||
IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
|
||||
&removeCallback, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
|
||||
CFRunLoopGetMain(),
|
||||
kCFRunLoopDefaultMode);
|
||||
|
||||
IOHIDManagerOpen(_glfw.ns_js.managerRef, kIOHIDOptionsTypeNone);
|
||||
IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
|
||||
|
||||
// Execute the run loop once in order to register any initially-attached
|
||||
// joysticks
|
||||
@@ -456,16 +362,13 @@ void _glfwInitJoysticksNS(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksNS(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
{
|
||||
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
|
||||
removeJoystick(js);
|
||||
}
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
CFRelease(_glfw.ns_js.managerRef);
|
||||
_glfw.ns_js.managerRef = NULL;
|
||||
CFRelease(_glfw.ns.hidManager);
|
||||
_glfw.ns.hidManager = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -473,39 +376,84 @@ void _glfwTerminateJoysticksNS(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
|
||||
if (mode & _GLFW_POLL_AXES)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.axes); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.axes, i);
|
||||
|
||||
const long raw = getElementValue(js, axis);
|
||||
// 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)
|
||||
_glfwInputJoystickAxis(js, i, 0.f);
|
||||
else
|
||||
{
|
||||
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
|
||||
_glfwInputJoystickAxis(js, i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mode & _GLFW_POLL_BUTTONS)
|
||||
{
|
||||
CFIndex i;
|
||||
|
||||
for (i = 0; i < CFArrayGetCount(js->ns.buttons); i++)
|
||||
{
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||
const char value = getElementValue(js, button) - button->minimum;
|
||||
_glfwInputJoystickButton(js, i, value);
|
||||
}
|
||||
|
||||
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*)
|
||||
CFArrayGetValueAtIndex(js->ns.hats, i);
|
||||
long state = getElementValue(js, hat) - hat->minimum;
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, i, states[state]);
|
||||
}
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
|
||||
if (!pollJoystickAxisEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = (int) CFArrayGetCount(js->axisElements);
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
{
|
||||
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
|
||||
if (!pollJoystickButtonEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = (int) CFArrayGetCount(js->buttonElements) +
|
||||
(int) CFArrayGetCount(js->hatElements) * 4;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
{
|
||||
_GLFWjoydeviceNS* js = _glfw.ns_js.js + joy;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
|
||||
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||
{
|
||||
char original[33];
|
||||
strcpy(original, guid);
|
||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||
original, original + 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+137
-77
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -27,50 +27,88 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
#include <CoreVideo/CVBase.h>
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
|
||||
|
||||
// Get the name of the specified display
|
||||
// Get the name of the specified display, or NULL
|
||||
//
|
||||
static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
{
|
||||
char* name;
|
||||
CFDictionaryRef info, names;
|
||||
CFStringRef value;
|
||||
CFIndex size;
|
||||
io_iterator_t it;
|
||||
io_service_t service;
|
||||
CFDictionaryRef info;
|
||||
|
||||
// NOTE: This uses a deprecated function because Apple has
|
||||
// (as of January 2015) not provided any alternative
|
||||
info = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID),
|
||||
kIODisplayOnlyPreferredName);
|
||||
names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
|
||||
|
||||
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
|
||||
(const void**) &value))
|
||||
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
||||
IOServiceMatching("IODisplayConnect"),
|
||||
&it) != 0)
|
||||
{
|
||||
// This may happen if a desktop Mac is running headless
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to retrieve display name");
|
||||
|
||||
CFRelease(info);
|
||||
return strdup("Unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
|
||||
kCFStringEncodingUTF8);
|
||||
name = calloc(size + 1, sizeof(char));
|
||||
CFStringGetCString(value, name, size, kCFStringEncodingUTF8);
|
||||
while ((service = IOIteratorNext(it)) != 0)
|
||||
{
|
||||
info = IODisplayCreateInfoDictionary(service, kIODisplayOnlyPreferredName);
|
||||
|
||||
CFNumberRef vendorIDRef =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
|
||||
CFNumberRef productIDRef =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
|
||||
if (!vendorIDRef || !productIDRef)
|
||||
{
|
||||
CFRelease(info);
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int vendorID, productID;
|
||||
CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
|
||||
CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
|
||||
|
||||
if (CGDisplayVendorNumber(displayID) == vendorID &&
|
||||
CGDisplayModelNumber(displayID) == productID)
|
||||
{
|
||||
// Info dictionary is used and freed below
|
||||
break;
|
||||
}
|
||||
|
||||
CFRelease(info);
|
||||
}
|
||||
|
||||
IOObjectRelease(it);
|
||||
|
||||
if (!service)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find service port for display");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CFDictionaryRef names =
|
||||
CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
|
||||
|
||||
CFStringRef nameRef;
|
||||
|
||||
if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
|
||||
(const void**) &nameRef))
|
||||
{
|
||||
// This may happen if a desktop Mac is running headless
|
||||
CFRelease(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const CFIndex size =
|
||||
CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
|
||||
kCFStringEncodingUTF8);
|
||||
char* name = calloc(size + 1, 1);
|
||||
CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
|
||||
|
||||
CFRelease(info);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -79,15 +117,15 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
||||
{
|
||||
uint32_t flags = CGDisplayModeGetIOFlags(mode);
|
||||
|
||||
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (flags & kDisplayModeInterlacedFlag)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (flags & kDisplayModeStretchedFlag)
|
||||
return GLFW_FALSE;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
|
||||
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||
@@ -97,6 +135,7 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
||||
}
|
||||
|
||||
CFRelease(format);
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -117,8 +156,8 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||
|
||||
if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
|
||||
{
|
||||
result.redBits = 5;
|
||||
@@ -126,13 +165,16 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||
result.blueBits = 5;
|
||||
}
|
||||
else
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
{
|
||||
result.redBits = 8;
|
||||
result.greenBits = 8;
|
||||
result.blueBits = 8;
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFRelease(format);
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -164,6 +206,71 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsNS(void)
|
||||
{
|
||||
uint32_t i, j, displayCount, disconnectedCount;
|
||||
CGDirectDisplayID* displays;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (i = 0; i < displayCount; i++)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
continue;
|
||||
|
||||
for (j = 0; j < disconnectedCount; j++)
|
||||
{
|
||||
// HACK: Compare unit numbers instead of display IDs to work around
|
||||
// display replacement on machines with automatic graphics
|
||||
// switching
|
||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||
{
|
||||
disconnected[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i]);
|
||||
if (!name)
|
||||
name = strdup("Unknown");
|
||||
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = unitNumber;
|
||||
|
||||
free(name);
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
free(displays);
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
//
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
@@ -243,53 +350,6 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
uint32_t i, found = 0, displayCount;
|
||||
_GLFWmonitor** monitors;
|
||||
CGDirectDisplayID* displays;
|
||||
|
||||
*count = 0;
|
||||
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
|
||||
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
|
||||
for (i = 0; i < displayCount; i++)
|
||||
{
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
if (CGDisplayIsAsleep(displays[i]))
|
||||
continue;
|
||||
|
||||
const CGSize size = CGDisplayScreenSize(displays[i]);
|
||||
char* name = getDisplayName(displays[i]);
|
||||
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||
|
||||
free(name);
|
||||
|
||||
found++;
|
||||
monitors[found - 1] = monitor;
|
||||
}
|
||||
|
||||
free(displays);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
// HACK: Compare unit numbers instead of display IDs to work around display
|
||||
// replacement on machines with automatic graphics switching
|
||||
return first->ns.unitNumber == second->ns.unitNumber;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
|
||||
|
||||
+31
-21
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,9 +24,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_cocoa_platform_h_
|
||||
#define _glfw3_cocoa_platform_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -39,26 +36,39 @@
|
||||
typedef void* id;
|
||||
#endif
|
||||
|
||||
#include "posix_tls.h"
|
||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||
|
||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMacOSSurfaceCreateFlagsMVK flags;
|
||||
const void* pView;
|
||||
} VkMacOSSurfaceCreateInfoMVK;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
|
||||
#include "posix_thread.h"
|
||||
#include "cocoa_joystick.h"
|
||||
#include "nsgl_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->ns.view)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS 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_CURSOR_STATE _GLFWcursorNS ns
|
||||
|
||||
#define _GLFW_EGL_CONTEXT_STATE
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||
|
||||
// HIToolbox.framework pointer typedefs
|
||||
#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
|
||||
#define kTISNotifySelectedKeyboardInputSourceChanged _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged
|
||||
typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
|
||||
#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource
|
||||
typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
|
||||
@@ -74,6 +84,9 @@ typedef struct _GLFWwindowNS
|
||||
id object;
|
||||
id delegate;
|
||||
id view;
|
||||
id layer;
|
||||
|
||||
GLFWbool maximized;
|
||||
|
||||
// The total sum of the distances the cursor has been warped
|
||||
// since the last cursor motion event was processed
|
||||
@@ -82,7 +95,6 @@ typedef struct _GLFWwindowNS
|
||||
|
||||
} _GLFWwindowNS;
|
||||
|
||||
|
||||
// Cocoa-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryNS
|
||||
@@ -92,13 +104,15 @@ typedef struct _GLFWlibraryNS
|
||||
id autoreleasePool;
|
||||
id cursor;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
id unicodeData;
|
||||
id listener;
|
||||
|
||||
char keyName[64];
|
||||
short int publicKeys[256];
|
||||
short int nativeKeys[GLFW_KEY_LAST + 1];
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
char* clipboardString;
|
||||
CGPoint cascadePoint;
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
@@ -110,12 +124,10 @@ typedef struct _GLFWlibraryNS
|
||||
PFN_TISGetInputSourceProperty GetInputSourceProperty;
|
||||
PFN_LMGetKbdType GetKbdType;
|
||||
CFStringRef kPropertyUnicodeKeyLayoutData;
|
||||
CFStringRef kNotifySelectedKeyboardInputSourceChanged;
|
||||
} tis;
|
||||
|
||||
} _GLFWlibraryNS;
|
||||
|
||||
|
||||
// Cocoa-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorNS
|
||||
@@ -126,7 +138,6 @@ typedef struct _GLFWmonitorNS
|
||||
|
||||
} _GLFWmonitorNS;
|
||||
|
||||
|
||||
// Cocoa-specific per-cursor data
|
||||
//
|
||||
typedef struct _GLFWcursorNS
|
||||
@@ -135,19 +146,18 @@ typedef struct _GLFWcursorNS
|
||||
|
||||
} _GLFWcursorNS;
|
||||
|
||||
|
||||
// Cocoa-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimeNS
|
||||
typedef struct _GLFWtimerNS
|
||||
{
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimeNS;
|
||||
} _GLFWtimerNS;
|
||||
|
||||
|
||||
void _glfwInitTimerNS(void);
|
||||
|
||||
void _glfwPollMonitorsNS(void);
|
||||
GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||
|
||||
#endif // _glfw3_cocoa_platform_h_
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -40,7 +40,7 @@ void _glfwInitTimerNS(void)
|
||||
mach_timebase_info_data_t 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)
|
||||
{
|
||||
return _glfw.ns_time.frequency;
|
||||
return _glfw.timer.ns.frequency;
|
||||
}
|
||||
|
||||
|
||||
+279
-117
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -32,29 +32,23 @@
|
||||
// Needed for _NSGetProgname
|
||||
#include <crt_externs.h>
|
||||
|
||||
// HACK: The 10.12 SDK adds new symbols and immediately deprecates the old ones
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
|
||||
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
||||
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
||||
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||
#define NSEventModifierFlagControl NSControlKeyMask
|
||||
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||
#define NSEventTypeKeyUp NSKeyUp
|
||||
#endif
|
||||
|
||||
// Returns the specified standard cursor
|
||||
//
|
||||
static NSCursor* getStandardCursor(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
case GLFW_ARROW_CURSOR:
|
||||
return [NSCursor arrowCursor];
|
||||
case GLFW_IBEAM_CURSOR:
|
||||
return [NSCursor IBeamCursor];
|
||||
case GLFW_CROSSHAIR_CURSOR:
|
||||
return [NSCursor crosshairCursor];
|
||||
case GLFW_HAND_CURSOR:
|
||||
return [NSCursor pointingHandCursor];
|
||||
case GLFW_HRESIZE_CURSOR:
|
||||
return [NSCursor resizeLeftRightCursor];
|
||||
case GLFW_VRESIZE_CURSOR:
|
||||
return [NSCursor resizeUpDownCursor];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Returns the style mask corresponding to the window settings
|
||||
//
|
||||
@@ -63,14 +57,15 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
|
||||
NSUInteger styleMask = 0;
|
||||
|
||||
if (window->monitor || !window->decorated)
|
||||
styleMask |= NSBorderlessWindowMask;
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
else
|
||||
{
|
||||
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
|
||||
NSMiniaturizableWindowMask;
|
||||
styleMask |= NSWindowStyleMaskTitled |
|
||||
NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable;
|
||||
|
||||
if (window->resizable)
|
||||
styleMask |= NSResizableWindowMask;
|
||||
styleMask |= NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
return styleMask;
|
||||
@@ -129,7 +124,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
|
||||
|
||||
[window->ns.object setFrame:frame display:YES];
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, window);
|
||||
_glfwInputMonitorWindow(window->monitor, window);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -140,36 +135,36 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
if (window->monitor->window != window)
|
||||
return;
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, NULL);
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
_glfwRestoreVideoModeNS(window->monitor);
|
||||
}
|
||||
|
||||
// Translates OS X key modifiers into GLFW ones
|
||||
// Translates macOS key modifiers into GLFW ones
|
||||
//
|
||||
static int translateFlags(NSUInteger flags)
|
||||
{
|
||||
int mods = 0;
|
||||
|
||||
if (flags & NSShiftKeyMask)
|
||||
if (flags & NSEventModifierFlagShift)
|
||||
mods |= GLFW_MOD_SHIFT;
|
||||
if (flags & NSControlKeyMask)
|
||||
if (flags & NSEventModifierFlagControl)
|
||||
mods |= GLFW_MOD_CONTROL;
|
||||
if (flags & NSAlternateKeyMask)
|
||||
if (flags & NSEventModifierFlagOption)
|
||||
mods |= GLFW_MOD_ALT;
|
||||
if (flags & NSCommandKeyMask)
|
||||
if (flags & NSEventModifierFlagCommand)
|
||||
mods |= GLFW_MOD_SUPER;
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
// Translates a OS X keycode to a GLFW keycode
|
||||
// Translates a macOS keycode to a GLFW keycode
|
||||
//
|
||||
static int translateKey(unsigned int key)
|
||||
{
|
||||
if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
|
||||
if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
|
||||
return _glfw.ns.publicKeys[key];
|
||||
return _glfw.ns.keycodes[key];
|
||||
}
|
||||
|
||||
// Translate a GLFW keycode to a Cocoa modifier flag
|
||||
@@ -180,16 +175,16 @@ static NSUInteger translateKeyToModifierFlag(int key)
|
||||
{
|
||||
case GLFW_KEY_LEFT_SHIFT:
|
||||
case GLFW_KEY_RIGHT_SHIFT:
|
||||
return NSShiftKeyMask;
|
||||
return NSEventModifierFlagShift;
|
||||
case GLFW_KEY_LEFT_CONTROL:
|
||||
case GLFW_KEY_RIGHT_CONTROL:
|
||||
return NSControlKeyMask;
|
||||
return NSEventModifierFlagControl;
|
||||
case GLFW_KEY_LEFT_ALT:
|
||||
case GLFW_KEY_RIGHT_ALT:
|
||||
return NSAlternateKeyMask;
|
||||
return NSEventModifierFlagOption;
|
||||
case GLFW_KEY_LEFT_SUPER:
|
||||
case GLFW_KEY_RIGHT_SUPER:
|
||||
return NSCommandKeyMask;
|
||||
return NSEventModifierFlagCommand;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -238,6 +233,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
if (_glfw.ns.disabledCursorWindow == window)
|
||||
centerCursor(window);
|
||||
|
||||
const int maximized = [window->ns.object isZoomed];
|
||||
if (window->ns.maximized != maximized)
|
||||
{
|
||||
window->ns.maximized = maximized;
|
||||
_glfwInputWindowMaximize(window, maximized);
|
||||
}
|
||||
|
||||
const NSRect contentRect = [window->ns.view frame];
|
||||
const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
|
||||
|
||||
@@ -315,7 +317,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
||||
{
|
||||
_glfwInputMonitorChange();
|
||||
_GLFWwindow* window;
|
||||
|
||||
for (window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
[window->context.nsgl.object update];
|
||||
}
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||
@@ -406,6 +416,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)wantsUpdateLayer
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (id)makeBackingLayer
|
||||
{
|
||||
if (window->ns.layer)
|
||||
return window->ns.layer;
|
||||
|
||||
return [super makeBackingLayer];
|
||||
}
|
||||
|
||||
- (void)cursorUpdate:(NSEvent *)event
|
||||
{
|
||||
updateCursorImage(window);
|
||||
@@ -558,7 +581,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
{
|
||||
int action;
|
||||
const unsigned int modifierFlags =
|
||||
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
|
||||
[event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
const int key = translateKey([event keyCode]);
|
||||
const int mods = translateFlags(modifierFlags);
|
||||
const NSUInteger keyFlag = translateKeyToModifierFlag(key);
|
||||
@@ -753,7 +776,12 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
|
||||
- (BOOL)canBecomeKeyWindow
|
||||
{
|
||||
// Required for NSBorderlessWindowMask windows
|
||||
// Required for NSWindowStyleMaskBorderless windows
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeMainWindow
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -765,6 +793,10 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
@interface GLFWApplication : NSApplication
|
||||
{
|
||||
NSArray* nibObjects;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GLFWApplication
|
||||
@@ -774,8 +806,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
// down the command key don't get sent to the key window.
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
|
||||
if ([event type] == NSEventTypeKeyUp &&
|
||||
([event modifierFlags] & NSEventModifierFlagCommand))
|
||||
{
|
||||
[[self keyWindow] sendEvent:event];
|
||||
}
|
||||
else
|
||||
[super sendEvent:event];
|
||||
}
|
||||
@@ -786,53 +821,58 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||
- (void)doNothing:(id)object
|
||||
{
|
||||
}
|
||||
|
||||
- (void)loadMainMenu
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
|
||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
||||
owner:NSApp
|
||||
topLevelObjects:&nibObjects];
|
||||
#else
|
||||
[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp];
|
||||
#endif
|
||||
}
|
||||
@end
|
||||
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
|
||||
// Try to figure out what the calling application is called
|
||||
// Set up the menu bar (manually)
|
||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||
// could go away at any moment, lots of stuff that really should be
|
||||
// localize(d|able), etc. Add a nib to save us this horror.
|
||||
//
|
||||
static NSString* findAppName(void)
|
||||
static void createMenuBar(void)
|
||||
{
|
||||
size_t i;
|
||||
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
|
||||
|
||||
// Keys to search for as potential application names
|
||||
NSString* GLFWNameKeys[] =
|
||||
NSString* appName = nil;
|
||||
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
||||
NSString* nameKeys[] =
|
||||
{
|
||||
@"CFBundleDisplayName",
|
||||
@"CFBundleName",
|
||||
@"CFBundleExecutable",
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++)
|
||||
// Try to figure out what the calling application is called
|
||||
|
||||
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
|
||||
{
|
||||
id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
|
||||
id name = [bundleInfo objectForKey:nameKeys[i]];
|
||||
if (name &&
|
||||
[name isKindOfClass:[NSString class]] &&
|
||||
![name isEqualToString:@""])
|
||||
{
|
||||
return name;
|
||||
appName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char** progname = _NSGetProgname();
|
||||
if (progname && *progname)
|
||||
return [NSString stringWithUTF8String:*progname];
|
||||
|
||||
// Really shouldn't get here
|
||||
return @"GLFW Application";
|
||||
}
|
||||
|
||||
// Set up the menu bar (manually)
|
||||
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||
// could go away at any moment, lots of stuff that really should be
|
||||
// localize(d|able), etc. Loading a nib would save us this horror, but that
|
||||
// doesn't seem like a good thing to require of GLFW users.
|
||||
//
|
||||
static void createMenuBar(void)
|
||||
{
|
||||
NSString* appName = findAppName();
|
||||
if (!appName)
|
||||
{
|
||||
char** progname = _NSGetProgname();
|
||||
if (progname && *progname)
|
||||
appName = [NSString stringWithUTF8String:*progname];
|
||||
else
|
||||
appName = @"GLFW Application";
|
||||
}
|
||||
|
||||
NSMenu* bar = [[NSMenu alloc] init];
|
||||
[NSApp setMainMenu:bar];
|
||||
@@ -859,7 +899,7 @@ static void createMenuBar(void)
|
||||
[[appMenu addItemWithTitle:@"Hide Others"
|
||||
action:@selector(hideOtherApplications:)
|
||||
keyEquivalent:@"h"]
|
||||
setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
|
||||
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
||||
[appMenu addItemWithTitle:@"Show All"
|
||||
action:@selector(unhideAllApplications:)
|
||||
keyEquivalent:@""];
|
||||
@@ -891,7 +931,7 @@ static void createMenuBar(void)
|
||||
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
||||
action:@selector(toggleFullScreen:)
|
||||
keyEquivalent:@"f"]
|
||||
setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];
|
||||
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||
|
||||
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
||||
// to get the application menu working properly.
|
||||
@@ -899,8 +939,6 @@ static void createMenuBar(void)
|
||||
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
||||
}
|
||||
|
||||
#endif /* _GLFW_USE_MENUBAR */
|
||||
|
||||
// Initialize the Cocoa Application Kit
|
||||
//
|
||||
static GLFWbool initializeAppKit(void)
|
||||
@@ -916,15 +954,20 @@ static GLFWbool initializeAppKit(void)
|
||||
toTarget:NSApp
|
||||
withObject:nil];
|
||||
|
||||
// In case we are unbundled, make us a proper UI application
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
if (_glfw.hints.init.ns.menubar)
|
||||
{
|
||||
// In case we are unbundled, make us a proper UI application
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
#if defined(_GLFW_USE_MENUBAR)
|
||||
// Menu bar setup must go between sharedApplication above and
|
||||
// finishLaunching below, in order to properly emulate the behavior
|
||||
// of NSApplicationMain
|
||||
createMenuBar();
|
||||
#endif
|
||||
// Menu bar setup must go between sharedApplication above and
|
||||
// finishLaunching below, in order to properly emulate the behavior
|
||||
// of NSApplicationMain
|
||||
|
||||
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||
[NSApp loadMainMenu];
|
||||
else
|
||||
createMenuBar();
|
||||
}
|
||||
|
||||
// There can only be one application delegate, but we allocate it the
|
||||
// first time a window is created to keep all window code in this file
|
||||
@@ -944,8 +987,8 @@ static GLFWbool initializeAppKit(void)
|
||||
|
||||
// Create the Cocoa window
|
||||
//
|
||||
static GLFWbool createWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
|
||||
if (window->ns.delegate == nil)
|
||||
@@ -987,9 +1030,17 @@ static GLFWbool createWindow(_GLFWwindow* window,
|
||||
else
|
||||
{
|
||||
[window->ns.object center];
|
||||
_glfw.ns.cascadePoint =
|
||||
NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
|
||||
NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
|
||||
|
||||
if (wndconfig->resizable)
|
||||
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
{
|
||||
const NSWindowCollectionBehavior behavior =
|
||||
NSWindowCollectionBehaviorFullScreenPrimary |
|
||||
NSWindowCollectionBehaviorManaged;
|
||||
[window->ns.object setCollectionBehavior:behavior];
|
||||
}
|
||||
|
||||
if (wndconfig->floating)
|
||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||
@@ -998,17 +1049,19 @@ static GLFWbool createWindow(_GLFWwindow* window,
|
||||
[window->ns.object zoom:nil];
|
||||
}
|
||||
|
||||
if (wndconfig->ns.frame)
|
||||
[window->ns.object setFrameAutosaveName:[NSString stringWithUTF8String:wndconfig->title]];
|
||||
|
||||
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
|
||||
|
||||
#if defined(_GLFW_USE_RETINA)
|
||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||
#endif /*_GLFW_USE_RETINA*/
|
||||
if (wndconfig->ns.retina)
|
||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
[window->ns.object setContentView:window->ns.view];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
|
||||
[window->ns.object setDelegate:window->ns.delegate];
|
||||
[window->ns.object setAcceptsMouseMovedEvents:YES];
|
||||
[window->ns.object setContentView:window->ns.view];
|
||||
[window->ns.object setRestorable:NO];
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -1027,20 +1080,31 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!initializeAppKit())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!createWindow(window, wndconfig))
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitNSGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,7 +1115,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!acquireMonitor(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
centerCursor(window);
|
||||
if (wndconfig->centerCursor)
|
||||
centerCursor(window);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -1067,7 +1132,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
|
||||
[window->ns.object setDelegate:nil];
|
||||
@@ -1153,7 +1218,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
{
|
||||
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
|
||||
[window->ns.object setContentAspectRatio:NSMakeSize(0, 0)];
|
||||
[window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
|
||||
else
|
||||
[window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
|
||||
}
|
||||
@@ -1217,6 +1282,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
[window->ns.object orderOut:nil];
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
[NSApp requestUserAttention:NSInformationalRequest];
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
// Make us the active application
|
||||
@@ -1228,6 +1298,11 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
[window->ns.object makeKeyAndOrderFront:nil];
|
||||
}
|
||||
|
||||
void _glfwPlatformDragWindow(_GLFWwindow* window)
|
||||
{
|
||||
[window->ns.object performWindowDragWithEvent:[NSApp currentEvent]];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
@@ -1260,6 +1335,10 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
|
||||
_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);
|
||||
[window->ns.object setStyleMask:styleMask];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
@@ -1345,11 +1424,30 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
return [window->ns.object isZoomed];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
[window->ns.object setStyleMask:getStyleMask(window)];
|
||||
[window->ns.object makeFirstResponder:window->ns.view];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
[window->ns.object setLevel:NSFloatingWindowLevel];
|
||||
else
|
||||
[window->ns.object setLevel:NSNormalWindowLevel];
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:[NSDate distantPast]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@@ -1368,7 +1466,7 @@ void _glfwPlatformWaitEvents(void)
|
||||
// I wanted to pass NO to dequeue:, and rely on PollEvents to
|
||||
// dequeue and send. For reasons not at all clear to me, passing
|
||||
// NO to dequeue: causes this method never to return.
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:[NSDate distantFuture]
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@@ -1380,7 +1478,7 @@ void _glfwPlatformWaitEvents(void)
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
|
||||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:date
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
@@ -1393,7 +1491,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
|
||||
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||
location:NSMakePoint(0, 0)
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
@@ -1467,14 +1565,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
scancode = _glfw.ns.nativeKeys[key];
|
||||
|
||||
if (!_glfwIsPrintable(_glfw.ns.publicKeys[scancode]))
|
||||
return NULL;
|
||||
|
||||
UInt32 deadKeyState = 0;
|
||||
UniChar characters[8];
|
||||
UniCharCount characterCount = 0;
|
||||
@@ -1509,6 +1601,11 @@ const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
return _glfw.ns.keyName;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return _glfw.ns.scancodes[key];
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
@@ -1538,7 +1635,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
memcpy([rep bitmapData], image->pixels, image->width * image->height * 4);
|
||||
|
||||
native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];
|
||||
[native addRepresentation: rep];
|
||||
[native addRepresentation:rep];
|
||||
|
||||
cursor->ns.object = [[NSCursor alloc] initWithImage:native
|
||||
hotSpot:NSMakePoint(xhot, yhot)];
|
||||
@@ -1557,7 +1654,19 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
if (!initializeAppKit())
|
||||
return GLFW_FALSE;
|
||||
|
||||
cursor->ns.object = getStandardCursor(shape);
|
||||
if (shape == GLFW_ARROW_CURSOR)
|
||||
cursor->ns.object = [NSCursor arrowCursor];
|
||||
else if (shape == GLFW_IBEAM_CURSOR)
|
||||
cursor->ns.object = [NSCursor IBeamCursor];
|
||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
||||
cursor->ns.object = [NSCursor crosshairCursor];
|
||||
else if (shape == GLFW_HAND_CURSOR)
|
||||
cursor->ns.object = [NSCursor pointingHandCursor];
|
||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeLeftRightCursor];
|
||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
||||
cursor->ns.object = [NSCursor resizeUpDownCursor];
|
||||
|
||||
if (!cursor->ns.object)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -1616,17 +1725,20 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return _glfw.ns.clipboardString;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
*count = 0;
|
||||
return NULL;
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
|
||||
return;
|
||||
|
||||
extensions[0] = "VK_KHR_surface";
|
||||
extensions[1] = "VK_MVK_macos_surface";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
@@ -1634,7 +1746,57 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
|
||||
VkResult err;
|
||||
VkMacOSSurfaceCreateInfoMVK sci;
|
||||
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
|
||||
|
||||
vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
|
||||
if (!vkCreateMacOSSurfaceMVK)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
// HACK: Dynamically load Core Animation to avoid adding an extra
|
||||
// dependency for the majority who don't use MoltenVK
|
||||
NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
|
||||
if (!bundle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to find QuartzCore.framework");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
// NOTE: Create the layer here as makeBackingLayer should not return nil
|
||||
window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
|
||||
if (!window->ns.layer)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to create layer for view");
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
}
|
||||
|
||||
[window->ns.view setWantsLayer:YES];
|
||||
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
|
||||
sci.pView = window->ns.view;
|
||||
|
||||
err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to create Vulkan surface: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
return err;
|
||||
#else
|
||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
+92
-78
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -34,56 +34,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Parses the client API version string and extracts the version number
|
||||
//
|
||||
static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
|
||||
{
|
||||
int i;
|
||||
_GLFWwindow* window;
|
||||
const char* version;
|
||||
const char* prefixes[] =
|
||||
{
|
||||
"OpenGL ES-CM ",
|
||||
"OpenGL ES-CL ",
|
||||
"OpenGL ES ",
|
||||
NULL
|
||||
};
|
||||
|
||||
*api = GLFW_OPENGL_API;
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
|
||||
version = (const char*) window->context.GetString(GL_VERSION);
|
||||
if (!version)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Client API version string retrieval is broken");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; prefixes[i]; i++)
|
||||
{
|
||||
const size_t length = strlen(prefixes[i]);
|
||||
|
||||
if (strncmp(version, prefixes[i], length) == 0)
|
||||
{
|
||||
version += length;
|
||||
*api = GLFW_OPENGL_ES_API;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sscanf(version, "%d.%d.%d", major, minor, rev))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"No version found in client API version string");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -91,10 +41,11 @@ static GLFWbool parseVersionString(int* api, int* major, int* minor, int* rev)
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
|
||||
ctxconfig->source != GLFW_EGL_CONTEXT_API)
|
||||
ctxconfig->source != GLFW_EGL_CONTEXT_API &&
|
||||
ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context creation API %i",
|
||||
"Invalid context creation API 0x%08X",
|
||||
ctxconfig->source);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -104,7 +55,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->client != GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid client API %i",
|
||||
"Invalid client API 0x%08X",
|
||||
ctxconfig->client);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -134,7 +85,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid OpenGL profile %i",
|
||||
"Invalid OpenGL profile 0x%08X",
|
||||
ctxconfig->profile);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -183,7 +134,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context robustness mode %i",
|
||||
"Invalid context robustness mode 0x%08X",
|
||||
ctxconfig->robustness);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -195,7 +146,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context release behavior %i",
|
||||
"Invalid context release behavior 0x%08X",
|
||||
ctxconfig->release);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
@@ -369,27 +320,79 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||
|
||||
GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
int i;
|
||||
_GLFWwindow* window;
|
||||
const char* version;
|
||||
const char* prefixes[] =
|
||||
{
|
||||
"OpenGL ES-CM ",
|
||||
"OpenGL ES-CL ",
|
||||
"OpenGL ES ",
|
||||
NULL
|
||||
};
|
||||
|
||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
window->context.source = ctxconfig->source;
|
||||
window->context.client = GLFW_OPENGL_API;
|
||||
|
||||
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
||||
glfwGetProcAddress("glGetIntegerv");
|
||||
window->context.getProcAddress("glGetIntegerv");
|
||||
window->context.GetString = (PFNGLGETSTRINGPROC)
|
||||
glfwGetProcAddress("glGetString");
|
||||
window->context.getProcAddress("glGetString");
|
||||
if (!window->context.GetIntegerv || !window->context.GetString)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!parseVersionString(&window->context.client,
|
||||
&window->context.major,
|
||||
&window->context.minor,
|
||||
&window->context.revision))
|
||||
version = (const char*) window->context.GetString(GL_VERSION);
|
||||
if (!version)
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OpenGL version string retrieval is broken");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OpenGL ES version string retrieval is broken");
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.source = ctxconfig->source;
|
||||
for (i = 0; prefixes[i]; i++)
|
||||
{
|
||||
const size_t length = strlen(prefixes[i]);
|
||||
|
||||
if (strncmp(version, prefixes[i], length) == 0)
|
||||
{
|
||||
version += length;
|
||||
window->context.client = GLFW_OPENGL_ES_API;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sscanf(version, "%d.%d.%d",
|
||||
&window->context.major,
|
||||
&window->context.minor,
|
||||
&window->context.revision))
|
||||
{
|
||||
if (window->context.client == GLFW_OPENGL_API)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"No version found in OpenGL version string");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"No version found in OpenGL ES version string");
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (window->context.major < ctxconfig->major ||
|
||||
(window->context.major == ctxconfig->major &&
|
||||
@@ -402,10 +405,21 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
// For API consistency, we emulate the behavior of the
|
||||
// {GLX|WGL}_ARB_create_context extension and fail here
|
||||
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"Requested client API version %i.%i, got version %i.%i",
|
||||
ctxconfig->major, ctxconfig->minor,
|
||||
window->context.major, window->context.minor);
|
||||
if (window->context.client == GLFW_OPENGL_API)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"Requested OpenGL version %i.%i, got version %i.%i",
|
||||
ctxconfig->major, ctxconfig->minor,
|
||||
window->context.major, window->context.minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"Requested OpenGL ES version %i.%i, got version %i.%i",
|
||||
ctxconfig->major, ctxconfig->minor,
|
||||
window->context.major, window->context.minor);
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -416,7 +430,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
// users as early as possible that their build may be broken
|
||||
|
||||
window->context.GetStringi = (PFNGLGETSTRINGIPROC)
|
||||
glfwGetProcAddress("glGetStringi");
|
||||
window->context.getProcAddress("glGetStringi");
|
||||
if (!window->context.GetStringi)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -521,7 +535,8 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
|
||||
// Clearing the front buffer to black to avoid garbage pixels left over from
|
||||
// previous uses of our bit of VRAM
|
||||
{
|
||||
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
|
||||
PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
|
||||
window->context.getProcAddress("glClear");
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
window->context.swapBuffers(window);
|
||||
}
|
||||
@@ -563,7 +578,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
||||
GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFWwindow* previous = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -586,7 +601,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
|
||||
GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return (GLFWwindow*) _glfwPlatformGetCurrentContext();
|
||||
return _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
|
||||
@@ -611,7 +626,7 @@ GLFWAPI void glfwSwapInterval(int interval)
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
@@ -624,12 +639,11 @@ GLFWAPI void glfwSwapInterval(int interval)
|
||||
GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
||||
assert(extension != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
@@ -694,7 +708,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
window = _glfwPlatformGetCurrentContext();
|
||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
|
||||
|
||||
+149
-96
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 EGL - www.glfw.org
|
||||
// GLFW 3.3 EGL - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -28,13 +28,14 @@
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// Return a description of the specified EGL error
|
||||
//
|
||||
static const char* getErrorString(EGLint error)
|
||||
static const char* getEGLErrorString(EGLint error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
@@ -75,16 +76,16 @@ static const char* getErrorString(EGLint error)
|
||||
|
||||
// Returns the specified attribute of the specified EGLConfig
|
||||
//
|
||||
static int getConfigAttrib(EGLConfig config, int attrib)
|
||||
static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
||||
{
|
||||
int value;
|
||||
eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Return a list of available and usable framebuffer configs
|
||||
// Return the EGLConfig most closely matching the specified hints
|
||||
//
|
||||
static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
||||
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* desired,
|
||||
EGLConfig* result)
|
||||
{
|
||||
@@ -112,16 +113,16 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||
|
||||
// Only consider RGB(A) EGLConfigs
|
||||
if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))
|
||||
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
|
||||
continue;
|
||||
|
||||
// Only consider window EGLConfigs
|
||||
if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
|
||||
continue;
|
||||
|
||||
#if defined(_GLFW_X11)
|
||||
// Only consider EGLConfigs with associated Visuals
|
||||
if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
|
||||
continue;
|
||||
#endif // _GLFW_X11
|
||||
|
||||
@@ -129,30 +130,30 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
||||
{
|
||||
if (ctxconfig->major == 1)
|
||||
{
|
||||
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
||||
if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
|
||||
continue;
|
||||
}
|
||||
|
||||
u->redBits = getConfigAttrib(n, EGL_RED_SIZE);
|
||||
u->greenBits = getConfigAttrib(n, EGL_GREEN_SIZE);
|
||||
u->blueBits = getConfigAttrib(n, EGL_BLUE_SIZE);
|
||||
u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
|
||||
u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
|
||||
u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
|
||||
|
||||
u->alphaBits = getConfigAttrib(n, EGL_ALPHA_SIZE);
|
||||
u->depthBits = getConfigAttrib(n, EGL_DEPTH_SIZE);
|
||||
u->stencilBits = getConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||
u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
|
||||
u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
|
||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||
|
||||
u->samples = getConfigAttrib(n, EGL_SAMPLES);
|
||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
|
||||
u->handle = (uintptr_t) n;
|
||||
@@ -169,7 +170,7 @@ static GLFWbool chooseFBConfigs(const _GLFWctxconfig* ctxconfig,
|
||||
return closest != NULL;
|
||||
}
|
||||
|
||||
static void makeContextCurrent(_GLFWwindow* window)
|
||||
static void makeContextCurrentEGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
@@ -180,7 +181,7 @@ static void makeContextCurrent(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to make context current: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -193,17 +194,17 @@ static void makeContextCurrent(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to clear current context: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffers(_GLFWwindow* window)
|
||||
static void swapBuffersEGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window != _glfwPlatformGetCurrentContext())
|
||||
if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: The context must be current on the calling thread when swapping buffers");
|
||||
@@ -213,12 +214,12 @@ static void swapBuffers(_GLFWwindow* window)
|
||||
eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
|
||||
}
|
||||
|
||||
static void swapInterval(int interval)
|
||||
static void swapIntervalEGL(int interval)
|
||||
{
|
||||
eglSwapInterval(_glfw.egl.display, interval);
|
||||
}
|
||||
|
||||
static int extensionSupported(const char* extension)
|
||||
static int extensionSupportedEGL(const char* extension)
|
||||
{
|
||||
const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
|
||||
if (extensions)
|
||||
@@ -230,9 +231,9 @@ static int extensionSupported(const char* extension)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddress(const char* procname)
|
||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
if (window->context.egl.client)
|
||||
{
|
||||
@@ -245,7 +246,7 @@ static GLFWglproc getProcAddress(const char* procname)
|
||||
return eglGetProcAddress(procname);
|
||||
}
|
||||
|
||||
static void destroyContext(_GLFWwindow* window)
|
||||
static void destroyContextEGL(_GLFWwindow* window)
|
||||
{
|
||||
#if defined(_GLFW_X11)
|
||||
// NOTE: Do not unload libGL.so.1 while the X11 display is still open,
|
||||
@@ -290,12 +291,17 @@ GLFWbool _glfwInitEGL(void)
|
||||
"EGL.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libEGL.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libEGL-1.so",
|
||||
#else
|
||||
"libEGL.so.1",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
if (_glfw.egl.handle)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
_glfw.egl.handle = _glfw_dlopen(sonames[i]);
|
||||
@@ -304,47 +310,76 @@ GLFWbool _glfwInitEGL(void)
|
||||
}
|
||||
|
||||
if (!_glfw.egl.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
|
||||
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||
|
||||
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
||||
_glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)
|
||||
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
||||
_glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)
|
||||
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
||||
_glfw.egl.GetError = (PFNEGLGETERRORPROC)
|
||||
_glfw.egl.GetError = (PFN_eglGetError)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
||||
_glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)
|
||||
_glfw.egl.Initialize = (PFN_eglInitialize)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
||||
_glfw.egl.Terminate = (PFNEGLTERMINATEPROC)
|
||||
_glfw.egl.Terminate = (PFN_eglTerminate)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
||||
_glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)
|
||||
_glfw.egl.BindAPI = (PFN_eglBindAPI)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
||||
_glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)
|
||||
_glfw.egl.CreateContext = (PFN_eglCreateContext)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
||||
_glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)
|
||||
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
||||
_glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)
|
||||
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
||||
_glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)
|
||||
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
||||
_glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)
|
||||
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
||||
_glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)
|
||||
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
||||
_glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)
|
||||
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
||||
_glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)
|
||||
_glfw.egl.QueryString = (PFN_eglQueryString)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
||||
_glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)
|
||||
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
|
||||
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
||||
|
||||
if (!_glfw.egl.GetConfigAttrib ||
|
||||
!_glfw.egl.GetConfigs ||
|
||||
!_glfw.egl.GetDisplay ||
|
||||
!_glfw.egl.GetError ||
|
||||
!_glfw.egl.Initialize ||
|
||||
!_glfw.egl.Terminate ||
|
||||
!_glfw.egl.BindAPI ||
|
||||
!_glfw.egl.CreateContext ||
|
||||
!_glfw.egl.DestroySurface ||
|
||||
!_glfw.egl.DestroyContext ||
|
||||
!_glfw.egl.CreateWindowSurface ||
|
||||
!_glfw.egl.MakeCurrent ||
|
||||
!_glfw.egl.SwapBuffers ||
|
||||
!_glfw.egl.SwapInterval ||
|
||||
!_glfw.egl.QueryString ||
|
||||
!_glfw.egl.GetProcAddress)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to load required entry points");
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||
if (_glfw.egl.display == EGL_NO_DISPLAY)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to get EGL display: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
@@ -354,18 +389,22 @@ GLFWbool _glfwInitEGL(void)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to initialize EGL: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.egl.KHR_create_context =
|
||||
extensionSupported("EGL_KHR_create_context");
|
||||
extensionSupportedEGL("EGL_KHR_create_context");
|
||||
_glfw.egl.KHR_create_context_no_error =
|
||||
extensionSupported("EGL_KHR_create_context_no_error");
|
||||
extensionSupportedEGL("EGL_KHR_create_context_no_error");
|
||||
_glfw.egl.KHR_gl_colorspace =
|
||||
extensionSupported("EGL_KHR_gl_colorspace");
|
||||
extensionSupportedEGL("EGL_KHR_gl_colorspace");
|
||||
_glfw.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;
|
||||
}
|
||||
@@ -387,11 +426,11 @@ void _glfwTerminateEGL(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define setEGLattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -403,6 +442,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
EGLint attribs[40];
|
||||
EGLConfig config;
|
||||
EGLContext share = NULL;
|
||||
int index = 0;
|
||||
|
||||
if (!_glfw.egl.display)
|
||||
{
|
||||
@@ -413,7 +453,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.egl.handle;
|
||||
|
||||
if (!chooseFBConfigs(ctxconfig, fbconfig, &config))
|
||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
@@ -426,7 +466,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to bind OpenGL ES: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -436,14 +476,14 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to bind OpenGL: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.egl.KHR_create_context)
|
||||
{
|
||||
int index = 0, mask = 0, flags = 0;
|
||||
int mask = 0, flags = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
@@ -454,12 +494,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;
|
||||
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
{
|
||||
if (ctxconfig->noerror)
|
||||
flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->debug)
|
||||
@@ -469,44 +503,57 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_NO_RESET_NOTIFICATION_KHR);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
|
||||
EGL_LOSE_CONTEXT_ON_RESET_KHR);
|
||||
}
|
||||
|
||||
flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.egl.KHR_create_context_no_error)
|
||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
|
||||
setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
|
||||
|
||||
if (flags)
|
||||
setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
|
||||
}
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on EGL but are not a hard constraint, so ignore and continue
|
||||
if (_glfw.egl.KHR_context_flush_control)
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
|
||||
EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
|
||||
window->context.egl.handle = eglCreateContext(_glfw.egl.display,
|
||||
config, share, attribs);
|
||||
@@ -515,7 +562,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"EGL: Failed to create context: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -526,12 +573,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
if (_glfw.egl.KHR_gl_colorspace)
|
||||
{
|
||||
setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
|
||||
}
|
||||
|
||||
setEGLattrib(EGL_NONE, EGL_NONE);
|
||||
setAttrib(EGL_NONE, EGL_NONE);
|
||||
}
|
||||
|
||||
window->context.egl.surface =
|
||||
@@ -543,13 +588,14 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to create window surface: %s",
|
||||
getErrorString(eglGetError()));
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.egl.config = config;
|
||||
|
||||
// Load the appropriate client library
|
||||
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
||||
{
|
||||
int i;
|
||||
const char** sonames;
|
||||
@@ -573,6 +619,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
"libGLESv2.dll",
|
||||
#elif defined(_GLFW_COCOA)
|
||||
"libGLESv2.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libGLESv2-2.so",
|
||||
#else
|
||||
"libGLESv2.so.2",
|
||||
#endif
|
||||
@@ -600,6 +648,11 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
// HACK: Match presence of lib prefix to increase chance of finding
|
||||
// a matching pair in the jungle that is Win32 EGL/GLES
|
||||
if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))
|
||||
continue;
|
||||
|
||||
window->context.egl.client = _glfw_dlopen(sonames[i]);
|
||||
if (window->context.egl.client)
|
||||
break;
|
||||
@@ -613,17 +666,17 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrent;
|
||||
window->context.swapBuffers = swapBuffers;
|
||||
window->context.swapInterval = swapInterval;
|
||||
window->context.extensionSupported = extensionSupported;
|
||||
window->context.getProcAddress = getProcAddress;
|
||||
window->context.destroy = destroyContext;
|
||||
window->context.makeCurrent = makeContextCurrentEGL;
|
||||
window->context.swapBuffers = swapBuffersEGL;
|
||||
window->context.swapInterval = swapIntervalEGL;
|
||||
window->context.extensionSupported = extensionSupportedEGL;
|
||||
window->context.getProcAddress = getProcAddressEGL;
|
||||
window->context.destroy = destroyContextEGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setEGLattrib
|
||||
#undef setAttrib
|
||||
|
||||
// Returns the Visual and depth of the chosen EGLConfig
|
||||
//
|
||||
@@ -638,7 +691,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
||||
EGLint visualID = 0, count = 0;
|
||||
const long vimask = VisualScreenMask | VisualIDMask;
|
||||
|
||||
if (!chooseFBConfigs(ctxconfig, fbconfig, &native))
|
||||
if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
|
||||
+44
-39
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 EGL - www.glfw.org
|
||||
// GLFW 3.3 EGL - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,15 +25,16 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_egl_context_h_
|
||||
#define _glfw3_egl_context_h_
|
||||
|
||||
#if defined(_GLFW_USE_EGLPLATFORM_H)
|
||||
#include <EGL/eglplatform.h>
|
||||
#elif defined(_GLFW_WIN32)
|
||||
#define EGLAPIENTRY __stdcall
|
||||
typedef HDC EGLNativeDisplayType;
|
||||
typedef HWND EGLNativeWindowType;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
#define EGLAPIENTRY
|
||||
typedef void* EGLNativeDisplayType;
|
||||
typedef id EGLNativeWindowType;
|
||||
#elif defined(_GLFW_X11)
|
||||
#define EGLAPIENTRY
|
||||
typedef Display* EGLNativeDisplayType;
|
||||
@@ -106,6 +107,9 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3
|
||||
#define EGL_GL_COLORSPACE_KHR 0x309d
|
||||
#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 unsigned int EGLBoolean;
|
||||
@@ -116,22 +120,22 @@ typedef void* EGLDisplay;
|
||||
typedef void* EGLSurface;
|
||||
|
||||
// EGL function pointer typedefs
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
|
||||
typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
|
||||
typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
|
||||
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
|
||||
typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
|
||||
typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
|
||||
typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
|
||||
typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
|
||||
typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
|
||||
typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
|
||||
typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
|
||||
typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
|
||||
typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*);
|
||||
#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
|
||||
#define eglGetConfigs _glfw.egl.GetConfigs
|
||||
#define eglGetDisplay _glfw.egl.GetDisplay
|
||||
@@ -165,36 +169,38 @@ typedef struct _GLFWcontextEGL
|
||||
|
||||
} _GLFWcontextEGL;
|
||||
|
||||
|
||||
// EGL-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryEGL
|
||||
{
|
||||
EGLDisplay display;
|
||||
EGLint major, minor;
|
||||
GLFWbool prefix;
|
||||
|
||||
GLFWbool KHR_create_context;
|
||||
GLFWbool KHR_create_context_no_error;
|
||||
GLFWbool KHR_gl_colorspace;
|
||||
GLFWbool KHR_get_all_proc_addresses;
|
||||
GLFWbool KHR_context_flush_control;
|
||||
|
||||
void* handle;
|
||||
|
||||
PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
|
||||
PFNEGLGETCONFIGSPROC GetConfigs;
|
||||
PFNEGLGETDISPLAYPROC GetDisplay;
|
||||
PFNEGLGETERRORPROC GetError;
|
||||
PFNEGLINITIALIZEPROC Initialize;
|
||||
PFNEGLTERMINATEPROC Terminate;
|
||||
PFNEGLBINDAPIPROC BindAPI;
|
||||
PFNEGLCREATECONTEXTPROC CreateContext;
|
||||
PFNEGLDESTROYSURFACEPROC DestroySurface;
|
||||
PFNEGLDESTROYCONTEXTPROC DestroyContext;
|
||||
PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
|
||||
PFNEGLMAKECURRENTPROC MakeCurrent;
|
||||
PFNEGLSWAPBUFFERSPROC SwapBuffers;
|
||||
PFNEGLSWAPINTERVALPROC SwapInterval;
|
||||
PFNEGLQUERYSTRINGPROC QueryString;
|
||||
PFNEGLGETPROCADDRESSPROC GetProcAddress;
|
||||
PFN_eglGetConfigAttrib GetConfigAttrib;
|
||||
PFN_eglGetConfigs GetConfigs;
|
||||
PFN_eglGetDisplay GetDisplay;
|
||||
PFN_eglGetError GetError;
|
||||
PFN_eglInitialize Initialize;
|
||||
PFN_eglTerminate Terminate;
|
||||
PFN_eglBindAPI BindAPI;
|
||||
PFN_eglCreateContext CreateContext;
|
||||
PFN_eglDestroySurface DestroySurface;
|
||||
PFN_eglDestroyContext DestroyContext;
|
||||
PFN_eglCreateWindowSurface CreateWindowSurface;
|
||||
PFN_eglMakeCurrent MakeCurrent;
|
||||
PFN_eglSwapBuffers SwapBuffers;
|
||||
PFN_eglSwapInterval SwapInterval;
|
||||
PFN_eglQueryString QueryString;
|
||||
PFN_eglGetProcAddress GetProcAddress;
|
||||
|
||||
} _GLFWlibraryEGL;
|
||||
|
||||
@@ -210,4 +216,3 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
|
||||
Visual** visual, int* depth);
|
||||
#endif /*_GLFW_X11*/
|
||||
|
||||
#endif // _glfw3_egl_context_h_
|
||||
|
||||
+6
-12
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2010-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2010-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -44,20 +44,14 @@
|
||||
#cmakedefine _GLFW_WAYLAND
|
||||
// Define this to 1 if building GLFW for Mir
|
||||
#cmakedefine _GLFW_MIR
|
||||
// Define this to 1 if building GLFW for OSMesa
|
||||
#cmakedefine _GLFW_OSMESA
|
||||
|
||||
// Define this to 1 if building as a shared library / dynamic library / DLL
|
||||
#cmakedefine _GLFW_BUILD_DLL
|
||||
// Define this to 1 to use Vulkan loader linked statically into application
|
||||
#cmakedefine _GLFW_VULKAN_STATIC
|
||||
|
||||
// Define this to 1 to force use of high-performance GPU on hybrid systems
|
||||
#cmakedefine _GLFW_USE_HYBRID_HPG
|
||||
|
||||
// Define this to 1 if the Xxf86vm X11 extension is available
|
||||
#cmakedefine _GLFW_HAS_XF86VM
|
||||
|
||||
// Define this to 1 if glfwInit should change the current directory
|
||||
#cmakedefine _GLFW_USE_CHDIR
|
||||
// Define this to 1 if glfwCreateWindow should populate the menu bar
|
||||
#cmakedefine _GLFW_USE_MENUBAR
|
||||
// Define this to 1 if windows should use full resolution on Retina displays
|
||||
#cmakedefine _GLFW_USE_RETINA
|
||||
|
||||
|
||||
+114
-80
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 GLX - www.glfw.org
|
||||
// GLFW 3.3 GLX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -38,16 +38,16 @@
|
||||
|
||||
// Returns the specified attribute of the specified GLXFBConfig
|
||||
//
|
||||
static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
||||
static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
||||
{
|
||||
int value;
|
||||
glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Return a list of available and usable framebuffer configs
|
||||
// Return the GLXFBConfig most closely matching the specified hints
|
||||
//
|
||||
static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
|
||||
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)
|
||||
{
|
||||
GLXFBConfig* nativeConfigs;
|
||||
_GLFWfbconfig* usableConfigs;
|
||||
@@ -59,12 +59,12 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
|
||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||
if (strcmp(vendor, "Chromium") == 0)
|
||||
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||
trustWindowBit = GLFW_FALSE;
|
||||
|
||||
nativeConfigs =
|
||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||
if (!nativeCount)
|
||||
if (!nativeConfigs || !nativeCount)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||
return GLFW_FALSE;
|
||||
@@ -79,41 +79,41 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
|
||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
||||
|
||||
// Only consider RGBA GLXFBConfigs
|
||||
if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
||||
if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
|
||||
continue;
|
||||
|
||||
// Only consider window GLXFBConfigs
|
||||
if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
||||
if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
|
||||
{
|
||||
if (trustWindowBit)
|
||||
continue;
|
||||
}
|
||||
|
||||
u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);
|
||||
u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||
u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE);
|
||||
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
|
||||
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
|
||||
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
|
||||
|
||||
u->alphaBits = getFBConfigAttrib(n, GLX_ALPHA_SIZE);
|
||||
u->depthBits = getFBConfigAttrib(n, GLX_DEPTH_SIZE);
|
||||
u->stencilBits = getFBConfigAttrib(n, GLX_STENCIL_SIZE);
|
||||
u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
|
||||
u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
|
||||
u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
|
||||
|
||||
u->accumRedBits = getFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
|
||||
u->accumGreenBits = getFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
|
||||
u->accumBlueBits = getFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
|
||||
u->accumAlphaBits = getFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
|
||||
u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
|
||||
u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
|
||||
u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
|
||||
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
|
||||
|
||||
u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
||||
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
||||
|
||||
if (getFBConfigAttrib(n, GLX_STEREO))
|
||||
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
||||
u->stereo = GLFW_TRUE;
|
||||
if (getFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
||||
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
|
||||
if (_glfw.glx.ARB_multisample)
|
||||
u->samples = getFBConfigAttrib(n, GLX_SAMPLES);
|
||||
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
||||
|
||||
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
|
||||
u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||
u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
|
||||
|
||||
u->handle = (uintptr_t) n;
|
||||
usableCount++;
|
||||
@@ -131,9 +131,9 @@ static GLFWbool chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result
|
||||
|
||||
// Create the OpenGL context using legacy API
|
||||
//
|
||||
static GLXContext createLegacyContext(_GLFWwindow* window,
|
||||
GLXFBConfig fbconfig,
|
||||
GLXContext share)
|
||||
static GLXContext createLegacyContextGLX(_GLFWwindow* window,
|
||||
GLXFBConfig fbconfig,
|
||||
GLXContext share)
|
||||
{
|
||||
return glXCreateNewContext(_glfw.x11.display,
|
||||
fbconfig,
|
||||
@@ -142,7 +142,7 @@ static GLXContext createLegacyContext(_GLFWwindow* window,
|
||||
True);
|
||||
}
|
||||
|
||||
static void makeContextCurrent(_GLFWwindow* window)
|
||||
static void makeContextCurrentGLX(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
@@ -165,17 +165,17 @@ static void makeContextCurrent(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffers(_GLFWwindow* window)
|
||||
static void swapBuffersGLX(_GLFWwindow* window)
|
||||
{
|
||||
glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
|
||||
}
|
||||
|
||||
static void swapInterval(int interval)
|
||||
static void swapIntervalGLX(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
if (_glfw.glx.EXT_swap_control)
|
||||
{
|
||||
@@ -192,7 +192,7 @@ static void swapInterval(int interval)
|
||||
}
|
||||
}
|
||||
|
||||
static int extensionSupported(const char* extension)
|
||||
static int extensionSupportedGLX(const char* extension)
|
||||
{
|
||||
const char* extensions =
|
||||
glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
|
||||
@@ -205,7 +205,7 @@ static int extensionSupported(const char* extension)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddress(const char* procname)
|
||||
static GLFWglproc getProcAddressGLX(const char* procname)
|
||||
{
|
||||
if (_glfw.glx.GetProcAddress)
|
||||
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
|
||||
@@ -217,7 +217,7 @@ static GLFWglproc getProcAddress(const char* procname)
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContext(_GLFWwindow* window)
|
||||
static void destroyContextGLX(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.glx.window)
|
||||
{
|
||||
@@ -253,6 +253,9 @@ GLFWbool _glfwInitGLX(void)
|
||||
NULL
|
||||
};
|
||||
|
||||
if (_glfw.glx.handle)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
_glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
|
||||
@@ -297,6 +300,27 @@ GLFWbool _glfwInitGLX(void)
|
||||
_glfw.glx.GetVisualFromFBConfig =
|
||||
dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||
|
||||
if (!_glfw.glx.GetFBConfigs ||
|
||||
!_glfw.glx.GetFBConfigAttrib ||
|
||||
!_glfw.glx.GetClientString ||
|
||||
!_glfw.glx.QueryExtension ||
|
||||
!_glfw.glx.QueryVersion ||
|
||||
!_glfw.glx.DestroyContext ||
|
||||
!_glfw.glx.MakeCurrent ||
|
||||
!_glfw.glx.SwapBuffers ||
|
||||
!_glfw.glx.QueryExtensionsString ||
|
||||
!_glfw.glx.CreateNewContext ||
|
||||
!_glfw.glx.CreateWindow ||
|
||||
!_glfw.glx.DestroyWindow ||
|
||||
!_glfw.glx.GetProcAddress ||
|
||||
!_glfw.glx.GetProcAddressARB ||
|
||||
!_glfw.glx.GetVisualFromFBConfig)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"GLX: Failed to load required entry points");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!glXQueryExtension(_glfw.x11.display,
|
||||
&_glfw.glx.errorBase,
|
||||
&_glfw.glx.eventBase))
|
||||
@@ -319,61 +343,64 @@ GLFWbool _glfwInitGLX(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (extensionSupported("GLX_EXT_swap_control"))
|
||||
if (extensionSupportedGLX("GLX_EXT_swap_control"))
|
||||
{
|
||||
_glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
|
||||
getProcAddress("glXSwapIntervalEXT");
|
||||
getProcAddressGLX("glXSwapIntervalEXT");
|
||||
|
||||
if (_glfw.glx.SwapIntervalEXT)
|
||||
_glfw.glx.EXT_swap_control = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (extensionSupported("GLX_SGI_swap_control"))
|
||||
if (extensionSupportedGLX("GLX_SGI_swap_control"))
|
||||
{
|
||||
_glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
|
||||
getProcAddress("glXSwapIntervalSGI");
|
||||
getProcAddressGLX("glXSwapIntervalSGI");
|
||||
|
||||
if (_glfw.glx.SwapIntervalSGI)
|
||||
_glfw.glx.SGI_swap_control = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (extensionSupported("GLX_MESA_swap_control"))
|
||||
if (extensionSupportedGLX("GLX_MESA_swap_control"))
|
||||
{
|
||||
_glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
|
||||
getProcAddress("glXSwapIntervalMESA");
|
||||
getProcAddressGLX("glXSwapIntervalMESA");
|
||||
|
||||
if (_glfw.glx.SwapIntervalMESA)
|
||||
_glfw.glx.MESA_swap_control = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (extensionSupported("GLX_ARB_multisample"))
|
||||
if (extensionSupportedGLX("GLX_ARB_multisample"))
|
||||
_glfw.glx.ARB_multisample = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_ARB_framebuffer_sRGB"))
|
||||
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
|
||||
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_EXT_framebuffer_sRGB"))
|
||||
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
|
||||
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_ARB_create_context"))
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context"))
|
||||
{
|
||||
_glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
|
||||
getProcAddress("glXCreateContextAttribsARB");
|
||||
getProcAddressGLX("glXCreateContextAttribsARB");
|
||||
|
||||
if (_glfw.glx.CreateContextAttribsARB)
|
||||
_glfw.glx.ARB_create_context = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (extensionSupported("GLX_ARB_create_context_robustness"))
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
|
||||
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_ARB_create_context_profile"))
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
|
||||
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_EXT_create_context_es2_profile"))
|
||||
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
||||
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
|
||||
|
||||
if (extensionSupported("GLX_ARB_context_flush_control"))
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
|
||||
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
|
||||
|
||||
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
||||
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -393,11 +420,11 @@ void _glfwTerminateGLX(void)
|
||||
}
|
||||
}
|
||||
|
||||
#define setGLXattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -413,7 +440,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.glx.handle;
|
||||
|
||||
if (!chooseFBConfig(fbconfig, &native))
|
||||
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"GLX: Failed to find a suitable GLXFBConfig");
|
||||
@@ -474,8 +501,6 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
|
||||
if (ctxconfig->noerror)
|
||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
@@ -483,13 +508,13 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
GLX_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
@@ -502,33 +527,39 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.glx.ARB_create_context_no_error)
|
||||
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
// explicitly requesting version 1.0 does not always return the
|
||||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
if (flags)
|
||||
setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
setGLXattrib(None, None);
|
||||
setAttrib(None, None);
|
||||
|
||||
window->context.glx.handle =
|
||||
_glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
|
||||
@@ -549,12 +580,15 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
ctxconfig->forward == GLFW_FALSE)
|
||||
{
|
||||
window->context.glx.handle =
|
||||
createLegacyContext(window, native, share);
|
||||
createLegacyContextGLX(window, native, share);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
window->context.glx.handle = createLegacyContext(window, native, share);
|
||||
{
|
||||
window->context.glx.handle =
|
||||
createLegacyContextGLX(window, native, share);
|
||||
}
|
||||
|
||||
_glfwReleaseErrorHandlerX11();
|
||||
|
||||
@@ -572,17 +606,17 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrent;
|
||||
window->context.swapBuffers = swapBuffers;
|
||||
window->context.swapInterval = swapInterval;
|
||||
window->context.extensionSupported = extensionSupported;
|
||||
window->context.getProcAddress = getProcAddress;
|
||||
window->context.destroy = destroyContext;
|
||||
window->context.makeCurrent = makeContextCurrentGLX;
|
||||
window->context.swapBuffers = swapBuffersGLX;
|
||||
window->context.swapInterval = swapIntervalGLX;
|
||||
window->context.extensionSupported = extensionSupportedGLX;
|
||||
window->context.getProcAddress = getProcAddressGLX;
|
||||
window->context.destroy = destroyContextGLX;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setGLXattrib
|
||||
#undef setAttrib
|
||||
|
||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||
//
|
||||
@@ -593,7 +627,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
||||
GLXFBConfig native;
|
||||
XVisualInfo* result;
|
||||
|
||||
if (!chooseFBConfig(fbconfig, &native))
|
||||
if (!chooseGLXFBConfig(fbconfig, &native))
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"GLX: Failed to find a suitable GLXFBConfig");
|
||||
|
||||
+9
-11
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 GLX - www.glfw.org
|
||||
// GLFW 3.3 GLX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,9 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_glx_context_h_
|
||||
#define _glfw3_glx_context_h_
|
||||
|
||||
#define GLX_VENDOR 1
|
||||
#define GLX_RGBA_BIT 0x00000001
|
||||
#define GLX_WINDOW_BIT 0x00000001
|
||||
@@ -67,6 +64,7 @@
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||
#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||
|
||||
typedef XID GLXWindow;
|
||||
typedef XID GLXDrawable;
|
||||
@@ -84,15 +82,16 @@ typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);
|
||||
typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);
|
||||
typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*);
|
||||
typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool);
|
||||
typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC) (const GLubyte *procName);
|
||||
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
|
||||
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
|
||||
typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName);
|
||||
typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
|
||||
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
|
||||
typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
|
||||
typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
|
||||
typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
|
||||
|
||||
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
|
||||
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
|
||||
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
|
||||
|
||||
// libGL.so function pointer typedefs
|
||||
#define glXGetFBConfigs _glfw.glx.GetFBConfigs
|
||||
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
|
||||
@@ -121,7 +120,6 @@ typedef struct _GLFWcontextGLX
|
||||
|
||||
} _GLFWcontextGLX;
|
||||
|
||||
|
||||
// GLX-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryGLX
|
||||
@@ -165,6 +163,7 @@ typedef struct _GLFWlibraryGLX
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryGLX;
|
||||
@@ -180,4 +179,3 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
|
||||
#endif // _glfw3_glx_context_h_
|
||||
|
||||
+206
-89
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -26,33 +26,45 @@
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
#include "mappings.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// The three global variables below comprise all global data in GLFW.
|
||||
// The global variables below comprise all global data in GLFW.
|
||||
// Any other global variable is a bug.
|
||||
|
||||
// Global state shared between compilation units of GLFW
|
||||
// These are documented in internal.h
|
||||
//
|
||||
GLFWbool _glfwInitialized = GLFW_FALSE;
|
||||
_GLFWlibrary _glfw;
|
||||
_GLFWlibrary _glfw = { GLFW_FALSE };
|
||||
|
||||
// This is outside of _glfw so it can be initialized and usable before
|
||||
// glfwInit is called, which lets that function report errors
|
||||
// These are outside of _glfw so they can be used before initialization and
|
||||
// after termination
|
||||
//
|
||||
static GLFWerrorfun _glfwErrorCallback = NULL;
|
||||
|
||||
static _GLFWerror _glfwMainThreadError;
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
{
|
||||
GLFW_TRUE, // macOS menu bar
|
||||
GLFW_TRUE // macOS bundle chdir
|
||||
},
|
||||
{
|
||||
"", // X11 WM_CLASS name
|
||||
"" // X11 WM_CLASS class
|
||||
}
|
||||
};
|
||||
|
||||
// Returns a generic string representation of the specified error
|
||||
//
|
||||
static const char* getErrorString(int error)
|
||||
static const char* getErrorString(int code)
|
||||
{
|
||||
switch (error)
|
||||
switch (code)
|
||||
{
|
||||
case GLFW_NOT_INITIALIZED:
|
||||
return "The GLFW library is not initialized";
|
||||
@@ -65,11 +77,11 @@ static const char* getErrorString(int error)
|
||||
case GLFW_OUT_OF_MEMORY:
|
||||
return "Out of memory";
|
||||
case GLFW_API_UNAVAILABLE:
|
||||
return "The requested client API is unavailable";
|
||||
return "The requested API is unavailable";
|
||||
case GLFW_VERSION_UNAVAILABLE:
|
||||
return "The requested client API version is unavailable";
|
||||
return "The requested API version is unavailable";
|
||||
case GLFW_PLATFORM_ERROR:
|
||||
return "A platform-specific error occurred";
|
||||
return "An undocumented platform-specific error occurred";
|
||||
case GLFW_FORMAT_UNAVAILABLE:
|
||||
return "The requested format is unavailable";
|
||||
case GLFW_NO_WINDOW_CONTEXT:
|
||||
@@ -79,77 +91,12 @@ static const char* getErrorString(int error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputError(int error, const char* format, ...)
|
||||
{
|
||||
if (_glfwErrorCallback)
|
||||
{
|
||||
char buffer[8192];
|
||||
const char* description;
|
||||
|
||||
if (format)
|
||||
{
|
||||
int count;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, format);
|
||||
count = vsnprintf(buffer, sizeof(buffer), format, vl);
|
||||
va_end(vl);
|
||||
|
||||
if (count < 0)
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
|
||||
description = buffer;
|
||||
}
|
||||
else
|
||||
description = getErrorString(error);
|
||||
|
||||
_glfwErrorCallback(error, description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwInit(void)
|
||||
{
|
||||
if (_glfwInitialized)
|
||||
return GLFW_TRUE;
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
_glfwPlatformTerminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwInitVulkan();
|
||||
|
||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||
_glfwInitialized = GLFW_TRUE;
|
||||
|
||||
_glfw.timerOffset = _glfwPlatformGetTimerValue();
|
||||
|
||||
// Not all window hints have zero as their default value
|
||||
glfwDefaultWindowHints();
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwTerminate(void)
|
||||
// Terminate the library
|
||||
//
|
||||
static void terminate(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!_glfwInitialized)
|
||||
return;
|
||||
|
||||
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
|
||||
|
||||
while (_glfw.windowListHead)
|
||||
@@ -163,28 +110,174 @@ GLFWAPI void glfwTerminate(void)
|
||||
_GLFWmonitor* monitor = _glfw.monitors[i];
|
||||
if (monitor->originalRamp.size)
|
||||
_glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
|
||||
_glfwFreeMonitor(monitor);
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
|
||||
_glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
|
||||
free(_glfw.monitors);
|
||||
_glfw.monitors = NULL;
|
||||
_glfw.monitorCount = 0;
|
||||
|
||||
free(_glfw.mappings);
|
||||
_glfw.mappings = NULL;
|
||||
_glfw.mappingCount = 0;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
_glfw.initialized = GLFW_FALSE;
|
||||
|
||||
while (_glfw.errorListHead)
|
||||
{
|
||||
_GLFWerror* error = _glfw.errorListHead;
|
||||
_glfw.errorListHead = error->next;
|
||||
free(error);
|
||||
}
|
||||
|
||||
_glfwPlatformDestroyTls(&_glfw.contextSlot);
|
||||
_glfwPlatformDestroyTls(&_glfw.errorSlot);
|
||||
_glfwPlatformDestroyMutex(&_glfw.errorLock);
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfwInitialized = GLFW_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputError(int code, const char* format, ...)
|
||||
{
|
||||
_GLFWerror* error;
|
||||
char description[1024];
|
||||
|
||||
if (format)
|
||||
{
|
||||
int count;
|
||||
va_list vl;
|
||||
|
||||
va_start(vl, format);
|
||||
count = vsnprintf(description, sizeof(description), format, vl);
|
||||
va_end(vl);
|
||||
|
||||
if (count < 0)
|
||||
description[sizeof(description) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
strcpy(description, getErrorString(code));
|
||||
|
||||
if (_glfw.initialized)
|
||||
{
|
||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||
if (!error)
|
||||
{
|
||||
error = calloc(1, sizeof(_GLFWerror));
|
||||
_glfwPlatformSetTls(&_glfw.errorSlot, error);
|
||||
_glfwPlatformLockMutex(&_glfw.errorLock);
|
||||
error->next = _glfw.errorListHead;
|
||||
_glfw.errorListHead = error;
|
||||
_glfwPlatformUnlockMutex(&_glfw.errorLock);
|
||||
}
|
||||
}
|
||||
else
|
||||
error = &_glfwMainThreadError;
|
||||
|
||||
error->code = code;
|
||||
strcpy(error->description, description);
|
||||
|
||||
if (_glfwErrorCallback)
|
||||
_glfwErrorCallback(code, description);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW public API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwInit(void)
|
||||
{
|
||||
if (_glfw.initialized)
|
||||
return GLFW_TRUE;
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfw.hints.init = _glfwInitHints;
|
||||
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfwPlatformCreateMutex(&_glfw.errorLock))
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwPlatformCreateTls(&_glfw.errorSlot))
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||
|
||||
_glfw.initialized = GLFW_TRUE;
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||
|
||||
glfwDefaultWindowHints();
|
||||
glfwUpdateGamepadMappings(_glfwDefaultMappings);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwTerminate(void)
|
||||
{
|
||||
if (!_glfw.initialized)
|
||||
return;
|
||||
|
||||
terminate();
|
||||
}
|
||||
|
||||
GLFWAPI void glfwInitHint(int hint, int value)
|
||||
{
|
||||
switch (hint)
|
||||
{
|
||||
case GLFW_JOYSTICK_HAT_BUTTONS:
|
||||
_glfwInitHints.hatButtons = value;
|
||||
return;
|
||||
case GLFW_COCOA_CHDIR_RESOURCES:
|
||||
_glfwInitHints.ns.chdir = value;
|
||||
return;
|
||||
case GLFW_COCOA_MENUBAR:
|
||||
_glfwInitHints.ns.menubar = value;
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid integer type init hint 0x%08X", hint);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwInitHintString(int hint, const char* value)
|
||||
{
|
||||
assert(value != NULL);
|
||||
|
||||
switch (hint)
|
||||
{
|
||||
case GLFW_X11_WM_CLASS_NAME:
|
||||
strncpy(_glfwInitHints.x11.className, value,
|
||||
sizeof(_glfwInitHints.x11.className) - 1);
|
||||
break;
|
||||
case GLFW_X11_WM_CLASS_CLASS:
|
||||
strncpy(_glfwInitHints.x11.classClass, value,
|
||||
sizeof(_glfwInitHints.x11.classClass) - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid string type init hint 0x%08X", hint);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
|
||||
{
|
||||
if (major != NULL)
|
||||
*major = GLFW_VERSION_MAJOR;
|
||||
|
||||
if (minor != NULL)
|
||||
*minor = GLFW_VERSION_MINOR;
|
||||
|
||||
if (rev != NULL)
|
||||
*rev = GLFW_VERSION_REVISION;
|
||||
}
|
||||
@@ -194,6 +287,30 @@ GLFWAPI const char* glfwGetVersionString(void)
|
||||
return _glfwPlatformGetVersionString();
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetError(const char** description)
|
||||
{
|
||||
_GLFWerror* error;
|
||||
int code = GLFW_NO_ERROR;
|
||||
|
||||
if (description)
|
||||
*description = NULL;
|
||||
|
||||
if (_glfw.initialized)
|
||||
error = _glfwPlatformGetTls(&_glfw.errorSlot);
|
||||
else
|
||||
error = &_glfwMainThreadError;
|
||||
|
||||
if (error)
|
||||
{
|
||||
code = error->code;
|
||||
error->code = GLFW_NO_ERROR;
|
||||
if (description && code)
|
||||
*description = error->description;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||
{
|
||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||
|
||||
+536
-37
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -29,11 +29,144 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// Internal key state used for sticky keys
|
||||
#define _GLFW_STICK 3
|
||||
|
||||
// Internal constants for gamepad mapping source types
|
||||
#define _GLFW_JOYSTICK_AXIS 1
|
||||
#define _GLFW_JOYSTICK_BUTTON 2
|
||||
#define _GLFW_JOYSTICK_HATBIT 3
|
||||
|
||||
// Finds a mapping based on joystick GUID
|
||||
//
|
||||
static _GLFWmapping* findMapping(const char* guid)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _glfw.mappingCount; i++)
|
||||
{
|
||||
if (strcmp(_glfw.mappings[i].guid, guid) == 0)
|
||||
return _glfw.mappings + i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parses an SDL_GameControllerDB line and adds it to the mapping list
|
||||
//
|
||||
static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||
{
|
||||
const char* c = string;
|
||||
size_t i, length;
|
||||
struct
|
||||
{
|
||||
const char* name;
|
||||
_GLFWmapelement* element;
|
||||
} fields[] =
|
||||
{
|
||||
{ "platform", NULL },
|
||||
{ "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
|
||||
{ "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
|
||||
{ "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
|
||||
{ "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
|
||||
{ "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
|
||||
{ "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
|
||||
{ "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
|
||||
{ "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
|
||||
{ "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
|
||||
{ "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
|
||||
{ "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
|
||||
{ "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
|
||||
{ "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
|
||||
{ "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
|
||||
{ "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
|
||||
{ "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
|
||||
{ "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
|
||||
{ "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
|
||||
{ "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
|
||||
{ "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
|
||||
{ "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
|
||||
};
|
||||
|
||||
length = strcspn(c, ",");
|
||||
if (length != 32 || c[length] != ',')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
memcpy(mapping->guid, c, length);
|
||||
c += length + 1;
|
||||
|
||||
length = strcspn(c, ",");
|
||||
if (length >= sizeof(mapping->name) || c[length] != ',')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
memcpy(mapping->name, c, length);
|
||||
c += length + 1;
|
||||
|
||||
while (*c)
|
||||
{
|
||||
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
|
||||
{
|
||||
length = strlen(fields[i].name);
|
||||
if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
|
||||
continue;
|
||||
|
||||
c += length + 1;
|
||||
|
||||
if (fields[i].element)
|
||||
{
|
||||
if (*c == 'a')
|
||||
fields[i].element->type = _GLFW_JOYSTICK_AXIS;
|
||||
else if (*c == 'b')
|
||||
fields[i].element->type = _GLFW_JOYSTICK_BUTTON;
|
||||
else if (*c == 'h')
|
||||
fields[i].element->type = _GLFW_JOYSTICK_HATBIT;
|
||||
else
|
||||
break;
|
||||
|
||||
if (fields[i].element->type == _GLFW_JOYSTICK_HATBIT)
|
||||
{
|
||||
const unsigned int hat = strtoul(c + 1, (char**) &c, 10);
|
||||
const unsigned int bit = strtoul(c + 1, (char**) &c, 10);
|
||||
fields[i].element->value = (hat << 4) | bit;
|
||||
}
|
||||
else
|
||||
fields[i].element->value = (uint8_t) strtoul(c + 1, (char**) &c, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
|
||||
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
c += strcspn(c, ",");
|
||||
c += strspn(c, ",");
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
|
||||
mapping->guid[i] += 'a' - 'A';
|
||||
}
|
||||
|
||||
_glfwPlatformUpdateGamepadGUID(mapping->guid);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW event API //////
|
||||
@@ -90,7 +223,6 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
||||
if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
|
||||
return;
|
||||
|
||||
// Register mouse button action
|
||||
if (action == GLFW_RELEASE && window->stickyMouseButtons)
|
||||
window->mouseButtons[button] = _GLFW_STICK;
|
||||
else
|
||||
@@ -124,10 +256,34 @@ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
||||
}
|
||||
|
||||
void _glfwInputJoystickChange(int joy, int event)
|
||||
void _glfwInputJoystick(_GLFWjoystick* js, int event)
|
||||
{
|
||||
const int jid = (int) (js - _glfw.joysticks);
|
||||
|
||||
if (_glfw.callbacks.joystick)
|
||||
_glfw.callbacks.joystick(joy, event);
|
||||
_glfw.callbacks.joystick(jid, event);
|
||||
}
|
||||
|
||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
|
||||
{
|
||||
js->axes[axis] = value;
|
||||
}
|
||||
|
||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
|
||||
{
|
||||
js->buttons[button] = value;
|
||||
}
|
||||
|
||||
void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,11 +291,47 @@ void _glfwInputJoystickChange(int joy, int event)
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwIsPrintable(int key)
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
const char* guid,
|
||||
int axisCount,
|
||||
int buttonCount,
|
||||
int hatCount)
|
||||
{
|
||||
return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
|
||||
(key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
|
||||
key == GLFW_KEY_KP_EQUAL;
|
||||
int jid;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (jid > GLFW_JOYSTICK_LAST)
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||
js->hats = calloc(hatCount, 1);
|
||||
js->axisCount = axisCount;
|
||||
js->buttonCount = buttonCount;
|
||||
js->hatCount = hatCount;
|
||||
js->mapping = findMapping(guid);
|
||||
|
||||
strcpy(js->guid, guid);
|
||||
|
||||
return js;
|
||||
}
|
||||
|
||||
void _glfwFreeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
free(js->name);
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->hats);
|
||||
memset(js, 0, sizeof(_GLFWjoystick));
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +355,7 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
|
||||
case GLFW_STICKY_MOUSE_BUTTONS:
|
||||
return window->stickyMouseButtons;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -184,7 +376,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
value != GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid cursor mode %i",
|
||||
"Invalid cursor mode 0x%08X",
|
||||
value);
|
||||
return;
|
||||
}
|
||||
@@ -247,13 +439,39 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
}
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return _glfwPlatformGetKeyName(key, scancode);
|
||||
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
{
|
||||
if (key != GLFW_KEY_KP_EQUAL &&
|
||||
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
|
||||
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scancode = _glfwPlatformGetKeyScancode(key);
|
||||
}
|
||||
|
||||
return _glfwPlatformGetScancodeName(scancode);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetKeyScancode(int key)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
|
||||
|
||||
if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
|
||||
return GLFW_RELEASE;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetKeyScancode(key);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
||||
@@ -332,11 +550,11 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (xpos != xpos || xpos < DBL_MIN || xpos > DBL_MAX ||
|
||||
ypos != ypos || ypos < DBL_MIN || ypos > DBL_MAX)
|
||||
if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
|
||||
ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"Invalid cursor position %fx%f",
|
||||
"Invalid cursor position %f %f",
|
||||
xpos, ypos);
|
||||
return;
|
||||
}
|
||||
@@ -391,7 +609,7 @@ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
||||
shape != GLFW_HRESIZE_CURSOR &&
|
||||
shape != GLFW_VRESIZE_CURSOR)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -540,62 +758,167 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwJoystickPresent(int joy)
|
||||
GLFWAPI int glfwJoystickPresent(int jid)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
_GLFWjoystick* js;
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
return 0;
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return _glfwPlatformJoystickPresent(joy);
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
|
||||
GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickAxes(joy, count);
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
|
||||
return NULL;
|
||||
|
||||
*count = js->axisCount;
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
|
||||
GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickButtons(joy, count);
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
if (_glfw.hints.init.hatButtons)
|
||||
*count = js->buttonCount + js->hatCount * 4;
|
||||
else
|
||||
*count = js->buttonCount;
|
||||
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickName(int joy)
|
||||
GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetJoystickName(joy);
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
|
||||
return NULL;
|
||||
|
||||
*count = js->hatCount;
|
||||
return js->hats;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickName(int jid)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetJoystickGUID(int jid)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
return NULL;
|
||||
|
||||
return js->guid;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
@@ -605,6 +928,182 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||
{
|
||||
int jid;
|
||||
const char* c = string;
|
||||
|
||||
assert(string != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
while (*c)
|
||||
{
|
||||
if (isxdigit(*c))
|
||||
{
|
||||
char line[1024];
|
||||
|
||||
const size_t length = strcspn(c, "\r\n");
|
||||
if (length < sizeof(line))
|
||||
{
|
||||
_GLFWmapping mapping = {{0}};
|
||||
|
||||
memcpy(line, c, length);
|
||||
line[length] = '\0';
|
||||
|
||||
if (parseMapping(&mapping, line))
|
||||
{
|
||||
_GLFWmapping* previous = findMapping(mapping.guid);
|
||||
if (previous)
|
||||
*previous = mapping;
|
||||
else
|
||||
{
|
||||
_glfw.mappingCount++;
|
||||
_glfw.mappings =
|
||||
realloc(_glfw.mappings,
|
||||
sizeof(_GLFWmapping) * _glfw.mappingCount);
|
||||
_glfw.mappings[_glfw.mappingCount - 1] = mapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
c += strcspn(c, "\r\n");
|
||||
c += strspn(c, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
js->mapping = findMapping(js->guid);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwJoystickIsGamepad(int jid)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
return GLFW_FALSE;
|
||||
|
||||
return js->mapping != NULL;
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetGamepadName(int jid)
|
||||
{
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return NULL;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
return NULL;
|
||||
|
||||
if (!js->mapping)
|
||||
return NULL;
|
||||
|
||||
return js->mapping->name;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
||||
{
|
||||
int i;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||
assert(state != NULL);
|
||||
|
||||
memset(state, 0, sizeof(GLFWgamepadstate));
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!js->mapping)
|
||||
return GLFW_FALSE;
|
||||
|
||||
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
||||
{
|
||||
if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_AXIS)
|
||||
{
|
||||
if (fabs(js->axes[js->mapping->buttons[i].value]) > 0.5)
|
||||
state->buttons[i] = GLFW_PRESS;
|
||||
}
|
||||
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
|
||||
{
|
||||
const unsigned int hat = js->mapping->buttons[i].value >> 4;
|
||||
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
|
||||
if (js->hats[hat] & bit)
|
||||
state->buttons[i] = GLFW_PRESS;
|
||||
}
|
||||
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
|
||||
state->buttons[i] = js->buttons[js->mapping->buttons[i].value];
|
||||
}
|
||||
|
||||
for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
|
||||
{
|
||||
if (js->mapping->axes[i].type == _GLFW_JOYSTICK_AXIS)
|
||||
state->axes[i] = js->axes[js->mapping->axes[i].value];
|
||||
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_HATBIT)
|
||||
{
|
||||
const unsigned int hat = js->mapping->buttons[i].value >> 4;
|
||||
const unsigned int bit = js->mapping->buttons[i].value & 0xf;
|
||||
if (js->hats[hat] & bit)
|
||||
state->axes[i] = 1.f;
|
||||
}
|
||||
else if (js->mapping->buttons[i].type == _GLFW_JOYSTICK_BUTTON)
|
||||
state->axes[i] = (float) js->buttons[js->mapping->axes[i].value];
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -627,7 +1126,7 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
||||
GLFWAPI double glfwGetTime(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
|
||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
|
||||
_glfwPlatformGetTimerFrequency();
|
||||
}
|
||||
|
||||
@@ -641,7 +1140,7 @@ GLFWAPI void glfwSetTime(double time)
|
||||
return;
|
||||
}
|
||||
|
||||
_glfw.timerOffset = _glfwPlatformGetTimerValue() -
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
|
||||
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
||||
}
|
||||
|
||||
|
||||
+262
-306
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,10 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_internal_h_
|
||||
#define _glfw3_internal_h_
|
||||
|
||||
|
||||
#if defined(_GLFW_USE_CONFIG_H)
|
||||
#include "glfw_config.h"
|
||||
#endif
|
||||
@@ -37,9 +33,12 @@
|
||||
defined(GLFW_INCLUDE_ES1) || \
|
||||
defined(GLFW_INCLUDE_ES2) || \
|
||||
defined(GLFW_INCLUDE_ES3) || \
|
||||
defined(GLFW_INCLUDE_ES31) || \
|
||||
defined(GLFW_INCLUDE_ES32) || \
|
||||
defined(GLFW_INCLUDE_NONE) || \
|
||||
defined(GLFW_INCLUDE_GLEXT) || \
|
||||
defined(GLFW_INCLUDE_GLU) || \
|
||||
defined(GLFW_INCLUDE_VULKAN) || \
|
||||
defined(GLFW_DLL)
|
||||
#error "You must not define any header option macros when compiling GLFW"
|
||||
#endif
|
||||
@@ -47,8 +46,18 @@
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include "../include/GLFW/glfw3.h"
|
||||
|
||||
#define _GLFW_INSERT_FIRST 0
|
||||
#define _GLFW_INSERT_LAST 1
|
||||
|
||||
#define _GLFW_POLL_PRESENCE 0
|
||||
#define _GLFW_POLL_AXES 1
|
||||
#define _GLFW_POLL_BUTTONS 2
|
||||
#define _GLFW_POLL_ALL (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
|
||||
|
||||
typedef int GLFWbool;
|
||||
|
||||
typedef struct _GLFWerror _GLFWerror;
|
||||
typedef struct _GLFWinitconfig _GLFWinitconfig;
|
||||
typedef struct _GLFWwndconfig _GLFWwndconfig;
|
||||
typedef struct _GLFWctxconfig _GLFWctxconfig;
|
||||
typedef struct _GLFWfbconfig _GLFWfbconfig;
|
||||
@@ -57,6 +66,11 @@ typedef struct _GLFWwindow _GLFWwindow;
|
||||
typedef struct _GLFWlibrary _GLFWlibrary;
|
||||
typedef struct _GLFWmonitor _GLFWmonitor;
|
||||
typedef struct _GLFWcursor _GLFWcursor;
|
||||
typedef struct _GLFWmapelement _GLFWmapelement;
|
||||
typedef struct _GLFWmapping _GLFWmapping;
|
||||
typedef struct _GLFWjoystick _GLFWjoystick;
|
||||
typedef struct _GLFWtls _GLFWtls;
|
||||
typedef struct _GLFWmutex _GLFWmutex;
|
||||
|
||||
typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
|
||||
typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
|
||||
@@ -68,6 +82,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
#define GL_VERSION 0x1f02
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_EXTENSIONS 0x1f03
|
||||
#define GL_NUM_EXTENSIONS 0x821d
|
||||
#define GL_CONTEXT_FLAGS 0x821e
|
||||
@@ -109,6 +124,7 @@ typedef enum VkStructureType
|
||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
|
||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||
} VkStructureType;
|
||||
|
||||
@@ -149,11 +165,16 @@ typedef struct VkExtensionProperties
|
||||
} VkExtensionProperties;
|
||||
|
||||
typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
|
||||
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
|
||||
|
||||
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
|
||||
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
|
||||
#if defined(_GLFW_VULKAN_STATIC)
|
||||
PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
|
||||
VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
|
||||
#else
|
||||
typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
|
||||
typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
|
||||
#define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
|
||||
#define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
|
||||
#endif
|
||||
|
||||
#if defined(_GLFW_COCOA)
|
||||
#include "cocoa_platform.h"
|
||||
@@ -165,6 +186,8 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
|
||||
#include "wl_platform.h"
|
||||
#elif defined(_GLFW_MIR)
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "null_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
@@ -210,13 +233,13 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
|
||||
|
||||
// Checks for whether the library has been initialized
|
||||
#define _GLFW_REQUIRE_INIT() \
|
||||
if (!_glfwInitialized) \
|
||||
if (!_glfw.initialized) \
|
||||
{ \
|
||||
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
||||
return; \
|
||||
}
|
||||
#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
|
||||
if (!_glfwInitialized) \
|
||||
if (!_glfw.initialized) \
|
||||
{ \
|
||||
_glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
|
||||
return x; \
|
||||
@@ -236,6 +259,30 @@ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const c
|
||||
// Platform-independent structures
|
||||
//========================================================================
|
||||
|
||||
struct _GLFWerror
|
||||
{
|
||||
_GLFWerror* next;
|
||||
int code;
|
||||
char description[1024];
|
||||
};
|
||||
|
||||
/*! @brief Initialization configuration.
|
||||
*
|
||||
* Parameters relating to the initialization of the library.
|
||||
*/
|
||||
struct _GLFWinitconfig
|
||||
{
|
||||
GLFWbool hatButtons;
|
||||
struct {
|
||||
GLFWbool menubar;
|
||||
GLFWbool chdir;
|
||||
} ns;
|
||||
struct {
|
||||
char className[256];
|
||||
char classClass[256];
|
||||
} x11;
|
||||
};
|
||||
|
||||
/*! @brief Window configuration.
|
||||
*
|
||||
* Parameters relating to the creation of the window but not directly related
|
||||
@@ -254,9 +301,13 @@ struct _GLFWwndconfig
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool maximized;
|
||||
GLFWbool centerCursor;
|
||||
struct {
|
||||
GLFWbool retina;
|
||||
GLFWbool frame;
|
||||
} ns;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Context configuration.
|
||||
*
|
||||
* Parameters relating to the creation of the context but not directly related
|
||||
@@ -276,9 +327,11 @@ struct _GLFWctxconfig
|
||||
int robustness;
|
||||
int release;
|
||||
_GLFWwindow* share;
|
||||
struct {
|
||||
GLFWbool offline;
|
||||
} nsgl;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Framebuffer configuration.
|
||||
*
|
||||
* This describes buffers and their sizes. It also contains
|
||||
@@ -307,7 +360,6 @@ struct _GLFWfbconfig
|
||||
uintptr_t handle;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Context structure.
|
||||
*/
|
||||
struct _GLFWcontext
|
||||
@@ -335,9 +387,10 @@ struct _GLFWcontext
|
||||
_GLFW_PLATFORM_CONTEXT_STATE;
|
||||
// This is defined in egl_context.h
|
||||
_GLFW_EGL_CONTEXT_STATE;
|
||||
// This is defined in osmesa_context.h
|
||||
_GLFW_OSMESA_CONTEXT_STATE;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Window and context structure.
|
||||
*/
|
||||
struct _GLFWwindow
|
||||
@@ -349,7 +402,7 @@ struct _GLFWwindow
|
||||
GLFWbool decorated;
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool closed;
|
||||
GLFWbool shouldClose;
|
||||
void* userPointer;
|
||||
GLFWvidmode videoMode;
|
||||
_GLFWmonitor* monitor;
|
||||
@@ -376,6 +429,7 @@ struct _GLFWwindow
|
||||
GLFWwindowrefreshfun refresh;
|
||||
GLFWwindowfocusfun focus;
|
||||
GLFWwindowiconifyfun iconify;
|
||||
GLFWwindowmaximizefun maximize;
|
||||
GLFWframebuffersizefun fbsize;
|
||||
GLFWmousebuttonfun mouseButton;
|
||||
GLFWcursorposfun cursorPos;
|
||||
@@ -391,7 +445,6 @@ struct _GLFWwindow
|
||||
_GLFW_PLATFORM_WINDOW_STATE;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Monitor structure.
|
||||
*/
|
||||
struct _GLFWmonitor
|
||||
@@ -415,7 +468,6 @@ struct _GLFWmonitor
|
||||
_GLFW_PLATFORM_MONITOR_STATE;
|
||||
};
|
||||
|
||||
|
||||
/*! @brief Cursor structure
|
||||
*/
|
||||
struct _GLFWcursor
|
||||
@@ -426,39 +478,115 @@ struct _GLFWcursor
|
||||
_GLFW_PLATFORM_CURSOR_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Gamepad mapping element structure
|
||||
*/
|
||||
struct _GLFWmapelement
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t value;
|
||||
};
|
||||
|
||||
/*! @brief Gamepad mapping structure
|
||||
*/
|
||||
struct _GLFWmapping
|
||||
{
|
||||
char name[128];
|
||||
char guid[33];
|
||||
_GLFWmapelement buttons[15];
|
||||
_GLFWmapelement axes[6];
|
||||
};
|
||||
|
||||
/*! @brief Joystick structure
|
||||
*/
|
||||
struct _GLFWjoystick
|
||||
{
|
||||
GLFWbool present;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
unsigned char* hats;
|
||||
int hatCount;
|
||||
char* name;
|
||||
char guid[33];
|
||||
_GLFWmapping* mapping;
|
||||
|
||||
// This is defined in the joystick API's joystick.h
|
||||
_GLFW_PLATFORM_JOYSTICK_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Thread local storage structure.
|
||||
*/
|
||||
struct _GLFWtls
|
||||
{
|
||||
// This is defined in the platform's thread.h
|
||||
_GLFW_PLATFORM_TLS_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Mutex structure.
|
||||
*/
|
||||
struct _GLFWmutex
|
||||
{
|
||||
// This is defined in the platform's thread.h
|
||||
_GLFW_PLATFORM_MUTEX_STATE;
|
||||
};
|
||||
|
||||
/*! @brief Library global data.
|
||||
*/
|
||||
struct _GLFWlibrary
|
||||
{
|
||||
GLFWbool initialized;
|
||||
|
||||
struct {
|
||||
_GLFWinitconfig init;
|
||||
_GLFWfbconfig framebuffer;
|
||||
_GLFWwndconfig window;
|
||||
_GLFWctxconfig context;
|
||||
int refreshRate;
|
||||
} hints;
|
||||
|
||||
_GLFWerror* errorListHead;
|
||||
_GLFWcursor* cursorListHead;
|
||||
|
||||
_GLFWwindow* windowListHead;
|
||||
|
||||
_GLFWmonitor** monitors;
|
||||
int monitorCount;
|
||||
|
||||
uint64_t timerOffset;
|
||||
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
|
||||
_GLFWmapping* mappings;
|
||||
int mappingCount;
|
||||
|
||||
_GLFWtls errorSlot;
|
||||
_GLFWtls contextSlot;
|
||||
_GLFWmutex errorLock;
|
||||
|
||||
struct {
|
||||
uint64_t offset;
|
||||
// This is defined in the platform's time.h
|
||||
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
|
||||
} timer;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
void* handle;
|
||||
char** extensions;
|
||||
uint32_t extensionCount;
|
||||
char* extensions[2];
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||
#endif
|
||||
GLFWbool KHR_surface;
|
||||
#if defined(_GLFW_WIN32)
|
||||
GLFWbool KHR_win32_surface;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
GLFWbool MVK_macos_surface;
|
||||
#elif defined(_GLFW_X11)
|
||||
GLFWbool KHR_xlib_surface;
|
||||
GLFWbool KHR_xcb_surface;
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
GLFWbool KHR_wayland_surface;
|
||||
#elif defined(_GLFW_MIR)
|
||||
GLFWbool KHR_mir_surface;
|
||||
#endif
|
||||
} vk;
|
||||
|
||||
struct {
|
||||
@@ -470,14 +598,12 @@ struct _GLFWlibrary
|
||||
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
||||
// This is defined in the context API's context.h
|
||||
_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
|
||||
_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
|
||||
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
||||
// This is defined in osmesa_context.h
|
||||
_GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
|
||||
};
|
||||
|
||||
|
||||
@@ -485,13 +611,7 @@ struct _GLFWlibrary
|
||||
// Global state shared between compilation units of GLFW
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Flag indicating whether GLFW has been successfully initialized.
|
||||
*/
|
||||
extern GLFWbool _glfwInitialized;
|
||||
|
||||
/*! @brief All global data protected by @ref _glfwInitialized.
|
||||
* This should only be touched after a call to @ref glfwInit that has not been
|
||||
* followed by a call to @ref glfwTerminate.
|
||||
/*! @brief All global data shared between compilation units.
|
||||
*/
|
||||
extern _GLFWlibrary _glfw;
|
||||
|
||||
@@ -500,312 +620,97 @@ extern _GLFWlibrary _glfw;
|
||||
// Platform API functions
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Initializes the platform-specific part of the library.
|
||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an error occurred.
|
||||
* @ingroup platform
|
||||
*/
|
||||
/*! @addtogroup platform @{ */
|
||||
|
||||
int _glfwPlatformInit(void);
|
||||
|
||||
/*! @brief Terminates the platform-specific part of the library.
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformTerminate(void);
|
||||
|
||||
/*! @copydoc glfwGetVersionString
|
||||
* @ingroup platform
|
||||
*
|
||||
* @note The returned string must be available for the duration of the program.
|
||||
*
|
||||
* @note The returned string must not change for the duration of the program.
|
||||
*/
|
||||
const char* _glfwPlatformGetVersionString(void);
|
||||
|
||||
/*! @copydoc glfwGetCursorPos
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
|
||||
|
||||
/*! @copydoc glfwSetCursorPos
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
|
||||
/*! @brief Sets the specified cursor mode of the specified window.
|
||||
* @param[in] window The window whose cursor mode to set.
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
|
||||
/*! @copydoc glfwGetKeyName
|
||||
* @ingroup platform
|
||||
*/
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode);
|
||||
const char* _glfwPlatformGetScancodeName(int scancode);
|
||||
int _glfwPlatformGetKeyScancode(int key);
|
||||
|
||||
/*! @copydoc glfwGetMonitors
|
||||
* @ingroup platform
|
||||
*/
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count);
|
||||
|
||||
/*! @brief Checks whether two monitor objects represent the same monitor.
|
||||
*
|
||||
* @param[in] first The first monitor.
|
||||
* @param[in] second The second monitor.
|
||||
* @return @c GLFW_TRUE if the monitor objects represent the same monitor, or
|
||||
* @c GLFW_FALSE otherwise.
|
||||
* @ingroup platform
|
||||
*/
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second);
|
||||
|
||||
/*! @copydoc glfwGetMonitorPos
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||
|
||||
/*! @copydoc glfwGetVideoModes
|
||||
* @ingroup platform
|
||||
*/
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||
|
||||
/*! @copydoc glfwGetGammaRamp
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
|
||||
/*! @copydoc glfwSetGammaRamp
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
/*! @copydoc glfwSetClipboardString
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
|
||||
|
||||
/*! @copydoc glfwGetClipboardString
|
||||
* @ingroup platform
|
||||
*
|
||||
* @note The returned string must be valid until the next call to @ref
|
||||
* _glfwPlatformGetClipboardString or @ref _glfwPlatformSetClipboardString.
|
||||
*/
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwJoystickPresent
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformJoystickPresent(int joy);
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
||||
|
||||
/*! @copydoc glfwGetJoystickAxes
|
||||
* @ingroup platform
|
||||
*/
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count);
|
||||
|
||||
/*! @copydoc glfwGetJoystickButtons
|
||||
* @ingroup platform
|
||||
*/
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
|
||||
|
||||
/*! @copydoc glfwGetJoystickName
|
||||
* @ingroup platform
|
||||
*/
|
||||
const char* _glfwPlatformGetJoystickName(int joy);
|
||||
|
||||
/*! @copydoc glfwGetTimerValue
|
||||
* @ingroup platform
|
||||
*/
|
||||
uint64_t _glfwPlatformGetTimerValue(void);
|
||||
|
||||
/*! @copydoc glfwGetTimerFrequency
|
||||
* @ingroup platform
|
||||
*/
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwSetWindowTitle
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
|
||||
|
||||
/*! @copydoc glfwSetWindowIcon
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images);
|
||||
|
||||
/*! @copydoc glfwGetWindowPos
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
|
||||
|
||||
/*! @copydoc glfwSetWindowPos
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||
|
||||
/*! @copydoc glfwGetWindowSize
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
|
||||
|
||||
/*! @copydoc glfwSetWindowSize
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
|
||||
|
||||
/*! @copydoc glfwSetWindowSizeLimits
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
|
||||
|
||||
/*! @copydoc glfwSetWindowAspectRatio
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||
|
||||
/*! @copydoc glfwGetFramebufferSize
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||
|
||||
/*! @copydoc glfwGetWindowFrameSize
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
|
||||
|
||||
/*! @copydoc glfwIconifyWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwRestoreWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwMaximizeWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwShowWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwHideWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwFocusWindow
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
||||
|
||||
/*! @copydoc glfwSetWindowMonitor
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformDragWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
|
||||
|
||||
/*! @brief Returns whether the window is focused.
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns whether the window is iconified.
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns whether the window is visible.
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns whether the window is maximized.
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
||||
|
||||
/*! @copydoc glfwPollEvents
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformPollEvents(void);
|
||||
|
||||
/*! @copydoc glfwWaitEvents
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformWaitEvents(void);
|
||||
|
||||
/*! @copydoc glfwWaitEventsTimeout
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout);
|
||||
|
||||
/*! @copydoc glfwPostEmptyEvent
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformPostEmptyEvent(void);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
|
||||
|
||||
/*! @copydoc glfwGetCurrentContext
|
||||
* @ingroup platform
|
||||
*/
|
||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void);
|
||||
|
||||
/*! @copydoc glfwCreateCursor
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
|
||||
|
||||
/*! @copydoc glfwCreateStandardCursor
|
||||
* @ingroup platform
|
||||
*/
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
|
||||
|
||||
/*! @copydoc glfwDestroyCursor
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||
|
||||
/*! @copydoc glfwSetCursor
|
||||
* @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
|
||||
|
||||
/*! @ingroup platform
|
||||
*/
|
||||
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);
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
||||
|
||||
/*! @} */
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Event API functions
|
||||
//========================================================================
|
||||
|
||||
/*! @brief Notifies shared code of a window focus event.
|
||||
/*! @brief Notifies shared code that a window has lost or received input focus.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE`
|
||||
* if it lost focus.
|
||||
@@ -813,7 +718,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* wind
|
||||
*/
|
||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
||||
|
||||
/*! @brief Notifies shared code of a window movement event.
|
||||
/*! @brief Notifies shared code that a window has moved.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] xpos The new x-coordinate of the client area of the window.
|
||||
* @param[in] ypos The new y-coordinate of the client area of the window.
|
||||
@@ -821,7 +726,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
||||
*/
|
||||
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||
|
||||
/*! @brief Notifies shared code of a window resize event.
|
||||
/*! @brief Notifies shared code that a window has been resized.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] width The new width of the client area of the window.
|
||||
* @param[in] height The new height of the client area of the window.
|
||||
@@ -829,7 +734,7 @@ void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||
*/
|
||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||
|
||||
/*! @brief Notifies shared code of a framebuffer resize event.
|
||||
/*! @brief Notifies shared code that a window framebuffer has been resized.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] width The new width, in pixels, of the framebuffer.
|
||||
* @param[in] height The new height, in pixels, of the framebuffer.
|
||||
@@ -837,7 +742,7 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||
*/
|
||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||
|
||||
/*! @brief Notifies shared code of a window iconification event.
|
||||
/*! @brief Notifies shared code that a window has been iconified or restored.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
@@ -845,17 +750,30 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||
*/
|
||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
||||
|
||||
/*! @brief Notifies shared code of a window damage event.
|
||||
/*! @brief Notifies shared code that a window has been maximized or restored.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] maximized `GLFW_TRUE` if the window was maximized, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
||||
|
||||
/*! @brief Notifies shared code that a window's contents needs updating.
|
||||
* @param[in] window The window that received the event.
|
||||
*/
|
||||
void _glfwInputWindowDamage(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code of a window close request event
|
||||
/*! @brief Notifies shared code that the user wishes to close a window.
|
||||
* @param[in] window The window that received the event.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code that a window has changed its desired monitor.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] monitor The new desired monitor, or `NULL`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Notifies shared code of a physical key event.
|
||||
@@ -890,6 +808,7 @@ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] button The button that was pressed or released.
|
||||
* @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
|
||||
* @param[in] mods The modifiers pressed when the event was generated.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||
@@ -912,27 +831,35 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
*/
|
||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
||||
|
||||
/*! @ingroup event
|
||||
/*! @brief Notifies shared code of a monitor connection or disconnection.
|
||||
* @param[in] monitor The monitor that was connected or disconnected.
|
||||
* @param[in] action One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
* @param[in] placement `_GLFW_INSERT_FIRST` or `_GLFW_INSERT_LAST`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMonitorChange(void);
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
||||
|
||||
/*! @ingroup event
|
||||
/*! @brief Notifies shared code that a full screen window has acquired or
|
||||
* released a monitor.
|
||||
* @param[in] monitor The monitor that was acquired or released.
|
||||
* @param[in] window The window that acquired the monitor, or `NULL`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||
|
||||
/*! @brief Notifies shared code of an error.
|
||||
* @param[in] error The error code most suitable for the error.
|
||||
* @param[in] code The error code most suitable for the error.
|
||||
* @param[in] format The `printf` style format string of the error
|
||||
* description.
|
||||
* @ingroup event
|
||||
*/
|
||||
#if defined(__GNUC__)
|
||||
void _glfwInputError(int error, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
void _glfwInputError(int code, const char* format, ...) __attribute__((format(printf, 2, 3)));
|
||||
#else
|
||||
void _glfwInputError(int error, const char* format, ...);
|
||||
void _glfwInputError(int code, const char* format, ...);
|
||||
#endif
|
||||
|
||||
/*! @brief Notifies dropped object over window.
|
||||
/*! @brief Notifies shared code of files or directories dropped on a window.
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] count The number of dropped objects.
|
||||
* @param[in] names The names of the dropped objects.
|
||||
@@ -940,19 +867,41 @@ void _glfwInputError(int error, const char* format, ...);
|
||||
*/
|
||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||
|
||||
/*! @brief Notifies shared code of a joystick connection/disconnection event.
|
||||
* @param[in] joy The joystick that was connected or disconnected.
|
||||
/*! @brief Notifies shared code of a joystick connection or disconnection.
|
||||
* @param[in] js The joystick that was connected or disconnected.
|
||||
* @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
|
||||
* @ingroup event
|
||||
*/
|
||||
void _glfwInputJoystickChange(int joy, int event);
|
||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick axis.
|
||||
* @param[in] js The joystick whose axis to update.
|
||||
* @param[in] axis The index of the axis to update.
|
||||
* @param[in] value The new value of the axis.
|
||||
*/
|
||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick button.
|
||||
* @param[in] js The joystick whose button to update.
|
||||
* @param[in] button The index of the button to update.
|
||||
* @param[in] value The new value of the button.
|
||||
*/
|
||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
||||
|
||||
/*! @brief Notifies shared code of the new value of a joystick hat.
|
||||
* @param[in] js 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(_GLFWjoystick* js, int hat, char value);
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Utility functions
|
||||
//========================================================================
|
||||
|
||||
/*! @ingroup utility
|
||||
/*! @brief Chooses the video mode most closely matching the desired one.
|
||||
* @ingroup utility
|
||||
*/
|
||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||
const GLFWvidmode* desired);
|
||||
@@ -1007,11 +956,13 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
|
||||
*/
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||
|
||||
/*! @ingroup utility
|
||||
/*! @brief Allocates red, green and blue value arrays of the specified size.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
|
||||
|
||||
/*! @ingroup utility
|
||||
/*! @brief Frees the red, green and blue value arrays and clears the struct.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
|
||||
|
||||
@@ -1030,17 +981,23 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
|
||||
*/
|
||||
void _glfwFreeMonitor(_GLFWmonitor* monitor);
|
||||
|
||||
/*! @ingroup utility
|
||||
/*! @brief Returns an available joystick object with arrays and name allocated.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
|
||||
_GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
const char* guid,
|
||||
int axisCount,
|
||||
int buttonCount,
|
||||
int hatCount);
|
||||
|
||||
/*! @brief Frees arrays and name and flags the joystick object as unused.
|
||||
* @ingroup utility
|
||||
*/
|
||||
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
GLFWbool _glfwIsPrintable(int key);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
void _glfwInitVulkan(void);
|
||||
GLFWbool _glfwInitVulkan(int mode);
|
||||
|
||||
/*! @ingroup utility
|
||||
*/
|
||||
@@ -1050,4 +1007,3 @@ void _glfwTerminateVulkan(void);
|
||||
*/
|
||||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
|
||||
#endif // _glfw3_internal_h_
|
||||
|
||||
+266
-164
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Linux - www.glfw.org
|
||||
// GLFW 3.3 Linux - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -27,9 +27,6 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/joystick.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/inotify.h>
|
||||
@@ -40,129 +37,220 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#endif // __linux__
|
||||
|
||||
// Apply an EV_KEY event to the specified joystick
|
||||
//
|
||||
static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
|
||||
{
|
||||
_glfwInputJoystickButton(js,
|
||||
js->linjs.keyMap[code - BTN_MISC],
|
||||
value ? GLFW_PRESS : GLFW_RELEASE);
|
||||
}
|
||||
|
||||
// Apply an EV_ABS event to the specified joystick
|
||||
//
|
||||
static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
|
||||
{
|
||||
const int index = js->linjs.absMap[code];
|
||||
|
||||
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||
{
|
||||
static const char stateMap[3][3] =
|
||||
{
|
||||
{ GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN },
|
||||
{ GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN },
|
||||
{ GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
|
||||
};
|
||||
|
||||
const int hat = (code - ABS_HAT0X) / 2;
|
||||
const int axis = (code - ABS_HAT0X) % 2;
|
||||
int* state = js->linjs.hats[hat];
|
||||
|
||||
// NOTE: Looking at several input drivers, it seems all hat events use
|
||||
// -1 for left / up, 0 for centered and 1 for right / down
|
||||
if (value == 0)
|
||||
state[axis] = 0;
|
||||
else if (value < 0)
|
||||
state[axis] = 1;
|
||||
else if (value > 0)
|
||||
state[axis] = 2;
|
||||
|
||||
_glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||
float normalized = value;
|
||||
|
||||
const int range = info->maximum - info->minimum;
|
||||
if (range)
|
||||
{
|
||||
// Normalize to 0.0 -> 1.0
|
||||
normalized = (normalized - info->minimum) / range;
|
||||
// Normalize to -1.0 -> 1.0
|
||||
normalized = normalized * 2.0f - 1.0f;
|
||||
}
|
||||
|
||||
_glfwInputJoystickAxis(js, index, normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Poll state of absolute axes
|
||||
//
|
||||
static void pollAbsState(_GLFWjoystick* js)
|
||||
{
|
||||
int code;
|
||||
|
||||
for (code = 0; code < ABS_CNT; code++)
|
||||
{
|
||||
if (js->linjs.absMap[code] < 0)
|
||||
continue;
|
||||
|
||||
struct input_absinfo* info = &js->linjs.absInfo[code];
|
||||
|
||||
if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
|
||||
continue;
|
||||
|
||||
handleAbsEvent(js, code, info->value);
|
||||
}
|
||||
}
|
||||
|
||||
#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
//
|
||||
#if defined(__linux__)
|
||||
static GLFWbool openJoystickDevice(const char* path)
|
||||
{
|
||||
char axisCount, buttonCount;
|
||||
char name[256];
|
||||
int joy, fd, version;
|
||||
_GLFWjoystickLinux* js;
|
||||
int jid, code;
|
||||
char name[256] = "";
|
||||
char guid[33] = "";
|
||||
char evBits[(EV_CNT + 7) / 8] = {0};
|
||||
char keyBits[(KEY_CNT + 7) / 8] = {0};
|
||||
char absBits[(ABS_CNT + 7) / 8] = {0};
|
||||
int axisCount = 0, buttonCount = 0, hatCount = 0;
|
||||
struct input_id id;
|
||||
_GLFWjoystickLinux linjs = {0};
|
||||
_GLFWjoystick* js = NULL;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[joy].present)
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
|
||||
if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
{
|
||||
if (!_glfw.linux_js.js[joy].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (linjs.fd == -1)
|
||||
return GLFW_FALSE;
|
||||
|
||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (fd == -1)
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Verify that the joystick driver version is at least 1.0
|
||||
ioctl(fd, JSIOCGVERSION, &version);
|
||||
if (version < 0x010000)
|
||||
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
|
||||
ioctl(linjs.fd, EVIOCGID, &id) < 0)
|
||||
{
|
||||
// It's an old 0.x interface (we don't support it)
|
||||
close(fd);
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to query input device: %s",
|
||||
strerror(errno));
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
|
||||
// Ensure this device supports the events expected of a joystick
|
||||
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||
strncpy(name, "Unknown", sizeof(name));
|
||||
|
||||
js = _glfw.linux_js.js + joy;
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(name);
|
||||
js->path = strdup(path);
|
||||
js->fd = fd;
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (id.vendor && id.product && id.version)
|
||||
{
|
||||
sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
|
||||
id.bustype & 0xff, id.bustype >> 8,
|
||||
id.vendor & 0xff, id.vendor >> 8,
|
||||
id.product & 0xff, id.product >> 8,
|
||||
id.version & 0xff, id.version >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
id.bustype & 0xff, id.bustype >> 8,
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
ioctl(fd, JSIOCGAXES, &axisCount);
|
||||
js->axisCount = (int) axisCount;
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
for (code = BTN_MISC; code < KEY_CNT; code++)
|
||||
{
|
||||
if (!isBitSet(code, keyBits))
|
||||
continue;
|
||||
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttonCount);
|
||||
js->buttonCount = (int) buttonCount;
|
||||
js->buttons = calloc(buttonCount, 1);
|
||||
linjs.keyMap[code - BTN_MISC] = buttonCount;
|
||||
buttonCount++;
|
||||
}
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
for (code = 0; code < ABS_CNT; code++)
|
||||
{
|
||||
linjs.absMap[code] = -1;
|
||||
if (!isBitSet(code, absBits))
|
||||
continue;
|
||||
|
||||
if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
|
||||
{
|
||||
linjs.absMap[code] = hatCount;
|
||||
hatCount++;
|
||||
// Skip the Y axis
|
||||
code++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
|
||||
continue;
|
||||
|
||||
linjs.absMap[code] = axisCount;
|
||||
axisCount++;
|
||||
}
|
||||
}
|
||||
|
||||
js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
|
||||
if (!js)
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
strncpy(linjs.path, path, sizeof(linjs.path));
|
||||
memcpy(&js->linjs, &linjs, sizeof(linjs));
|
||||
|
||||
pollAbsState(js);
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
// Polls for and processes events the specified joystick
|
||||
#undef isBitSet
|
||||
|
||||
// Frees all resources associated with the specified joystick
|
||||
//
|
||||
static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
_glfwPollJoystickEvents();
|
||||
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
{
|
||||
struct js_event e;
|
||||
|
||||
errno = 0;
|
||||
if (read(js->fd, &e, sizeof(e)) < 0)
|
||||
{
|
||||
// Reset the joystick slot if the device was disconnected
|
||||
if (errno == ENODEV)
|
||||
{
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->name);
|
||||
free(js->path);
|
||||
|
||||
memset(js, 0, sizeof(_GLFWjoystickLinux));
|
||||
|
||||
_glfwInputJoystickChange(js - _glfw.linux_js.js,
|
||||
GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the initial-state bit
|
||||
e.type &= ~JS_EVENT_INIT;
|
||||
|
||||
if (e.type == JS_EVENT_AXIS)
|
||||
js->axes[e.number] = (float) e.value / 32767.0f;
|
||||
else if (e.type == JS_EVENT_BUTTON)
|
||||
js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
|
||||
}
|
||||
#endif // __linux__
|
||||
return js->present;
|
||||
close(js->linjs.fd);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Lexically compare joysticks, used by quicksort
|
||||
// Lexically compare joysticks by name; used by qsort
|
||||
//
|
||||
#if defined(__linux__)
|
||||
static int compareJoysticks(const void* fp, const void* sp)
|
||||
{
|
||||
const _GLFWjoystickLinux* fj = fp;
|
||||
const _GLFWjoystickLinux* sj = sp;
|
||||
return strcmp(fj->path, sj->path);
|
||||
const _GLFWjoystick* fj = fp;
|
||||
const _GLFWjoystick* sj = sp;
|
||||
return strcmp(fj->linjs.path, sj->linjs.path);
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -173,13 +261,12 @@ static int compareJoysticks(const void* fp, const void* sp)
|
||||
//
|
||||
GLFWbool _glfwInitJoysticksLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
DIR* dir;
|
||||
int count = 0;
|
||||
const char* dirname = "/dev/input";
|
||||
|
||||
_glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linux_js.inotify == -1)
|
||||
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||
if (_glfw.linjs.inotify == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to initialize inotify: %s",
|
||||
@@ -190,10 +277,10 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
// HACK: Register for IN_ATTRIB as well to get notified when udev is done
|
||||
// This works well in practice but the true way is libudev
|
||||
|
||||
_glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB);
|
||||
if (_glfw.linux_js.watch == -1)
|
||||
_glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
|
||||
dirname,
|
||||
IN_CREATE | IN_ATTRIB | IN_DELETE);
|
||||
if (_glfw.linjs.watch == -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Linux: Failed to watch for joystick connections in %s: %s",
|
||||
@@ -202,7 +289,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
// Continue without device connection notifications
|
||||
}
|
||||
|
||||
if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0)
|
||||
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||
return GLFW_FALSE;
|
||||
@@ -215,13 +302,15 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
|
||||
while ((entry = readdir(dir)))
|
||||
{
|
||||
char path[20];
|
||||
regmatch_t match;
|
||||
|
||||
if (regexec(&_glfw.linux_js.regex, entry->d_name, 1, &match, 0) != 0)
|
||||
if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
|
||||
snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
|
||||
|
||||
if (openJoystickDevice(path))
|
||||
count++;
|
||||
}
|
||||
@@ -237,9 +326,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
// Continue with no joysticks detected
|
||||
}
|
||||
|
||||
qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks);
|
||||
#endif // __linux__
|
||||
|
||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -247,56 +334,62 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
int i;
|
||||
int jid;
|
||||
|
||||
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.linux_js.js[i].present)
|
||||
{
|
||||
close(_glfw.linux_js.js[i].fd);
|
||||
free(_glfw.linux_js.js[i].axes);
|
||||
free(_glfw.linux_js.js[i].buttons);
|
||||
free(_glfw.linux_js.js[i].name);
|
||||
free(_glfw.linux_js.js[i].path);
|
||||
}
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
closeJoystick(js);
|
||||
}
|
||||
|
||||
regfree(&_glfw.linux_js.regex);
|
||||
regfree(&_glfw.linjs.regex);
|
||||
|
||||
if (_glfw.linux_js.inotify > 0)
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
{
|
||||
if (_glfw.linux_js.watch > 0)
|
||||
inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
|
||||
if (_glfw.linjs.watch > 0)
|
||||
inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
|
||||
|
||||
close(_glfw.linux_js.inotify);
|
||||
close(_glfw.linjs.inotify);
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
void _glfwPollJoystickEvents(void)
|
||||
void _glfwDetectJoystickConnectionLinux(void)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
ssize_t offset = 0;
|
||||
char buffer[16384];
|
||||
|
||||
const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
|
||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||
|
||||
while (size > offset)
|
||||
{
|
||||
regmatch_t match;
|
||||
const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
|
||||
|
||||
if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
|
||||
{
|
||||
char path[20];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
openJoystickDevice(path);
|
||||
}
|
||||
|
||||
offset += sizeof(struct inotify_event) + e->len;
|
||||
|
||||
if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
|
||||
continue;
|
||||
|
||||
char path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/dev/input/%s", e->name);
|
||||
|
||||
if (e->mask & (IN_CREATE | IN_ATTRIB))
|
||||
openJoystickDevice(path);
|
||||
else if (e->mask & IN_DELETE)
|
||||
{
|
||||
int jid;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
{
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -304,38 +397,47 @@ void _glfwPollJoystickEvents(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
return pollJoystickEvents(js);
|
||||
// Read all queued events (non-blocking)
|
||||
for (;;)
|
||||
{
|
||||
struct input_event e;
|
||||
|
||||
errno = 0;
|
||||
if (read(js->linjs.fd, &e, sizeof(e)) < 0)
|
||||
{
|
||||
// Reset the joystick slot if the device was disconnected
|
||||
if (errno == ENODEV)
|
||||
closeJoystick(js);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (e.type == EV_SYN)
|
||||
{
|
||||
if (e.code == SYN_DROPPED)
|
||||
_glfw.linjs.dropped = GLFW_TRUE;
|
||||
else if (e.code == SYN_REPORT)
|
||||
{
|
||||
_glfw.linjs.dropped = GLFW_FALSE;
|
||||
pollAbsState(js);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.linjs.dropped)
|
||||
continue;
|
||||
|
||||
if (e.type == EV_KEY)
|
||||
handleKeyEvent(js, e.code, e.value);
|
||||
else if (e.type == EV_ABS)
|
||||
handleAbsEvent(js, e.code, e.value);
|
||||
}
|
||||
|
||||
return js->present;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = js->axisCount;
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
*count = js->buttonCount;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
{
|
||||
_GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
|
||||
if (!pollJoystickEvents(js))
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
}
|
||||
|
||||
|
||||
+19
-26
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Linux - www.glfw.org
|
||||
// GLFW 3.3 Linux - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||
//
|
||||
@@ -24,46 +24,39 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_linux_joystick_h_
|
||||
#define _glfw3_linux_joystick_h_
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/limits.h>
|
||||
#include <regex.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
|
||||
|
||||
// Linux-specific joystick data
|
||||
//
|
||||
typedef struct _GLFWjoystickLinux
|
||||
{
|
||||
GLFWbool present;
|
||||
int fd;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
char* name;
|
||||
char* path;
|
||||
int fd;
|
||||
char path[PATH_MAX];
|
||||
int keyMap[KEY_CNT - BTN_MISC];
|
||||
int absMap[ABS_CNT];
|
||||
struct input_absinfo absInfo[ABS_CNT];
|
||||
int hats[4][2];
|
||||
} _GLFWjoystickLinux;
|
||||
|
||||
|
||||
// Linux-specific joystick API data
|
||||
//
|
||||
typedef struct _GLFWjoylistLinux
|
||||
typedef struct _GLFWlibraryLinux
|
||||
{
|
||||
_GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
#if defined(__linux__)
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
#endif /*__linux__*/
|
||||
} _GLFWjoylistLinux;
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
GLFWbool dropped;
|
||||
} _GLFWlibraryLinux;
|
||||
|
||||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(void);
|
||||
void _glfwDetectJoystickConnectionLinux(void);
|
||||
|
||||
void _glfwPollJoystickEvents(void);
|
||||
|
||||
#endif // _glfw3_linux_joystick_h_
|
||||
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
// All gamepad mappings not labeled GLFW are copied from the
|
||||
// SDL_GameControllerDB project under the following license:
|
||||
//
|
||||
// Simple DirectMedia Layer
|
||||
// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
const char* _glfwDefaultMappings =
|
||||
"8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
|
||||
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
|
||||
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,\n"
|
||||
"6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
|
||||
"0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,\n"
|
||||
"88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,\n"
|
||||
"4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,\n"
|
||||
"25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,\n"
|
||||
"4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
|
||||
"4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
|
||||
"4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,\n"
|
||||
"6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,\n"
|
||||
"4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
|
||||
"00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
|
||||
"00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,\n"
|
||||
"28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,\n"
|
||||
"8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
|
||||
"8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
|
||||
"4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
|
||||
"83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,\n"
|
||||
"10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
|
||||
"49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,\n"
|
||||
"4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
|
||||
"79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows,\n"
|
||||
"10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows,\n"
|
||||
"63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,\n"
|
||||
"341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,\n"
|
||||
"c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,\n"
|
||||
"100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows,\n"
|
||||
"79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,\n"
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,\n"
|
||||
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
|
||||
"6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
|
||||
"6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
|
||||
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,\n"
|
||||
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,\n"
|
||||
"4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
|
||||
"4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,\n"
|
||||
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
|
||||
"891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,\n"
|
||||
"4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,\n"
|
||||
"8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
|
||||
"0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
|
||||
"4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,\n"
|
||||
"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,\n"
|
||||
"83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
|
||||
"bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,\n"
|
||||
"79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,\n"
|
||||
"5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,\n"
|
||||
"79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,\n"
|
||||
"2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,\n"
|
||||
"351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
|
||||
"b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
|
||||
"81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,\n"
|
||||
"10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,\n"
|
||||
"d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,\n"
|
||||
"0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,\n"
|
||||
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,\n"
|
||||
"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,\n"
|
||||
"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n"
|
||||
"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,\n"
|
||||
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,\n"
|
||||
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,\n"
|
||||
"030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
|
||||
"050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,\n"
|
||||
"030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
|
||||
"050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
|
||||
"030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,\n"
|
||||
"030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,\n"
|
||||
"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
|
||||
"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
|
||||
"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
|
||||
"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,\n"
|
||||
"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
|
||||
"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,\n"
|
||||
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
|
||||
"030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,\n"
|
||||
"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,\n"
|
||||
"030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,\n"
|
||||
"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,\n"
|
||||
"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
|
||||
"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
|
||||
"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,\n"
|
||||
"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,\n"
|
||||
"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
|
||||
"050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,\n"
|
||||
"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4,\n"
|
||||
"03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,\n"
|
||||
"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
|
||||
"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,\n"
|
||||
"030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
|
||||
"03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
|
||||
"050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,\n"
|
||||
"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,\n"
|
||||
"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,\n"
|
||||
"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7\n"
|
||||
"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
|
||||
"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux,\n"
|
||||
"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,\n"
|
||||
"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,\n"
|
||||
"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,\n"
|
||||
"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,\n"
|
||||
"05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
|
||||
"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,\n"
|
||||
"030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,\n"
|
||||
"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,\n"
|
||||
"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,\n"
|
||||
"05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,\n"
|
||||
"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux,\n"
|
||||
"030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,\n"
|
||||
"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,\n"
|
||||
"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,\n"
|
||||
"05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,\n"
|
||||
"030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux,\n"
|
||||
"03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,\n"
|
||||
"03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,\n"
|
||||
"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n"
|
||||
"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,\n";
|
||||
|
||||
+135
-136
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Mir - www.glfw.org
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -35,124 +35,134 @@
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
memset(_glfw.mir.publicKeys, -1, sizeof(_glfw.mir.publicKeys));
|
||||
int scancode;
|
||||
|
||||
_glfw.mir.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.mir.publicKeys[KEY_1] = GLFW_KEY_1;
|
||||
_glfw.mir.publicKeys[KEY_2] = GLFW_KEY_2;
|
||||
_glfw.mir.publicKeys[KEY_3] = GLFW_KEY_3;
|
||||
_glfw.mir.publicKeys[KEY_4] = GLFW_KEY_4;
|
||||
_glfw.mir.publicKeys[KEY_5] = GLFW_KEY_5;
|
||||
_glfw.mir.publicKeys[KEY_6] = GLFW_KEY_6;
|
||||
_glfw.mir.publicKeys[KEY_7] = GLFW_KEY_7;
|
||||
_glfw.mir.publicKeys[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.mir.publicKeys[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.mir.publicKeys[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.mir.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.mir.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.mir.publicKeys[KEY_Q] = GLFW_KEY_Q;
|
||||
_glfw.mir.publicKeys[KEY_W] = GLFW_KEY_W;
|
||||
_glfw.mir.publicKeys[KEY_E] = GLFW_KEY_E;
|
||||
_glfw.mir.publicKeys[KEY_R] = GLFW_KEY_R;
|
||||
_glfw.mir.publicKeys[KEY_T] = GLFW_KEY_T;
|
||||
_glfw.mir.publicKeys[KEY_Y] = GLFW_KEY_Y;
|
||||
_glfw.mir.publicKeys[KEY_U] = GLFW_KEY_U;
|
||||
_glfw.mir.publicKeys[KEY_I] = GLFW_KEY_I;
|
||||
_glfw.mir.publicKeys[KEY_O] = GLFW_KEY_O;
|
||||
_glfw.mir.publicKeys[KEY_P] = GLFW_KEY_P;
|
||||
_glfw.mir.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.mir.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.mir.publicKeys[KEY_A] = GLFW_KEY_A;
|
||||
_glfw.mir.publicKeys[KEY_S] = GLFW_KEY_S;
|
||||
_glfw.mir.publicKeys[KEY_D] = GLFW_KEY_D;
|
||||
_glfw.mir.publicKeys[KEY_F] = GLFW_KEY_F;
|
||||
_glfw.mir.publicKeys[KEY_G] = GLFW_KEY_G;
|
||||
_glfw.mir.publicKeys[KEY_H] = GLFW_KEY_H;
|
||||
_glfw.mir.publicKeys[KEY_J] = GLFW_KEY_J;
|
||||
_glfw.mir.publicKeys[KEY_K] = GLFW_KEY_K;
|
||||
_glfw.mir.publicKeys[KEY_L] = GLFW_KEY_L;
|
||||
_glfw.mir.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.mir.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.mir.publicKeys[KEY_Z] = GLFW_KEY_Z;
|
||||
_glfw.mir.publicKeys[KEY_X] = GLFW_KEY_X;
|
||||
_glfw.mir.publicKeys[KEY_C] = GLFW_KEY_C;
|
||||
_glfw.mir.publicKeys[KEY_V] = GLFW_KEY_V;
|
||||
_glfw.mir.publicKeys[KEY_B] = GLFW_KEY_B;
|
||||
_glfw.mir.publicKeys[KEY_N] = GLFW_KEY_N;
|
||||
_glfw.mir.publicKeys[KEY_M] = GLFW_KEY_M;
|
||||
_glfw.mir.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
|
||||
_glfw.mir.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
|
||||
_glfw.mir.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
|
||||
_glfw.mir.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.mir.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
|
||||
_glfw.mir.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
|
||||
_glfw.mir.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.mir.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.mir.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.mir.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.mir.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.mir.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.mir.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.mir.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.mir.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
|
||||
_glfw.mir.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.mir.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.mir.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.mir.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.mir.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
||||
_glfw.mir.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
|
||||
_glfw.mir.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.mir.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
|
||||
_glfw.mir.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
|
||||
_glfw.mir.publicKeys[KEY_END] = GLFW_KEY_END;
|
||||
_glfw.mir.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.mir.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.mir.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
|
||||
_glfw.mir.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
|
||||
_glfw.mir.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
||||
_glfw.mir.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
|
||||
_glfw.mir.publicKeys[KEY_UP] = GLFW_KEY_UP;
|
||||
_glfw.mir.publicKeys[KEY_F1] = GLFW_KEY_F1;
|
||||
_glfw.mir.publicKeys[KEY_F2] = GLFW_KEY_F2;
|
||||
_glfw.mir.publicKeys[KEY_F3] = GLFW_KEY_F3;
|
||||
_glfw.mir.publicKeys[KEY_F4] = GLFW_KEY_F4;
|
||||
_glfw.mir.publicKeys[KEY_F5] = GLFW_KEY_F5;
|
||||
_glfw.mir.publicKeys[KEY_F6] = GLFW_KEY_F6;
|
||||
_glfw.mir.publicKeys[KEY_F7] = GLFW_KEY_F7;
|
||||
_glfw.mir.publicKeys[KEY_F8] = GLFW_KEY_F8;
|
||||
_glfw.mir.publicKeys[KEY_F9] = GLFW_KEY_F9;
|
||||
_glfw.mir.publicKeys[KEY_F10] = GLFW_KEY_F10;
|
||||
_glfw.mir.publicKeys[KEY_F11] = GLFW_KEY_F11;
|
||||
_glfw.mir.publicKeys[KEY_F12] = GLFW_KEY_F12;
|
||||
_glfw.mir.publicKeys[KEY_F13] = GLFW_KEY_F13;
|
||||
_glfw.mir.publicKeys[KEY_F14] = GLFW_KEY_F14;
|
||||
_glfw.mir.publicKeys[KEY_F15] = GLFW_KEY_F15;
|
||||
_glfw.mir.publicKeys[KEY_F16] = GLFW_KEY_F16;
|
||||
_glfw.mir.publicKeys[KEY_F17] = GLFW_KEY_F17;
|
||||
_glfw.mir.publicKeys[KEY_F18] = GLFW_KEY_F18;
|
||||
_glfw.mir.publicKeys[KEY_F19] = GLFW_KEY_F19;
|
||||
_glfw.mir.publicKeys[KEY_F20] = GLFW_KEY_F20;
|
||||
_glfw.mir.publicKeys[KEY_F21] = GLFW_KEY_F21;
|
||||
_glfw.mir.publicKeys[KEY_F22] = GLFW_KEY_F22;
|
||||
_glfw.mir.publicKeys[KEY_F23] = GLFW_KEY_F23;
|
||||
_glfw.mir.publicKeys[KEY_F24] = GLFW_KEY_F24;
|
||||
_glfw.mir.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.mir.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.mir.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.mir.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_glfw.mir.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
|
||||
_glfw.mir.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
|
||||
_glfw.mir.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
|
||||
_glfw.mir.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
|
||||
_glfw.mir.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
|
||||
_glfw.mir.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
|
||||
_glfw.mir.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
|
||||
_glfw.mir.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
|
||||
_glfw.mir.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
|
||||
_glfw.mir.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
|
||||
_glfw.mir.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.mir.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.mir.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
memset(_glfw.mir.keycodes, -1, sizeof(_glfw.mir.keycodes));
|
||||
memset(_glfw.mir.scancodes, -1, sizeof(_glfw.mir.scancodes));
|
||||
|
||||
_glfw.mir.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.mir.keycodes[KEY_1] = GLFW_KEY_1;
|
||||
_glfw.mir.keycodes[KEY_2] = GLFW_KEY_2;
|
||||
_glfw.mir.keycodes[KEY_3] = GLFW_KEY_3;
|
||||
_glfw.mir.keycodes[KEY_4] = GLFW_KEY_4;
|
||||
_glfw.mir.keycodes[KEY_5] = GLFW_KEY_5;
|
||||
_glfw.mir.keycodes[KEY_6] = GLFW_KEY_6;
|
||||
_glfw.mir.keycodes[KEY_7] = GLFW_KEY_7;
|
||||
_glfw.mir.keycodes[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.mir.keycodes[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.mir.keycodes[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.mir.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
||||
_glfw.mir.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.mir.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.mir.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||
_glfw.mir.keycodes[KEY_W] = GLFW_KEY_W;
|
||||
_glfw.mir.keycodes[KEY_E] = GLFW_KEY_E;
|
||||
_glfw.mir.keycodes[KEY_R] = GLFW_KEY_R;
|
||||
_glfw.mir.keycodes[KEY_T] = GLFW_KEY_T;
|
||||
_glfw.mir.keycodes[KEY_Y] = GLFW_KEY_Y;
|
||||
_glfw.mir.keycodes[KEY_U] = GLFW_KEY_U;
|
||||
_glfw.mir.keycodes[KEY_I] = GLFW_KEY_I;
|
||||
_glfw.mir.keycodes[KEY_O] = GLFW_KEY_O;
|
||||
_glfw.mir.keycodes[KEY_P] = GLFW_KEY_P;
|
||||
_glfw.mir.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.mir.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.mir.keycodes[KEY_A] = GLFW_KEY_A;
|
||||
_glfw.mir.keycodes[KEY_S] = GLFW_KEY_S;
|
||||
_glfw.mir.keycodes[KEY_D] = GLFW_KEY_D;
|
||||
_glfw.mir.keycodes[KEY_F] = GLFW_KEY_F;
|
||||
_glfw.mir.keycodes[KEY_G] = GLFW_KEY_G;
|
||||
_glfw.mir.keycodes[KEY_H] = GLFW_KEY_H;
|
||||
_glfw.mir.keycodes[KEY_J] = GLFW_KEY_J;
|
||||
_glfw.mir.keycodes[KEY_K] = GLFW_KEY_K;
|
||||
_glfw.mir.keycodes[KEY_L] = GLFW_KEY_L;
|
||||
_glfw.mir.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.mir.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.mir.keycodes[KEY_Z] = GLFW_KEY_Z;
|
||||
_glfw.mir.keycodes[KEY_X] = GLFW_KEY_X;
|
||||
_glfw.mir.keycodes[KEY_C] = GLFW_KEY_C;
|
||||
_glfw.mir.keycodes[KEY_V] = GLFW_KEY_V;
|
||||
_glfw.mir.keycodes[KEY_B] = GLFW_KEY_B;
|
||||
_glfw.mir.keycodes[KEY_N] = GLFW_KEY_N;
|
||||
_glfw.mir.keycodes[KEY_M] = GLFW_KEY_M;
|
||||
_glfw.mir.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
||||
_glfw.mir.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
||||
_glfw.mir.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
||||
_glfw.mir.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.mir.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
||||
_glfw.mir.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
||||
_glfw.mir.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.mir.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.mir.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.mir.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.mir.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.mir.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.mir.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.mir.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.mir.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
||||
_glfw.mir.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.mir.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.mir.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.mir.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.mir.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
||||
_glfw.mir.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
||||
_glfw.mir.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.mir.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
||||
_glfw.mir.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
||||
_glfw.mir.keycodes[KEY_END] = GLFW_KEY_END;
|
||||
_glfw.mir.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.mir.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.mir.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
||||
_glfw.mir.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
||||
_glfw.mir.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
||||
_glfw.mir.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
||||
_glfw.mir.keycodes[KEY_UP] = GLFW_KEY_UP;
|
||||
_glfw.mir.keycodes[KEY_F1] = GLFW_KEY_F1;
|
||||
_glfw.mir.keycodes[KEY_F2] = GLFW_KEY_F2;
|
||||
_glfw.mir.keycodes[KEY_F3] = GLFW_KEY_F3;
|
||||
_glfw.mir.keycodes[KEY_F4] = GLFW_KEY_F4;
|
||||
_glfw.mir.keycodes[KEY_F5] = GLFW_KEY_F5;
|
||||
_glfw.mir.keycodes[KEY_F6] = GLFW_KEY_F6;
|
||||
_glfw.mir.keycodes[KEY_F7] = GLFW_KEY_F7;
|
||||
_glfw.mir.keycodes[KEY_F8] = GLFW_KEY_F8;
|
||||
_glfw.mir.keycodes[KEY_F9] = GLFW_KEY_F9;
|
||||
_glfw.mir.keycodes[KEY_F10] = GLFW_KEY_F10;
|
||||
_glfw.mir.keycodes[KEY_F11] = GLFW_KEY_F11;
|
||||
_glfw.mir.keycodes[KEY_F12] = GLFW_KEY_F12;
|
||||
_glfw.mir.keycodes[KEY_F13] = GLFW_KEY_F13;
|
||||
_glfw.mir.keycodes[KEY_F14] = GLFW_KEY_F14;
|
||||
_glfw.mir.keycodes[KEY_F15] = GLFW_KEY_F15;
|
||||
_glfw.mir.keycodes[KEY_F16] = GLFW_KEY_F16;
|
||||
_glfw.mir.keycodes[KEY_F17] = GLFW_KEY_F17;
|
||||
_glfw.mir.keycodes[KEY_F18] = GLFW_KEY_F18;
|
||||
_glfw.mir.keycodes[KEY_F19] = GLFW_KEY_F19;
|
||||
_glfw.mir.keycodes[KEY_F20] = GLFW_KEY_F20;
|
||||
_glfw.mir.keycodes[KEY_F21] = GLFW_KEY_F21;
|
||||
_glfw.mir.keycodes[KEY_F22] = GLFW_KEY_F22;
|
||||
_glfw.mir.keycodes[KEY_F23] = GLFW_KEY_F23;
|
||||
_glfw.mir.keycodes[KEY_F24] = GLFW_KEY_F24;
|
||||
_glfw.mir.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.mir.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.mir.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.mir.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_glfw.mir.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
||||
_glfw.mir.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
||||
_glfw.mir.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
||||
_glfw.mir.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
||||
_glfw.mir.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
||||
_glfw.mir.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
||||
_glfw.mir.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
||||
_glfw.mir.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
||||
_glfw.mir.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
||||
_glfw.mir.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
||||
_glfw.mir.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.mir.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.mir.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
{
|
||||
if (_glfw.mir.keycodes[scancode] > 0)
|
||||
_glfw.mir.scancodes[_glfw.mir.keycodes[scancode]] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,24 +190,15 @@ int _glfwPlatformInit(void)
|
||||
|
||||
createKeyTables();
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
// Need the default conf for when we set a NULL cursor
|
||||
_glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);
|
||||
_glfw.mir.eventQueue = calloc(1, sizeof(EventQueue));
|
||||
_glfwInitEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
_glfw.mir.event_queue = calloc(1, sizeof(EventQueue));
|
||||
_glfwInitEventQueueMir(_glfw.mir.event_queue);
|
||||
|
||||
error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
|
||||
error = pthread_mutex_init(&_glfw.mir.eventMutex, NULL);
|
||||
if (error)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -206,6 +207,7 @@ int _glfwPlatformInit(void)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfwPollMonitorsMir();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -213,11 +215,10 @@ void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
_glfwDeleteEventQueueMir(_glfw.mir.event_queue);
|
||||
_glfwDeleteEventQueueMir(_glfw.mir.eventQueue);
|
||||
|
||||
pthread_mutex_destroy(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_destroy(&_glfw.mir.eventMutex);
|
||||
|
||||
mir_connection_release(_glfw.mir.connection);
|
||||
}
|
||||
@@ -230,9 +231,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
+73
-50
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Mir - www.glfw.org
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -30,53 +30,55 @@
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsMir(void)
|
||||
{
|
||||
int i, found = 0;
|
||||
_GLFWmonitor** monitors = NULL;
|
||||
MirDisplayConfiguration* displayConfig =
|
||||
mir_connection_create_display_config(_glfw.mir.connection);
|
||||
int i;
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
*count = 0;
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < displayConfig->num_outputs; i++)
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirDisplayOutput* out = displayConfig->outputs + i;
|
||||
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||
MirOutputConnectionState state = mir_output_get_connection_state(output);
|
||||
bool enabled = mir_output_is_enabled(output);
|
||||
|
||||
if (out->used &&
|
||||
out->connected &&
|
||||
out->num_modes &&
|
||||
out->current_mode < out->num_modes)
|
||||
if (enabled && state == mir_output_connection_state_connected)
|
||||
{
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[i] = _glfwAllocMonitor("Unknown",
|
||||
out->physical_width_mm,
|
||||
out->physical_height_mm);
|
||||
int widthMM = mir_output_get_physical_width_mm(output);
|
||||
int heightMM = mir_output_get_physical_height_mm(output);
|
||||
int x = mir_output_get_position_x(output);
|
||||
int y = mir_output_get_position_y(output);
|
||||
int id = mir_output_get_id(output);
|
||||
size_t currentMode = mir_output_get_current_mode_index(output);
|
||||
const char* name = mir_output_type_name(mir_output_get_type(output));
|
||||
|
||||
monitors[i]->mir.x = out->position_x;
|
||||
monitors[i]->mir.y = out->position_y;
|
||||
monitors[i]->mir.output_id = out->output_id;
|
||||
monitors[i]->mir.cur_mode = out->current_mode;
|
||||
_GLFWmonitor* monitor = _glfwAllocMonitor(name,
|
||||
widthMM,
|
||||
heightMM);
|
||||
monitor->mir.x = x;
|
||||
monitor->mir.y = y;
|
||||
monitor->mir.outputId = id;
|
||||
monitor->mir.curMode = currentMode;
|
||||
monitor->modes = _glfwPlatformGetVideoModes(monitor, &monitor->modeCount);
|
||||
|
||||
monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
|
||||
&monitors[i]->modeCount);
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||
}
|
||||
}
|
||||
|
||||
mir_display_config_destroy(displayConfig);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
mir_display_config_release(displayConfig);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
return first->mir.output_id == second->mir.output_id;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
@@ -86,7 +88,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
*ypos = monitor->mir.y;
|
||||
}
|
||||
|
||||
void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
|
||||
static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
|
||||
{
|
||||
switch (pf)
|
||||
{
|
||||
@@ -123,37 +125,59 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
int i;
|
||||
GLFWvidmode* modes = NULL;
|
||||
MirDisplayConfiguration* displayConfig =
|
||||
mir_connection_create_display_config(_glfw.mir.connection);
|
||||
MirDisplayConfig* displayConfig =
|
||||
mir_connection_create_display_configuration(_glfw.mir.connection);
|
||||
|
||||
for (i = 0; i < displayConfig->num_outputs; i++)
|
||||
int numOutputs = mir_display_config_get_num_outputs(displayConfig);
|
||||
|
||||
for (i = 0; i < numOutputs; i++)
|
||||
{
|
||||
const MirDisplayOutput* out = displayConfig->outputs + i;
|
||||
if (out->output_id != monitor->mir.output_id)
|
||||
const MirOutput* output = mir_display_config_get_output(displayConfig, i);
|
||||
int id = mir_output_get_id(output);
|
||||
|
||||
if (id != monitor->mir.outputId)
|
||||
continue;
|
||||
|
||||
modes = calloc(out->num_modes, sizeof(GLFWvidmode));
|
||||
MirOutputConnectionState state = mir_output_get_connection_state(output);
|
||||
bool enabled = mir_output_is_enabled(output);
|
||||
|
||||
for (*found = 0; *found < out->num_modes; (*found)++)
|
||||
// We must have been disconnected
|
||||
if (!enabled || state != mir_output_connection_state_connected)
|
||||
{
|
||||
modes[*found].width = out->modes[*found].horizontal_resolution;
|
||||
modes[*found].height = out->modes[*found].vertical_resolution;
|
||||
modes[*found].refreshRate = out->modes[*found].refresh_rate;
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Monitor no longer connected");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
|
||||
int numModes = mir_output_get_num_modes(output);
|
||||
modes = calloc(numModes, sizeof(GLFWvidmode));
|
||||
|
||||
for (*found = 0; *found < numModes; (*found)++)
|
||||
{
|
||||
const MirOutputMode* mode = mir_output_get_mode(output, *found);
|
||||
int width = mir_output_mode_get_width(mode);
|
||||
int height = mir_output_mode_get_height(mode);
|
||||
double refreshRate = mir_output_mode_get_refresh_rate(mode);
|
||||
MirPixelFormat currentFormat = mir_output_get_current_pixel_format(output);
|
||||
|
||||
modes[*found].width = width;
|
||||
modes[*found].height = height;
|
||||
modes[*found].refreshRate = refreshRate;
|
||||
|
||||
FillInRGBBitsFromPixelFormat(&modes[*found], currentFormat);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mir_display_config_destroy(displayConfig);
|
||||
mir_display_config_release(displayConfig);
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
*mode = monitor->modes[monitor->mir.cur_mode];
|
||||
*mode = monitor->modes[monitor->mir.curMode];
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
@@ -177,6 +201,5 @@ GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return monitor->mir.output_id;
|
||||
return monitor->mir.outputId;
|
||||
}
|
||||
|
||||
|
||||
+27
-27
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Mir - www.glfw.org
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,40 +24,38 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_mir_platform_h_
|
||||
#define _glfw3_mir_platform_h_
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <pthread.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <mir_toolkit/mir_client_library.h>
|
||||
|
||||
typedef VkFlags VkMirSurfaceCreateFlagsKHR;
|
||||
typedef VkFlags VkMirWindowCreateFlagsKHR;
|
||||
|
||||
typedef struct VkMirSurfaceCreateInfoKHR
|
||||
typedef struct VkMirWindowCreateInfoKHR
|
||||
{
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkMirSurfaceCreateFlagsKHR flags;
|
||||
VkMirWindowCreateFlagsKHR flags;
|
||||
MirConnection* connection;
|
||||
MirSurface* mirSurface;
|
||||
} VkMirSurfaceCreateInfoKHR;
|
||||
MirWindow* mirWindow;
|
||||
} VkMirWindowCreateInfoKHR;
|
||||
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkResult (APIENTRY *PFN_vkCreateMirWindowKHR)(VkInstance,const VkMirWindowCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
|
||||
|
||||
#include "posix_tls.h"
|
||||
#include "posix_thread.h"
|
||||
#include "posix_time.h"
|
||||
#include "linux_joystick.h"
|
||||
#include "xkb_unicode.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.window)
|
||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.nativeWindow)
|
||||
#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
|
||||
@@ -80,54 +78,56 @@ typedef struct EventQueue
|
||||
//
|
||||
typedef struct _GLFWwindowMir
|
||||
{
|
||||
MirSurface* surface;
|
||||
MirWindow* window;
|
||||
int width;
|
||||
int height;
|
||||
MirEGLNativeWindowType window;
|
||||
MirEGLNativeWindowType nativeWindow;
|
||||
_GLFWcursor* currentCursor;
|
||||
|
||||
} _GLFWwindowMir;
|
||||
|
||||
|
||||
// Mir-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorMir
|
||||
{
|
||||
int cur_mode;
|
||||
int output_id;
|
||||
int curMode;
|
||||
int outputId;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
} _GLFWmonitorMir;
|
||||
|
||||
|
||||
// Mir-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryMir
|
||||
{
|
||||
MirConnection* connection;
|
||||
MirEGLNativeDisplayType display;
|
||||
MirCursorConfiguration* default_conf;
|
||||
EventQueue* event_queue;
|
||||
EventQueue* eventQueue;
|
||||
|
||||
short int publicKeys[256];
|
||||
short int keycodes[256];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
|
||||
pthread_mutex_t event_mutex;
|
||||
pthread_cond_t event_cond;
|
||||
pthread_mutex_t eventMutex;
|
||||
pthread_cond_t eventCond;
|
||||
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
|
||||
} _GLFWlibraryMir;
|
||||
|
||||
|
||||
// Mir-specific per-cursor data
|
||||
// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
|
||||
//
|
||||
typedef struct _GLFWcursorMir
|
||||
{
|
||||
MirCursorConfiguration* conf;
|
||||
MirBufferStream* custom_cursor;
|
||||
MirBufferStream* customCursor;
|
||||
char const* cursorName; // only needed for system cursors
|
||||
} _GLFWcursorMir;
|
||||
|
||||
|
||||
extern void _glfwPollMonitorsMir(void);
|
||||
extern void _glfwInitEventQueueMir(EventQueue* queue);
|
||||
extern void _glfwDeleteEventQueueMir(EventQueue* queue);
|
||||
|
||||
#endif // _glfw3_mir_platform_h_
|
||||
|
||||
+265
-169
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Mir - www.glfw.org
|
||||
// GLFW 3.3 Mir - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
// Copyright (c) 2014-2017 Brandon Schaefer <brandon.schaefer@canonical.com>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -54,44 +54,41 @@ static GLFWbool emptyEventQueue(EventQueue* queue)
|
||||
// for single threaded event handling.
|
||||
static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
|
||||
{
|
||||
EventNode* new_node = calloc(1, sizeof(EventNode));
|
||||
new_node->event = mir_event_ref(event);
|
||||
new_node->window = context;
|
||||
EventNode* newNode = calloc(1, sizeof(EventNode));
|
||||
newNode->event = mir_event_ref(event);
|
||||
newNode->window = context;
|
||||
|
||||
return new_node;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
EventNode* new_node = newEventNode(event, context);
|
||||
TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
|
||||
EventNode* newNode = newEventNode(event, context);
|
||||
TAILQ_INSERT_TAIL(&_glfw.mir.eventQueue->head, newNode, entries);
|
||||
|
||||
pthread_cond_signal(&_glfw.mir.event_cond);
|
||||
pthread_cond_signal(&_glfw.mir.eventCond);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
}
|
||||
|
||||
static EventNode* dequeueEvent(EventQueue* queue)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
node = queue->head.tqh_first;
|
||||
|
||||
if (node)
|
||||
TAILQ_REMOVE(&queue->head, node, entries);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
|
||||
the best pixel format!
|
||||
*/
|
||||
static MirPixelFormat findValidPixelFormat(void)
|
||||
{
|
||||
unsigned int i, validFormats, mirPixelFormats = 32;
|
||||
@@ -132,8 +129,8 @@ static int mirModToGLFWMod(uint32_t mods)
|
||||
|
||||
static int toGLFWKeyCode(uint32_t key)
|
||||
{
|
||||
if (key < sizeof(_glfw.mir.publicKeys) / sizeof(_glfw.mir.publicKeys[0]))
|
||||
return _glfw.mir.publicKeys[key];
|
||||
if (key < sizeof(_glfw.mir.keycodes) / sizeof(_glfw.mir.keycodes[0]))
|
||||
return _glfw.mir.keycodes[key];
|
||||
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
}
|
||||
@@ -201,16 +198,31 @@ static void handlePointerButton(_GLFWwindow* window,
|
||||
static void handlePointerMotion(_GLFWwindow* window,
|
||||
const MirPointerEvent* pointer_event)
|
||||
{
|
||||
int current_x = window->virtualCursorPosX;
|
||||
int current_y = window->virtualCursorPosY;
|
||||
int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
|
||||
int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
|
||||
int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
|
||||
int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
|
||||
const int hscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
|
||||
const int vscroll = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
|
||||
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
if (dx != 0 || dy != 0)
|
||||
_glfwInputScroll(window, dx, dy);
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
if (_glfw.mir.disabledCursorWindow != window)
|
||||
return;
|
||||
|
||||
const int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_x);
|
||||
const int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_relative_y);
|
||||
const int current_x = window->virtualCursorPosX;
|
||||
const int current_y = window->virtualCursorPosY;
|
||||
|
||||
_glfwInputCursorPos(window, dx + current_x, dy + current_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
|
||||
const int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
|
||||
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
}
|
||||
|
||||
if (hscroll != 0 || vscroll != 0)
|
||||
_glfwInputScroll(window, hscroll, vscroll);
|
||||
}
|
||||
|
||||
static void handlePointerEvent(const MirPointerEvent* pointer_event,
|
||||
@@ -234,7 +246,6 @@ static void handlePointerEvent(const MirPointerEvent* pointer_event,
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,14 +280,14 @@ static void handleEvent(const MirEvent* event, _GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context)
|
||||
static void addNewEvent(MirWindow* window, const MirEvent* event, void* context)
|
||||
{
|
||||
enqueueEvent(event, context);
|
||||
}
|
||||
|
||||
static GLFWbool createSurface(_GLFWwindow* window)
|
||||
static GLFWbool createWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
|
||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||
|
||||
@@ -286,32 +297,42 @@ static GLFWbool createSurface(_GLFWwindow* window)
|
||||
"Mir: Unable to find a correct pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
|
||||
window->mir.width,
|
||||
window->mir.height,
|
||||
pixel_format);
|
||||
|
||||
mir_surface_spec_set_buffer_usage(spec, buffer_usage);
|
||||
mir_surface_spec_set_name(spec, "MirSurface");
|
||||
spec = mir_create_normal_window_spec(_glfw.mir.connection,
|
||||
window->mir.width,
|
||||
window->mir.height);
|
||||
|
||||
window->mir.surface = mir_surface_create_sync(spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_spec_set_pixel_format(spec, pixel_format);
|
||||
mir_window_spec_set_buffer_usage(spec, buffer_usage);
|
||||
|
||||
if (!mir_surface_is_valid(window->mir.surface))
|
||||
window->mir.window = mir_create_window_sync(spec);
|
||||
mir_window_spec_release(spec);
|
||||
|
||||
if (!mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to create surface: %s",
|
||||
mir_surface_get_error_message(window->mir.surface));
|
||||
"Mir: Unable to create window: %s",
|
||||
mir_window_get_error_message(window->mir.window));
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
|
||||
mir_window_set_event_handler(window->mir.window, addNewEvent, window);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
static void setWindowConfinement(_GLFWwindow* window, MirPointerConfinementState state)
|
||||
{
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_pointer_confinement(spec, state);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -356,12 +377,12 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
GLFWvidmode mode;
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
|
||||
mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen);
|
||||
mir_window_set_state(window->mir.window, mir_window_state_fullscreen);
|
||||
|
||||
if (wndconfig->width > mode.width || wndconfig->height > mode.height)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Requested surface size too large: %ix%i",
|
||||
"Mir: Requested window size too large: %ix%i",
|
||||
wndconfig->width, wndconfig->height);
|
||||
|
||||
return GLFW_FALSE;
|
||||
@@ -370,17 +391,31 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
|
||||
window->mir.width = wndconfig->width;
|
||||
window->mir.height = wndconfig->height;
|
||||
window->mir.currentCursor = NULL;
|
||||
|
||||
if (!createSurface(window))
|
||||
if (!createWindow(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
window->mir.window = mir_buffer_stream_get_egl_native_window(
|
||||
mir_surface_get_buffer_stream(window->mir.surface));
|
||||
window->mir.nativeWindow = mir_buffer_stream_get_egl_native_window(
|
||||
mir_window_get_buffer_stream(window->mir.window));
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
|
||||
ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
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;
|
||||
@@ -388,26 +423,27 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (mir_surface_is_valid(window->mir.surface))
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
|
||||
if (mir_window_is_valid(window->mir.window))
|
||||
{
|
||||
mir_surface_release_sync(window->mir.surface);
|
||||
window->mir.surface = NULL;
|
||||
mir_window_release_sync(window->mir.window);
|
||||
window->mir.window= NULL;
|
||||
}
|
||||
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
const char* e_title = title ? title : "";
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_name(spec, e_title);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_name(spec, title);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
@@ -419,22 +455,30 @@ void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_width (spec, width);
|
||||
mir_surface_spec_set_height(spec, height);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_width (spec, width);
|
||||
mir_window_spec_set_height(spec, height);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_max_width (spec, maxwidth);
|
||||
mir_window_spec_set_max_height(spec, maxheight);
|
||||
mir_window_spec_set_min_width (spec, minwidth);
|
||||
mir_window_spec_set_min_height(spec, minheight);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
||||
@@ -473,40 +517,63 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
mir_surface_set_state(window->mir.surface, mir_surface_state_minimized);
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_minimized);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
mir_surface_set_state(window->mir.surface, mir_surface_state_restored);
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_maximized);
|
||||
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_hidden);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_hidden);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
MirSurfaceSpec* spec;
|
||||
MirWindowSpec* spec;
|
||||
|
||||
spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
|
||||
mir_surface_spec_set_state(spec, mir_surface_state_restored);
|
||||
spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_state(spec, mir_window_state_restored);
|
||||
|
||||
mir_surface_apply_spec(window->mir.surface, spec);
|
||||
mir_surface_spec_release(spec);
|
||||
mir_window_apply_spec(window->mir.window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
@@ -515,6 +582,10 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformDragWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
@@ -527,9 +598,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return GLFW_FALSE;
|
||||
return mir_window_get_focus_state(window->mir.window) == mir_window_focus_state_focused;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
@@ -541,53 +610,69 @@ int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
|
||||
return mir_window_get_visibility(window->mir.window) == mir_window_visibility_exposed;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return mir_window_get_state(window->mir.window) == mir_window_state_maximized;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
EventNode* node = NULL;
|
||||
|
||||
while ((node = dequeueEvent(_glfw.mir.event_queue)))
|
||||
while ((node = dequeueEvent(_glfw.mir.eventQueue)))
|
||||
{
|
||||
handleEvent(node->event, node->window);
|
||||
deleteNode(_glfw.mir.event_queue, node);
|
||||
deleteNode(_glfw.mir.eventQueue, node);
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
if (emptyEventQueue(_glfw.mir.event_queue))
|
||||
pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
|
||||
while (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
pthread_cond_wait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex);
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
pthread_mutex_lock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_lock(&_glfw.mir.eventMutex);
|
||||
|
||||
if (emptyEventQueue(_glfw.mir.event_queue))
|
||||
if (emptyEventQueue(_glfw.mir.eventQueue))
|
||||
{
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_REALTIME, &time);
|
||||
time.tv_sec += (long) timeout;
|
||||
time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
|
||||
pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);
|
||||
pthread_cond_timedwait(&_glfw.mir.eventCond, &_glfw.mir.eventMutex, &time);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_glfw.mir.event_mutex);
|
||||
pthread_mutex_unlock(&_glfw.mir.eventMutex);
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
}
|
||||
@@ -604,60 +689,45 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
|
||||
*height = window->mir.height;
|
||||
}
|
||||
|
||||
// FIXME implement
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
MirBufferStream* stream;
|
||||
MirPixelFormat pixel_format = findValidPixelFormat();
|
||||
|
||||
int i_w = image->width;
|
||||
int i_h = image->height;
|
||||
|
||||
if (pixel_format == mir_pixel_format_invalid)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unable to find a correct pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
|
||||
i_w, i_h,
|
||||
pixel_format,
|
||||
mir_pixel_format_argb_8888,
|
||||
mir_buffer_usage_software);
|
||||
|
||||
cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
|
||||
|
||||
char* dest;
|
||||
unsigned char *pixels;
|
||||
int i, r_stride, bytes_per_pixel, bytes_per_row;
|
||||
|
||||
MirGraphicsRegion region;
|
||||
mir_buffer_stream_get_graphics_region(stream, ®ion);
|
||||
|
||||
// FIXME Figure this out based on the current_pf
|
||||
bytes_per_pixel = 4;
|
||||
bytes_per_row = bytes_per_pixel * i_w;
|
||||
unsigned char* pixels = image->pixels;
|
||||
char* dest = region.vaddr;
|
||||
int i;
|
||||
|
||||
dest = region.vaddr;
|
||||
pixels = image->pixels;
|
||||
|
||||
r_stride = region.stride;
|
||||
|
||||
for (i = 0; i < i_h; i++)
|
||||
for (i = 0; i < i_w * i_h; i++, pixels += 4)
|
||||
{
|
||||
memcpy(dest, pixels, bytes_per_row);
|
||||
dest += r_stride;
|
||||
pixels += r_stride;
|
||||
unsigned int alpha = pixels[3];
|
||||
*dest++ = (char)(pixels[2] * alpha / 255);
|
||||
*dest++ = (char)(pixels[1] * alpha / 255);
|
||||
*dest++ = (char)(pixels[0] * alpha / 255);
|
||||
*dest++ = (char)alpha;
|
||||
}
|
||||
|
||||
cursor->mir.custom_cursor = stream;
|
||||
mir_buffer_stream_swap_buffers_sync(stream);
|
||||
cursor->mir.customCursor = stream;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
const char* getSystemCursorName(int shape)
|
||||
static const char* getSystemCursorName(int shape)
|
||||
{
|
||||
switch (shape)
|
||||
{
|
||||
@@ -680,40 +750,47 @@ const char* getSystemCursorName(int shape)
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
const char* cursor_name = getSystemCursorName(shape);
|
||||
cursor->mir.conf = NULL;
|
||||
cursor->mir.customCursor = NULL;
|
||||
cursor->mir.cursorName = getSystemCursorName(shape);
|
||||
|
||||
if (cursor_name)
|
||||
{
|
||||
cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
|
||||
cursor->mir.custom_cursor = NULL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return cursor->mir.cursorName != NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
{
|
||||
if (cursor->mir.conf)
|
||||
mir_cursor_configuration_destroy(cursor->mir.conf);
|
||||
if (cursor->mir.custom_cursor)
|
||||
mir_buffer_stream_release_sync(cursor->mir.custom_cursor);
|
||||
if (cursor->mir.customCursor)
|
||||
mir_buffer_stream_release_sync(cursor->mir.customCursor);
|
||||
}
|
||||
|
||||
static void setCursorNameForWindow(MirWindow* window, char const* name)
|
||||
{
|
||||
MirWindowSpec* spec = mir_create_window_spec(_glfw.mir.connection);
|
||||
mir_window_spec_set_cursor_name(spec, name);
|
||||
mir_window_apply_spec(window, spec);
|
||||
mir_window_spec_release(spec);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
if (cursor && cursor->mir.conf)
|
||||
if (cursor)
|
||||
{
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
|
||||
if (cursor->mir.custom_cursor)
|
||||
window->mir.currentCursor = cursor;
|
||||
|
||||
if (cursor->mir.cursorName)
|
||||
{
|
||||
mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
|
||||
setCursorNameForWindow(window->mir.window, cursor->mir.cursorName);
|
||||
}
|
||||
else if (cursor->mir.conf)
|
||||
{
|
||||
mir_window_configure_cursor(window->mir.window, cursor->mir.conf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));
|
||||
setCursorNameForWindow(window->mir.window, mir_default_cursor_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,17 +808,44 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = window;
|
||||
setWindowConfinement(window, mir_pointer_confined_to_window);
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we were disabled before lets undo that!
|
||||
if (_glfw.mir.disabledCursorWindow == window)
|
||||
{
|
||||
_glfw.mir.disabledCursorWindow = NULL;
|
||||
setWindowConfinement(window, mir_pointer_unconfined);
|
||||
}
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||
{
|
||||
_glfwPlatformSetCursor(window, window->mir.currentCursor);
|
||||
}
|
||||
else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
{
|
||||
setCursorNameForWindow(window->mir.window, mir_disabled_cursor_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return _glfw.mir.scancodes[key];
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -756,21 +860,13 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
char** extensions;
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_mir_surface)
|
||||
return;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_mir_surface)
|
||||
return NULL;
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
extensions[1] = strdup("VK_KHR_mir_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
extensions[0] = "VK_KHR_surface";
|
||||
extensions[1] = "VK_KHR_mir_surface";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
@@ -798,12 +894,12 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
VkResult err;
|
||||
VkMirSurfaceCreateInfoKHR sci;
|
||||
PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
|
||||
VkMirWindowCreateInfoKHR sci;
|
||||
PFN_vkCreateMirWindowKHR vkCreateMirWindowKHR;
|
||||
|
||||
vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
|
||||
if (!vkCreateMirSurfaceKHR)
|
||||
vkCreateMirWindowKHR = (PFN_vkCreateMirWindowKHR)
|
||||
vkGetInstanceProcAddr(instance, "vkCreateMirWindowKHR");
|
||||
if (!vkCreateMirWindowKHR)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Mir: Vulkan instance missing VK_KHR_mir_surface extension");
|
||||
@@ -813,9 +909,9 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
memset(&sci, 0, sizeof(sci));
|
||||
sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
|
||||
sci.connection = _glfw.mir.connection;
|
||||
sci.mirSurface = window->mir.surface;
|
||||
sci.mirWindow = window->mir.window;
|
||||
|
||||
err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
|
||||
err = vkCreateMirWindowKHR(instance, &sci, allocator, surface);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
@@ -837,10 +933,10 @@ GLFWAPI MirConnection* glfwGetMirDisplay(void)
|
||||
return _glfw.mir.connection;
|
||||
}
|
||||
|
||||
GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)
|
||||
GLFWAPI MirWindow* glfwGetMirWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return window->mir.surface;
|
||||
return window->mir.window;
|
||||
}
|
||||
|
||||
|
||||
+42
-78
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -86,83 +86,49 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
||||
////// GLFW event API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInputMonitorChange(void)
|
||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
||||
{
|
||||
int i, j, monitorCount = _glfw.monitorCount;
|
||||
_GLFWmonitor** monitors = _glfw.monitors;
|
||||
|
||||
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
|
||||
|
||||
// Re-use still connected monitor objects
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
if (action == GLFW_CONNECTED)
|
||||
{
|
||||
for (j = 0; j < monitorCount; j++)
|
||||
_glfw.monitorCount++;
|
||||
_glfw.monitors =
|
||||
realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
|
||||
|
||||
if (placement == _GLFW_INSERT_FIRST)
|
||||
{
|
||||
if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
|
||||
memmove(_glfw.monitors + 1,
|
||||
_glfw.monitors,
|
||||
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||
_glfw.monitors[0] = monitor;
|
||||
}
|
||||
else
|
||||
_glfw.monitors[_glfw.monitorCount - 1] = monitor;
|
||||
}
|
||||
else if (action == GLFW_DISCONNECTED)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
if (_glfw.monitors[i] == monitor)
|
||||
{
|
||||
_glfwFreeMonitor(_glfw.monitors[i]);
|
||||
_glfw.monitors[i] = monitors[j];
|
||||
_glfw.monitorCount--;
|
||||
memmove(_glfw.monitors + i,
|
||||
_glfw.monitors + i + 1,
|
||||
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find and report disconnected monitors (not in the new list)
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
|
||||
|
||||
for (i = 0; i < monitorCount; i++)
|
||||
{
|
||||
_GLFWwindow* window;
|
||||
|
||||
for (j = 0; j < _glfw.monitorCount; j++)
|
||||
{
|
||||
if (monitors[i] == _glfw.monitors[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if (j < _glfw.monitorCount)
|
||||
continue;
|
||||
|
||||
for (window = _glfw.windowListHead; window; window = window->next)
|
||||
{
|
||||
if (window->monitor == monitors[i])
|
||||
{
|
||||
int width, height;
|
||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// Find and report newly connected monitors (not in the old list)
|
||||
// Re-used monitor objects are then removed from the old list to avoid
|
||||
// having them destroyed at the end of this function
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
{
|
||||
for (j = 0; j < monitorCount; j++)
|
||||
{
|
||||
if (_glfw.monitors[i] == monitors[j])
|
||||
{
|
||||
monitors[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < monitorCount)
|
||||
continue;
|
||||
|
||||
if (_glfw.callbacks.monitor)
|
||||
_glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
|
||||
}
|
||||
|
||||
_glfwFreeMonitors(monitors, monitorCount);
|
||||
if (action == GLFW_DISCONNECTED)
|
||||
_glfwFreeMonitor(monitor);
|
||||
}
|
||||
|
||||
void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
{
|
||||
monitor->window = window;
|
||||
}
|
||||
@@ -175,10 +141,12 @@ void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
|
||||
_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
|
||||
{
|
||||
_GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
|
||||
monitor->name = strdup(name);
|
||||
monitor->widthMM = widthMM;
|
||||
monitor->heightMM = heightMM;
|
||||
|
||||
if (name)
|
||||
monitor->name = strdup(name);
|
||||
|
||||
return monitor;
|
||||
}
|
||||
|
||||
@@ -212,16 +180,6 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
|
||||
memset(ramp, 0, sizeof(GLFWgammaramp));
|
||||
}
|
||||
|
||||
void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
_glfwFreeMonitor(monitors[i]);
|
||||
|
||||
free(monitors);
|
||||
}
|
||||
|
||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||
const GLFWvidmode* desired)
|
||||
{
|
||||
@@ -304,6 +262,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
|
||||
GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
@@ -404,6 +363,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||
int i;
|
||||
unsigned short values[256];
|
||||
GLFWgammaramp ramp;
|
||||
assert(handle != NULL);
|
||||
assert(gamma == gamma);
|
||||
assert(gamma >= 0.f);
|
||||
assert(gamma <= FLT_MAX);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -455,6 +418,7 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
assert(monitor != NULL);
|
||||
assert(ramp != NULL);
|
||||
assert(ramp->size > 0);
|
||||
assert(ramp->red != NULL);
|
||||
assert(ramp->green != NULL);
|
||||
assert(ramp->blue != NULL);
|
||||
|
||||
+2
-7
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,9 +24,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_nsgl_context_h_
|
||||
#define _glfw3_nsgl_context_h_
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
||||
|
||||
@@ -40,7 +37,6 @@ typedef struct _GLFWcontextNSGL
|
||||
|
||||
} _GLFWcontextNSGL;
|
||||
|
||||
|
||||
// NSGL-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryNSGL
|
||||
@@ -58,4 +54,3 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||
|
||||
#endif // _glfw3_nsgl_context_h_
|
||||
|
||||
+81
-57
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 OS X - www.glfw.org
|
||||
// GLFW 3.3 macOS - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -27,38 +27,38 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static void makeContextCurrent(_GLFWwindow* window)
|
||||
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
[window->context.nsgl.object makeCurrentContext];
|
||||
else
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static void swapBuffers(_GLFWwindow* window)
|
||||
static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
{
|
||||
// ARP appears to be unnecessary, but this is future-proof
|
||||
[window->context.nsgl.object flushBuffer];
|
||||
}
|
||||
|
||||
static void swapInterval(int interval)
|
||||
static void swapIntervalNSGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
GLint sync = interval;
|
||||
[window->context.nsgl.object setValues:&sync
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
|
||||
static int extensionSupported(const char* extension)
|
||||
static int extensionSupportedNSGL(const char* extension)
|
||||
{
|
||||
// There are no NSGL extensions
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddress(const char* procname)
|
||||
static GLFWglproc getProcAddressNSGL(const char* procname)
|
||||
{
|
||||
CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
|
||||
procname,
|
||||
@@ -74,7 +74,7 @@ static GLFWglproc getProcAddress(const char* procname)
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContext(_GLFWwindow* window)
|
||||
static void destroyContextNSGL(_GLFWwindow* window)
|
||||
{
|
||||
[window->context.nsgl.pixelFormat release];
|
||||
window->context.nsgl.pixelFormat = nil;
|
||||
@@ -92,6 +92,9 @@ static void destroyContext(_GLFWwindow* window)
|
||||
//
|
||||
GLFWbool _glfwInitNSGL(void)
|
||||
{
|
||||
if (_glfw.nsgl.framework)
|
||||
return GLFW_TRUE;
|
||||
|
||||
_glfw.nsgl.framework =
|
||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (_glfw.nsgl.framework == NULL)
|
||||
@@ -116,70 +119,83 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
unsigned int attributeCount = 0;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"NSGL: OpenGL ES is not available on OS X");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");
|
||||
"NSGL: OpenGL ES is not available on macOS");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->major > 2)
|
||||
{
|
||||
if (!ctxconfig->forward)
|
||||
if (ctxconfig->major == 3 && ctxconfig->minor < 2)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");
|
||||
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
||||
if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");
|
||||
"NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Context robustness modes (GL_KHR_robustness) are not yet supported on
|
||||
// OS X but are not a hard constraint, so ignore and continue
|
||||
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
||||
// macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
// Context release behaviors (GL_KHR_context_flush_control) are not yet
|
||||
// supported on OS X but are not a hard constraint, so ignore and continue
|
||||
// supported by macOS but are not a hard constraint, so ignore and continue
|
||||
|
||||
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
|
||||
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
|
||||
// Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
|
||||
// a hard constraint, so ignore and continue
|
||||
|
||||
// Arbitrary array size here
|
||||
NSOpenGLPixelFormatAttribute attributes[40];
|
||||
// No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
|
||||
// are not a hard constraint, so ignore and continue
|
||||
|
||||
ADD_ATTR(NSOpenGLPFAAccelerated);
|
||||
ADD_ATTR(NSOpenGLPFAClosestPolicy);
|
||||
#define addAttrib(a) \
|
||||
{ \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
}
|
||||
#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
|
||||
|
||||
NSOpenGLPixelFormatAttribute attribs[40];
|
||||
int index = 0;
|
||||
|
||||
addAttrib(NSOpenGLPFAAccelerated);
|
||||
addAttrib(NSOpenGLPFAClosestPolicy);
|
||||
|
||||
if (ctxconfig->nsgl.offline)
|
||||
{
|
||||
addAttrib(NSOpenGLPFAAllowOfflineRenderers);
|
||||
// NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
|
||||
// Info.plist for unbundled applications
|
||||
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||
// a straightforward wrapper of its CGL counterpart
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
|
||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
if (ctxconfig->major >= 4)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
|
||||
}
|
||||
else
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
if (ctxconfig->major >= 3)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
|
||||
}
|
||||
|
||||
if (ctxconfig->major <= 2)
|
||||
{
|
||||
if (fbconfig->auxBuffers != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
|
||||
|
||||
if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
|
||||
fbconfig->accumGreenBits != GLFW_DONT_CARE &&
|
||||
@@ -191,7 +207,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
fbconfig->accumBlueBits +
|
||||
fbconfig->accumAlphaBits;
|
||||
|
||||
ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
|
||||
setAttrib(NSOpenGLPFAAccumSize, accumBits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,53 +219,61 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
fbconfig->greenBits +
|
||||
fbconfig->blueBits;
|
||||
|
||||
// OS X needs non-zero color size, so set reasonable values
|
||||
// macOS needs non-zero color size, so set reasonable values
|
||||
if (colorBits == 0)
|
||||
colorBits = 24;
|
||||
else if (colorBits < 15)
|
||||
colorBits = 15;
|
||||
|
||||
ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
|
||||
setAttrib(NSOpenGLPFAColorSize, colorBits);
|
||||
}
|
||||
|
||||
if (fbconfig->alphaBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
|
||||
|
||||
if (fbconfig->depthBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
|
||||
|
||||
if (fbconfig->stencilBits != GLFW_DONT_CARE)
|
||||
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
|
||||
|
||||
if (fbconfig->stereo)
|
||||
ADD_ATTR(NSOpenGLPFAStereo);
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"NSGL: Stereo rendering is deprecated");
|
||||
return GLFW_FALSE;
|
||||
#else
|
||||
addAttrib(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fbconfig->doublebuffer)
|
||||
ADD_ATTR(NSOpenGLPFADoubleBuffer);
|
||||
addAttrib(NSOpenGLPFADoubleBuffer);
|
||||
|
||||
if (fbconfig->samples != GLFW_DONT_CARE)
|
||||
{
|
||||
if (fbconfig->samples == 0)
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
|
||||
ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
|
||||
setAttrib(NSOpenGLPFASampleBuffers, 1);
|
||||
setAttrib(NSOpenGLPFASamples, fbconfig->samples);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
|
||||
// framebuffer, so there's no need (and no way) to request it
|
||||
|
||||
ADD_ATTR(0);
|
||||
addAttrib(0);
|
||||
|
||||
#undef ADD_ATTR
|
||||
#undef ADD_ATTR2
|
||||
#undef addAttrib
|
||||
#undef setAttrib
|
||||
|
||||
window->context.nsgl.pixelFormat =
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||
[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||
if (window->context.nsgl.pixelFormat == nil)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
@@ -274,12 +298,12 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
|
||||
[window->context.nsgl.object setView:window->ns.view];
|
||||
|
||||
window->context.makeCurrent = makeContextCurrent;
|
||||
window->context.swapBuffers = swapBuffers;
|
||||
window->context.swapInterval = swapInterval;
|
||||
window->context.extensionSupported = extensionSupported;
|
||||
window->context.getProcAddress = getProcAddress;
|
||||
window->context.destroy = destroyContext;
|
||||
window->context.makeCurrent = makeContextCurrentNSGL;
|
||||
window->context.swapBuffers = swapBuffersNSGL;
|
||||
window->context.swapInterval = swapIntervalNSGL;
|
||||
window->context.extensionSupported = extensionSupportedNSGL;
|
||||
window->context.getProcAddress = getProcAddressNSGL;
|
||||
window->context.destroy = destroyContextNSGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 POSIX - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -28,41 +28,23 @@
|
||||
#include "internal.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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
pthread_setspecific(_glfw.posix_tls.context, context);
|
||||
_glfwInitTimerPOSIX();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
return pthread_getspecific(_glfw.posix_tls.context);
|
||||
_glfwTerminateOSMesa();
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " null OSMesa";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
|
||||
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME ""
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -28,42 +28,28 @@
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStorageWin32(void)
|
||||
{
|
||||
_glfw.win32_tls.context = TlsAlloc();
|
||||
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
|
||||
{
|
||||
_glfwInputError(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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
TlsSetValue(_glfw.win32_tls.context, context);
|
||||
}
|
||||
|
||||
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
return TlsGetValue(_glfw.win32_tls.context);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
|
||||
|
||||
#define _GLFW_PLATFORM_CONTEXT_STATE
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE
|
||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||
#define _GLFW_EGL_CONTEXT_STATE
|
||||
#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
|
||||
|
||||
#include "osmesa_context.h"
|
||||
#include "posix_time.h"
|
||||
#include "posix_thread.h"
|
||||
#include "null_joystick.h"
|
||||
|
||||
#if defined(_GLFW_WIN32)
|
||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
||||
#else
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
#define _glfw_dlsym(handle, name) dlsym(handle, name)
|
||||
#endif
|
||||
|
||||
// Null-specific per-window data
|
||||
//
|
||||
typedef struct _GLFWwindowNull
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
} _GLFWwindowNull;
|
||||
|
||||
@@ -0,0 +1,297 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static int createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API ||
|
||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
|
||||
const GLFWimage* images)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
int width, int height,
|
||||
int refreshRate)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->null.width;
|
||||
if (height)
|
||||
*height = window->null.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
window->null.width = width;
|
||||
window->null.height = height;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int minwidth, int minheight,
|
||||
int maxwidth, int maxheight)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
||||
{
|
||||
if (width)
|
||||
*width = window->null.width;
|
||||
if (height)
|
||||
*height = window->null.height;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformDragWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEvents(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
_GLFWwindow* window,
|
||||
const VkAllocationCallbacks* allocator,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
// This seems like the most appropriate error to return here
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
int width, height;
|
||||
_glfwPlatformGetFramebufferSize(window, &width, &height);
|
||||
|
||||
// Check to see if we need to allocate a new buffer
|
||||
if ((window->context.osmesa.buffer == NULL) ||
|
||||
(width != window->context.osmesa.width) ||
|
||||
(height != window->context.osmesa.height))
|
||||
{
|
||||
free(window->context.osmesa.buffer);
|
||||
|
||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||
window->context.osmesa.buffer = calloc(4, width * height);
|
||||
window->context.osmesa.width = width;
|
||||
window->context.osmesa.height = height;
|
||||
}
|
||||
|
||||
if (!OSMesaMakeCurrent(window->context.osmesa.handle,
|
||||
window->context.osmesa.buffer,
|
||||
GL_UNSIGNED_BYTE,
|
||||
width, height))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to make context current");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressOSMesa(const char* procname)
|
||||
{
|
||||
return (GLFWglproc) OSMesaGetProcAddress(procname);
|
||||
}
|
||||
|
||||
static void destroyContextOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.osmesa.handle)
|
||||
{
|
||||
OSMesaDestroyContext(window->context.osmesa.handle);
|
||||
window->context.osmesa.handle = NULL;
|
||||
}
|
||||
|
||||
if (window->context.osmesa.buffer)
|
||||
{
|
||||
free(window->context.osmesa.buffer);
|
||||
window->context.osmesa.width = 0;
|
||||
window->context.osmesa.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffersOSMesa(_GLFWwindow* window)
|
||||
{
|
||||
// No double buffering on OSMesa
|
||||
}
|
||||
|
||||
static void swapIntervalOSMesa(int interval)
|
||||
{
|
||||
// No swap interval on OSMesa
|
||||
}
|
||||
|
||||
static int extensionSupportedOSMesa(const char* extension)
|
||||
{
|
||||
// OSMesa does not have extensions
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void)
|
||||
{
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
"libOSMesa.dll",
|
||||
"OSMesa.dll",
|
||||
#elif defined(__APPLE__)
|
||||
"libOSMesa.8.dylib",
|
||||
#elif defined(__CYGWIN__)
|
||||
"libOSMesa-8.so",
|
||||
#else
|
||||
"libOSMesa.so.8",
|
||||
"libOSMesa.so.6",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
if (_glfw.osmesa.handle)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
_glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
|
||||
if (_glfw.osmesa.handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_glfw.osmesa.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
|
||||
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
||||
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
||||
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
||||
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
||||
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
||||
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
|
||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
||||
|
||||
if (!_glfw.osmesa.CreateContextExt ||
|
||||
!_glfw.osmesa.DestroyContext ||
|
||||
!_glfw.osmesa.MakeCurrent ||
|
||||
!_glfw.osmesa.GetColorBuffer ||
|
||||
!_glfw.osmesa.GetDepthBuffer ||
|
||||
!_glfw.osmesa.GetProcAddress)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to load required entry points");
|
||||
|
||||
_glfwTerminateOSMesa();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwTerminateOSMesa(void)
|
||||
{
|
||||
if (_glfw.osmesa.handle)
|
||||
{
|
||||
_glfw_dlclose(_glfw.osmesa.handle);
|
||||
_glfw.osmesa.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
OSMesaContext share = NULL;
|
||||
const int accumBits = fbconfig->accumRedBits +
|
||||
fbconfig->accumGreenBits +
|
||||
fbconfig->accumBlueBits +
|
||||
fbconfig->accumAlphaBits;
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"OSMesa: OpenGL ES is not available on OSMesa");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.osmesa.handle;
|
||||
|
||||
if (OSMesaCreateContextAttribs)
|
||||
{
|
||||
int index = 0, attribs[40];
|
||||
|
||||
setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
|
||||
setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
|
||||
setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
|
||||
setAttrib(OSMESA_ACCUM_BITS, accumBits);
|
||||
|
||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
|
||||
}
|
||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||
{
|
||||
setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
|
||||
setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (ctxconfig->forward)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Foward-compatible contexts not supported");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
setAttrib(0, 0);
|
||||
|
||||
window->context.osmesa.handle =
|
||||
OSMesaCreateContextAttribs(attribs, share);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->profile)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: OpenGL profiles unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.osmesa.handle =
|
||||
OSMesaCreateContextExt(OSMESA_RGBA,
|
||||
fbconfig->depthBits,
|
||||
fbconfig->stencilBits,
|
||||
accumBits,
|
||||
share);
|
||||
}
|
||||
|
||||
if (window->context.osmesa.handle == NULL)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Failed to create context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||
window->context.swapBuffers = swapBuffersOSMesa;
|
||||
window->context.swapInterval = swapIntervalOSMesa;
|
||||
window->context.extensionSupported = extensionSupportedOSMesa;
|
||||
window->context.getProcAddress = getProcAddressOSMesa;
|
||||
window->context.destroy = destroyContextOSMesa;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW native API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||
int* height, int* format, void** buffer)
|
||||
{
|
||||
void* mesaBuffer;
|
||||
GLint mesaWidth, mesaHeight, mesaFormat;
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
&mesaFormat, &mesaBuffer))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve color buffer");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = mesaWidth;
|
||||
if (height)
|
||||
*height = mesaHeight;
|
||||
if (format)
|
||||
*format = mesaFormat;
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
int* width, int* height,
|
||||
int* bytesPerValue,
|
||||
void** buffer)
|
||||
{
|
||||
void* mesaBuffer;
|
||||
GLint mesaWidth, mesaHeight, mesaBytes;
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
&mesaBytes, &mesaBuffer))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve depth buffer");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = mesaWidth;
|
||||
if (height)
|
||||
*height = mesaHeight;
|
||||
if (bytesPerValue)
|
||||
*bytesPerValue = mesaBytes;
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (window->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return window->context.osmesa.handle;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 OSMesa - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#define OSMESA_RGBA 0x1908
|
||||
#define OSMESA_FORMAT 0x22
|
||||
#define OSMESA_DEPTH_BITS 0x30
|
||||
#define OSMESA_STENCIL_BITS 0x31
|
||||
#define OSMESA_ACCUM_BITS 0x32
|
||||
#define OSMESA_PROFILE 0x33
|
||||
#define OSMESA_CORE_PROFILE 0x34
|
||||
#define OSMESA_COMPAT_PROFILE 0x35
|
||||
#define OSMESA_CONTEXT_MAJOR_VERSION 0x36
|
||||
#define OSMESA_CONTEXT_MINOR_VERSION 0x37
|
||||
|
||||
typedef void* OSMesaContext;
|
||||
typedef void (*OSMESAproc)();
|
||||
|
||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext);
|
||||
typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext);
|
||||
typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext);
|
||||
typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int);
|
||||
typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**);
|
||||
typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**);
|
||||
typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*);
|
||||
#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt
|
||||
#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs
|
||||
#define OSMesaDestroyContext _glfw.osmesa.DestroyContext
|
||||
#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent
|
||||
#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer
|
||||
#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer
|
||||
#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress
|
||||
|
||||
#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa
|
||||
#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa
|
||||
|
||||
|
||||
// OSMesa-specific per-context data
|
||||
//
|
||||
typedef struct _GLFWcontextOSMesa
|
||||
{
|
||||
OSMesaContext handle;
|
||||
int width;
|
||||
int height;
|
||||
void* buffer;
|
||||
|
||||
} _GLFWcontextOSMesa;
|
||||
|
||||
// OSMesa-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryOSMesa
|
||||
{
|
||||
void* handle;
|
||||
|
||||
PFN_OSMesaCreateContextExt CreateContextExt;
|
||||
PFN_OSMesaCreateContextAttribs CreateContextAttribs;
|
||||
PFN_OSMesaDestroyContext DestroyContext;
|
||||
PFN_OSMesaMakeCurrent MakeCurrent;
|
||||
PFN_OSMesaGetColorBuffer GetColorBuffer;
|
||||
PFN_OSMesaGetDepthBuffer GetDepthBuffer;
|
||||
PFN_OSMesaGetProcAddress GetProcAddress;
|
||||
|
||||
} _GLFWlibraryOSMesa;
|
||||
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void);
|
||||
void _glfwTerminateOSMesa(void);
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_FALSE);
|
||||
|
||||
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
return mutex->posix.allocated = GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
if (mutex->posix.allocated)
|
||||
pthread_mutex_destroy(&mutex->posix.handle);
|
||||
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||
}
|
||||
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
pthread_mutex_lock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
pthread_mutex_unlock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 POSIX - www.glfw.org
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,25 +25,27 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_posix_tls_h_
|
||||
#define _glfw3_posix_tls_h_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls
|
||||
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix
|
||||
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexPOSIX posix
|
||||
|
||||
|
||||
// POSIX-specific global TLS data
|
||||
// POSIX-specific thread local storage data
|
||||
//
|
||||
typedef struct _GLFWtlsPOSIX
|
||||
{
|
||||
GLFWbool allocated;
|
||||
pthread_key_t context;
|
||||
pthread_key_t key;
|
||||
|
||||
} _GLFWtlsPOSIX;
|
||||
|
||||
// POSIX-specific mutex data
|
||||
//
|
||||
typedef struct _GLFWmutexPOSIX
|
||||
{
|
||||
GLFWbool allocated;
|
||||
pthread_mutex_t handle;
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
|
||||
void _glfwTerminateThreadLocalStoragePOSIX(void);
|
||||
} _GLFWmutexPOSIX;
|
||||
|
||||
#endif // _glfw3_posix_tls_h_
|
||||
+8
-8
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 POSIX - www.glfw.org
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -44,14 +44,14 @@ void _glfwInitTimerPOSIX(void)
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||
{
|
||||
_glfw.posix_time.monotonic = GLFW_TRUE;
|
||||
_glfw.posix_time.frequency = 1000000000;
|
||||
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||
_glfw.timer.posix.frequency = 1000000000;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_glfw.posix_time.monotonic = GLFW_FALSE;
|
||||
_glfw.posix_time.frequency = 1000000;
|
||||
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||
_glfw.timer.posix.frequency = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ void _glfwInitTimerPOSIX(void)
|
||||
uint64_t _glfwPlatformGetTimerValue(void)
|
||||
{
|
||||
#if defined(CLOCK_MONOTONIC)
|
||||
if (_glfw.posix_time.monotonic)
|
||||
if (_glfw.timer.posix.monotonic)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
@@ -80,6 +80,6 @@ uint64_t _glfwPlatformGetTimerValue(void)
|
||||
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||
{
|
||||
return _glfw.posix_time.frequency;
|
||||
return _glfw.timer.posix.frequency;
|
||||
}
|
||||
|
||||
|
||||
+5
-9
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 POSIX - www.glfw.org
|
||||
// GLFW 3.3 POSIX - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,24 +25,20 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _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>
|
||||
|
||||
|
||||
// POSIX-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimePOSIX
|
||||
typedef struct _GLFWtimerPOSIX
|
||||
{
|
||||
GLFWbool monotonic;
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimePOSIX;
|
||||
} _GLFWtimerPOSIX;
|
||||
|
||||
|
||||
void _glfwInitTimerPOSIX(void);
|
||||
|
||||
#endif // _glfw3_posix_time_h_
|
||||
|
||||
+87
-54
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -31,25 +31,38 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _GLFW_FIND_LOADER 1
|
||||
#define _GLFW_REQUIRE_LOADER 2
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void _glfwInitVulkan(void)
|
||||
GLFWbool _glfwInitVulkan(int mode)
|
||||
{
|
||||
VkResult err;
|
||||
VkExtensionProperties* ep;
|
||||
uint32_t i, count;
|
||||
#if defined(_GLFW_WIN32)
|
||||
const char* name = "vulkan-1.dll";
|
||||
#else
|
||||
const char* name = "libvulkan.so.1";
|
||||
#endif
|
||||
|
||||
_glfw.vk.handle = _glfw_dlopen(name);
|
||||
if (_glfw.vk.available)
|
||||
return GLFW_TRUE;
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_WIN32)
|
||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||
#elif defined(_GLFW_COCOA)
|
||||
_glfw.vk.handle = _glfw_dlopen("libMoltenVK.dylib");
|
||||
#else
|
||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||
#endif
|
||||
if (!_glfw.vk.handle)
|
||||
return;
|
||||
{
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||
@@ -57,7 +70,9 @@ void _glfwInitVulkan(void)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||
return;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
||||
@@ -66,16 +81,25 @@ void _glfwInitVulkan(void)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
||||
return;
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
#endif // _GLFW_VULKAN_STATIC
|
||||
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Vulkan: Failed to query instance extension count: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
return;
|
||||
// NOTE: This happens on systems with a loader but without any Vulkan ICD
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to query instance extension count: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
ep = calloc(count, sizeof(VkExtensionProperties));
|
||||
@@ -83,51 +107,54 @@ void _glfwInitVulkan(void)
|
||||
err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
|
||||
if (err)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Failed to query instance extensions: %s",
|
||||
_glfwGetVulkanResultString(err));
|
||||
|
||||
free(ep);
|
||||
return;
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
||||
_glfw.vk.KHR_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||
#if defined(_GLFW_WIN32)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||
#elif defined(_GLFW_COCOA)
|
||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
||||
#elif defined(_GLFW_X11)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
|
||||
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
|
||||
#elif defined(_GLFW_MIR)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
|
||||
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
free(ep);
|
||||
|
||||
_glfw.vk.available = GLFW_TRUE;
|
||||
|
||||
if (!_glfw.vk.KHR_surface)
|
||||
return;
|
||||
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
||||
|
||||
_glfw.vk.extensions =
|
||||
_glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwTerminateVulkan(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < _glfw.vk.extensionCount; i++)
|
||||
free(_glfw.vk.extensions[i]);
|
||||
free(_glfw.vk.extensions);
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
if (_glfw.vk.handle)
|
||||
_glfw_dlclose(_glfw.vk.handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* _glfwGetVulkanResultString(VkResult result)
|
||||
@@ -193,22 +220,24 @@ const char* _glfwGetVulkanResultString(VkResult result)
|
||||
GLFWAPI int glfwVulkanSupported(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
return _glfw.vk.available;
|
||||
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||
}
|
||||
|
||||
GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
|
||||
{
|
||||
assert(count != NULL);
|
||||
|
||||
*count = 0;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*count = _glfw.vk.extensionCount;
|
||||
if (!_glfw.vk.extensions[0])
|
||||
return NULL;
|
||||
|
||||
*count = 2;
|
||||
return (const char**) _glfw.vk.extensions;
|
||||
}
|
||||
|
||||
@@ -216,18 +245,24 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
||||
const char* procname)
|
||||
{
|
||||
GLFWvkproc proc;
|
||||
assert(procname != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
|
||||
#if defined(_GLFW_VULKAN_STATIC)
|
||||
if (!proc)
|
||||
{
|
||||
if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
|
||||
return (GLFWvkproc) vkGetInstanceProcAddr;
|
||||
}
|
||||
#else
|
||||
if (!proc)
|
||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
||||
#endif
|
||||
|
||||
return proc;
|
||||
}
|
||||
@@ -236,15 +271,15 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
assert(instance != VK_NULL_HANDLE);
|
||||
assert(device != VK_NULL_HANDLE);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions)
|
||||
if (!_glfw.vk.extensions[0])
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Window surface creation extensions not found");
|
||||
@@ -262,20 +297,18 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||
VkSurfaceKHR* surface)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(instance != VK_NULL_HANDLE);
|
||||
assert(window != NULL);
|
||||
|
||||
assert(surface != NULL);
|
||||
|
||||
*surface = VK_NULL_HANDLE;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
|
||||
|
||||
if (!_glfw.vk.available)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
if (!_glfw.vk.extensions)
|
||||
if (!_glfw.vk.extensions[0])
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Window surface creation extensions not found");
|
||||
|
||||
+242
-201
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 WGL - www.glfw.org
|
||||
// GLFW 3.3 WGL - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
||||
pixelFormat,
|
||||
0, 1, &attrib, &value))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve pixel format attribute %i",
|
||||
attrib);
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve pixel format attribute");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -55,19 +54,19 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
|
||||
|
||||
// Return a list of available and usable framebuffer configs
|
||||
//
|
||||
static GLFWbool choosePixelFormat(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* desired,
|
||||
int* result)
|
||||
static int choosePixelFormat(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
_GLFWfbconfig* usableConfigs;
|
||||
const _GLFWfbconfig* closest;
|
||||
int i, nativeCount, usableCount;
|
||||
int i, pixelFormat, nativeCount, usableCount;
|
||||
|
||||
if (_glfw.wgl.ARB_pixel_format)
|
||||
{
|
||||
nativeCount = getPixelFormatAttrib(window,
|
||||
1,
|
||||
WGL_NUMBER_PIXEL_FORMATS_ARB);
|
||||
1,
|
||||
WGL_NUMBER_PIXEL_FORMATS_ARB);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -130,11 +129,25 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
|
||||
if (_glfw.wgl.ARB_multisample)
|
||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_glfw.wgl.EXT_colorspace)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
||||
WGL_COLORSPACE_SRGB_EXT)
|
||||
{
|
||||
u->sRGB = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -197,23 +210,23 @@ static GLFWbool choosePixelFormat(_GLFWwindow* window,
|
||||
"WGL: The driver does not appear to support OpenGL");
|
||||
|
||||
free(usableConfigs);
|
||||
return GLFW_FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
|
||||
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
||||
if (!closest)
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"WGL: Failed to find a suitable pixel format");
|
||||
|
||||
free(usableConfigs);
|
||||
return GLFW_FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*result = (int) closest->handle;
|
||||
pixelFormat = (int) closest->handle;
|
||||
free(usableConfigs);
|
||||
|
||||
return GLFW_TRUE;
|
||||
return pixelFormat;
|
||||
}
|
||||
|
||||
// Returns whether desktop compositing is enabled
|
||||
@@ -231,32 +244,32 @@ static GLFWbool isCompositionEnabled(void)
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static void makeContextCurrent(_GLFWwindow* window)
|
||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window)
|
||||
{
|
||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
||||
_glfwPlatformSetCurrentContext(window);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make context current");
|
||||
_glfwPlatformSetCurrentContext(NULL);
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make context current");
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wglMakeCurrent(NULL, NULL))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to clear current context");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to clear current context");
|
||||
}
|
||||
|
||||
_glfwPlatformSetCurrentContext(NULL);
|
||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void swapBuffers(_GLFWwindow* window)
|
||||
static void swapBuffersWGL(_GLFWwindow* window)
|
||||
{
|
||||
// HACK: Use DwmFlush when desktop composition is enabled
|
||||
if (isCompositionEnabled() && !window->monitor)
|
||||
@@ -269,9 +282,9 @@ static void swapBuffers(_GLFWwindow* window)
|
||||
SwapBuffers(window->context.wgl.dc);
|
||||
}
|
||||
|
||||
static void swapInterval(int interval)
|
||||
static void swapIntervalWGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
window->context.wgl.interval = interval;
|
||||
|
||||
@@ -284,12 +297,10 @@ static void swapInterval(int interval)
|
||||
_glfw.wgl.SwapIntervalEXT(interval);
|
||||
}
|
||||
|
||||
static int extensionSupported(const char* extension)
|
||||
static int extensionSupportedWGL(const char* extension)
|
||||
{
|
||||
const char* extensions;
|
||||
|
||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||
|
||||
if (_glfw.wgl.GetExtensionsStringEXT)
|
||||
{
|
||||
extensions = _glfw.wgl.GetExtensionsStringEXT();
|
||||
@@ -302,7 +313,7 @@ static int extensionSupported(const char* extension)
|
||||
|
||||
if (_glfw.wgl.GetExtensionsStringARB)
|
||||
{
|
||||
extensions = _glfw.wgl.GetExtensionsStringARB(window->context.wgl.dc);
|
||||
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
|
||||
if (extensions)
|
||||
{
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
@@ -313,7 +324,7 @@ static int extensionSupported(const char* extension)
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddress(const char* procname)
|
||||
static GLFWglproc getProcAddressWGL(const char* procname)
|
||||
{
|
||||
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
||||
if (proc)
|
||||
@@ -324,7 +335,7 @@ static GLFWglproc getProcAddress(const char* procname)
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContext(_GLFWwindow* window)
|
||||
static void destroyContextWGL(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.wgl.handle)
|
||||
{
|
||||
@@ -335,51 +346,91 @@ static void destroyContext(_GLFWwindow* window)
|
||||
|
||||
// Initialize WGL-specific extensions
|
||||
//
|
||||
static void loadExtensions(void)
|
||||
static void loadWGLExtensions(void)
|
||||
{
|
||||
// Functions for WGL_EXT_extension_string
|
||||
// NOTE: These are needed by extensionSupported
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
HGLRC rc;
|
||||
HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
|
||||
|
||||
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
|
||||
|
||||
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
||||
// OpenGL ICD, from which we can then query WGL extensions
|
||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
||||
// creation failure occurs during manual pixel format enumeration
|
||||
|
||||
ZeroMemory(&pfd, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||
pfd.cColorBits = 24;
|
||||
|
||||
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set pixel format for dummy context");
|
||||
return;
|
||||
}
|
||||
|
||||
rc = wglCreateContext(dc);
|
||||
if (!rc)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to create dummy context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wglMakeCurrent(dc, rc))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to make dummy context current");
|
||||
wglDeleteContext(rc);
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||
// extension string that tells us whether the functions are supported
|
||||
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
||||
wglGetProcAddress("wglGetExtensionsStringEXT");
|
||||
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
||||
wglGetProcAddress("wglGetExtensionsStringARB");
|
||||
|
||||
// Functions for WGL_ARB_create_context
|
||||
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
||||
wglGetProcAddress("wglCreateContextAttribsARB");
|
||||
|
||||
// Functions for WGL_EXT_swap_control
|
||||
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
||||
wglGetProcAddress("wglSwapIntervalEXT");
|
||||
|
||||
// Functions for WGL_ARB_pixel_format
|
||||
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
||||
wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
||||
|
||||
// This needs to include every extension used below except for
|
||||
// WGL_ARB_extensions_string and WGL_EXT_extensions_string
|
||||
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
|
||||
// checked below as we are already using them
|
||||
_glfw.wgl.ARB_multisample =
|
||||
extensionSupported("WGL_ARB_multisample");
|
||||
extensionSupportedWGL("WGL_ARB_multisample");
|
||||
_glfw.wgl.ARB_framebuffer_sRGB =
|
||||
extensionSupported("WGL_ARB_framebuffer_sRGB");
|
||||
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
|
||||
_glfw.wgl.EXT_framebuffer_sRGB =
|
||||
extensionSupported("WGL_EXT_framebuffer_sRGB");
|
||||
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
|
||||
_glfw.wgl.ARB_create_context =
|
||||
extensionSupported("WGL_ARB_create_context");
|
||||
extensionSupportedWGL("WGL_ARB_create_context");
|
||||
_glfw.wgl.ARB_create_context_profile =
|
||||
extensionSupported("WGL_ARB_create_context_profile");
|
||||
extensionSupportedWGL("WGL_ARB_create_context_profile");
|
||||
_glfw.wgl.EXT_create_context_es2_profile =
|
||||
extensionSupported("WGL_EXT_create_context_es2_profile");
|
||||
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
||||
_glfw.wgl.ARB_create_context_robustness =
|
||||
extensionSupported("WGL_ARB_create_context_robustness");
|
||||
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
||||
_glfw.wgl.ARB_create_context_no_error =
|
||||
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
||||
_glfw.wgl.EXT_swap_control =
|
||||
extensionSupported("WGL_EXT_swap_control");
|
||||
extensionSupportedWGL("WGL_EXT_swap_control");
|
||||
_glfw.wgl.EXT_colorspace =
|
||||
extensionSupportedWGL("WGL_EXT_colorspace");
|
||||
_glfw.wgl.ARB_pixel_format =
|
||||
extensionSupported("WGL_ARB_pixel_format");
|
||||
extensionSupportedWGL("WGL_ARB_pixel_format");
|
||||
_glfw.wgl.ARB_context_flush_control =
|
||||
extensionSupported("WGL_ARB_context_flush_control");
|
||||
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
||||
|
||||
_glfw.wgl.extensionsLoaded = GLFW_TRUE;
|
||||
wglMakeCurrent(dc, NULL);
|
||||
wglDeleteContext(rc);
|
||||
}
|
||||
|
||||
|
||||
@@ -391,22 +442,28 @@ static void loadExtensions(void)
|
||||
//
|
||||
GLFWbool _glfwInitWGL(void)
|
||||
{
|
||||
if (_glfw.wgl.instance)
|
||||
return GLFW_TRUE;
|
||||
|
||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||
if (!_glfw.wgl.instance)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to load opengl32.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
|
||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
||||
_glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
|
||||
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
||||
_glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
|
||||
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
||||
_glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
|
||||
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
||||
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
||||
_glfw.wgl.ShareLists = (WGLSHARELISTS_T)
|
||||
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
||||
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -420,11 +477,11 @@ void _glfwTerminateWGL(void)
|
||||
FreeLibrary(_glfw.wgl.instance);
|
||||
}
|
||||
|
||||
#define setWGLattrib(attribName, attribValue) \
|
||||
#define setAttrib(a, v) \
|
||||
{ \
|
||||
attribs[index++] = attribName; \
|
||||
attribs[index++] = attribValue; \
|
||||
assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||
attribs[index++] = a; \
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
@@ -434,12 +491,12 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
int attribs[40];
|
||||
int pixelFormat = 0;
|
||||
int pixelFormat;
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
HGLRC share = NULL;
|
||||
|
||||
if (ctxconfig->client == GLFW_NO_API)
|
||||
return GLFW_TRUE;
|
||||
if (!_glfw.wgl.extensionsLoaded)
|
||||
loadWGLExtensions();
|
||||
|
||||
if (ctxconfig->share)
|
||||
share = ctxconfig->share->context.wgl.handle;
|
||||
@@ -452,24 +509,59 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!choosePixelFormat(window, fbconfig, &pixelFormat))
|
||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||
if (!pixelFormat)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||
pixelFormat, sizeof(pfd), &pfd))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set selected pixel format");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (ctxconfig->forward)
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->profile)
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context_profile)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context ||
|
||||
!_glfw.wgl.ARB_create_context_profile ||
|
||||
!_glfw.wgl.EXT_create_context_es2_profile)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.wgl.ARB_create_context)
|
||||
{
|
||||
int index = 0, mask = 0, flags = 0;
|
||||
@@ -489,8 +581,6 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
|
||||
if (ctxconfig->debug)
|
||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
if (ctxconfig->noerror)
|
||||
flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
|
||||
|
||||
if (ctxconfig->robustness)
|
||||
{
|
||||
@@ -498,13 +588,13 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
||||
}
|
||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
||||
}
|
||||
|
||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
||||
@@ -517,41 +607,88 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
||||
}
|
||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
if (_glfw.wgl.ARB_create_context_no_error)
|
||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
||||
}
|
||||
|
||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||
// explicitly requesting version 1.0 does not always return the
|
||||
// highest version supported by the driver
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
||||
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
||||
}
|
||||
|
||||
if (flags)
|
||||
setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
||||
|
||||
if (mask)
|
||||
setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
||||
|
||||
setWGLattrib(0, 0);
|
||||
setAttrib(0, 0);
|
||||
|
||||
window->context.wgl.handle =
|
||||
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
|
||||
share, attribs);
|
||||
if (!window->context.wgl.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
const DWORD error = GetLastError();
|
||||
|
||||
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Driver does not support OpenGL version %i.%i",
|
||||
ctxconfig->major,
|
||||
ctxconfig->minor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Driver does not support OpenGL ES version %i.%i",
|
||||
ctxconfig->major,
|
||||
ctxconfig->minor);
|
||||
}
|
||||
}
|
||||
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Driver does not support the requested OpenGL profile");
|
||||
}
|
||||
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"WGL: The share context is not compatible with the requested context");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL ES context");
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
@@ -560,8 +697,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
||||
if (!window->context.wgl.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -569,120 +706,24 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
if (!wglShareLists(share, window->context.wgl.handle))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrent;
|
||||
window->context.swapBuffers = swapBuffers;
|
||||
window->context.swapInterval = swapInterval;
|
||||
window->context.extensionSupported = extensionSupported;
|
||||
window->context.getProcAddress = getProcAddress;
|
||||
window->context.destroy = destroyContext;
|
||||
window->context.makeCurrent = makeContextCurrentWGL;
|
||||
window->context.swapBuffers = swapBuffersWGL;
|
||||
window->context.swapInterval = swapIntervalWGL;
|
||||
window->context.extensionSupported = extensionSupportedWGL;
|
||||
window->context.getProcAddress = getProcAddressWGL;
|
||||
window->context.destroy = destroyContextWGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
#undef setWGLattrib
|
||||
|
||||
// Analyzes the specified context for possible recreation
|
||||
//
|
||||
int _glfwAnalyzeContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
GLFWbool required = GLFW_FALSE;
|
||||
|
||||
if (_glfw.wgl.extensionsLoaded)
|
||||
return _GLFW_RECREATION_NOT_NEEDED;
|
||||
|
||||
makeContextCurrent(window);
|
||||
loadExtensions();
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
{
|
||||
if (ctxconfig->forward)
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
||||
return _GLFW_RECREATION_IMPOSSIBLE;
|
||||
}
|
||||
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (ctxconfig->profile)
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context_profile)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
||||
return _GLFW_RECREATION_IMPOSSIBLE;
|
||||
}
|
||||
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (ctxconfig->release)
|
||||
{
|
||||
if (_glfw.wgl.ARB_context_flush_control)
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_glfw.wgl.ARB_create_context ||
|
||||
!_glfw.wgl.ARB_create_context_profile ||
|
||||
!_glfw.wgl.EXT_create_context_es2_profile)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
||||
return _GLFW_RECREATION_IMPOSSIBLE;
|
||||
}
|
||||
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||
{
|
||||
if (_glfw.wgl.ARB_create_context)
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (ctxconfig->debug)
|
||||
{
|
||||
if (_glfw.wgl.ARB_create_context)
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (fbconfig->samples > 0)
|
||||
{
|
||||
// MSAA is not a hard constraint, so do nothing if it's not supported
|
||||
if (_glfw.wgl.ARB_multisample && _glfw.wgl.ARB_pixel_format)
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
|
||||
if (fbconfig->sRGB)
|
||||
{
|
||||
// sRGB is not a hard constraint, so do nothing if it's not supported
|
||||
if ((_glfw.wgl.ARB_framebuffer_sRGB ||
|
||||
_glfw.wgl.EXT_framebuffer_sRGB) &&
|
||||
_glfw.wgl.ARB_pixel_format)
|
||||
{
|
||||
required = GLFW_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (required)
|
||||
return _GLFW_RECREATION_REQUIRED;
|
||||
|
||||
return _GLFW_RECREATION_NOT_NEEDED;
|
||||
}
|
||||
#undef setAttrib
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+24
-21
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 WGL - www.glfw.org
|
||||
// GLFW 3.3 WGL - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,10 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_wgl_context_h_
|
||||
#define _glfw3_wgl_context_h_
|
||||
|
||||
|
||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
@@ -72,6 +68,13 @@
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
||||
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
||||
#define WGL_COLORSPACE_EXT 0x309d
|
||||
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
||||
|
||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
||||
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
||||
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
||||
|
||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
||||
@@ -79,16 +82,18 @@ typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
|
||||
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
|
||||
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
|
||||
|
||||
typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
|
||||
typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
|
||||
typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
|
||||
typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
|
||||
typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
|
||||
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
|
||||
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
||||
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
||||
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
||||
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
||||
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
||||
|
||||
// opengl32.dll function pointer typedefs
|
||||
#define wglCreateContext _glfw.wgl.CreateContext
|
||||
#define wglDeleteContext _glfw.wgl.DeleteContext
|
||||
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
||||
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
||||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
||||
#define wglShareLists _glfw.wgl.ShareLists
|
||||
|
||||
@@ -110,17 +115,17 @@ typedef struct _GLFWcontextWGL
|
||||
|
||||
} _GLFWcontextWGL;
|
||||
|
||||
|
||||
// WGL-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryWGL
|
||||
{
|
||||
HINSTANCE instance;
|
||||
WGLCREATECONTEXT_T CreateContext;
|
||||
WGLDELETECONTEXT_T DeleteContext;
|
||||
WGLGETPROCADDRESS_T GetProcAddress;
|
||||
WGLMAKECURRENT_T MakeCurrent;
|
||||
WGLSHARELISTS_T ShareLists;
|
||||
PFN_wglCreateContext CreateContext;
|
||||
PFN_wglDeleteContext DeleteContext;
|
||||
PFN_wglGetProcAddress GetProcAddress;
|
||||
PFN_wglGetCurrentDC GetCurrentDC;
|
||||
PFN_wglMakeCurrent MakeCurrent;
|
||||
PFN_wglShareLists ShareLists;
|
||||
|
||||
GLFWbool extensionsLoaded;
|
||||
|
||||
@@ -130,6 +135,7 @@ typedef struct _GLFWlibraryWGL
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||
GLFWbool EXT_swap_control;
|
||||
GLFWbool EXT_colorspace;
|
||||
GLFWbool ARB_multisample;
|
||||
GLFWbool ARB_framebuffer_sRGB;
|
||||
GLFWbool EXT_framebuffer_sRGB;
|
||||
@@ -138,6 +144,7 @@ typedef struct _GLFWlibraryWGL
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryWGL;
|
||||
@@ -148,8 +155,4 @@ void _glfwTerminateWGL(void);
|
||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
int _glfwAnalyzeContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
#endif // _glfw3_wgl_context_h_
|
||||
|
||||
+195
-158
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -30,20 +30,21 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include <initguid.h>
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
|
||||
static const GUID _glfw_GUID_DEVINTERFACE_HID = {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
|
||||
|
||||
#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
|
||||
|
||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
||||
|
||||
// Applications exporting this symbol with this value will be automatically
|
||||
// directed to the high-performance GPU on Nvidia Optimus systems with
|
||||
// up-to-date drivers
|
||||
// Executables (but not DLLs) exporting this symbol with this value will be
|
||||
// automatically directed to the high-performance GPU on Nvidia Optimus systems
|
||||
// with up-to-date drivers
|
||||
//
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 1;
|
||||
|
||||
// Applications exporting this symbol with this value will be automatically
|
||||
// directed to the high-performance GPU on AMD PowerXpress systems with
|
||||
// up-to-date drivers
|
||||
// Executables (but not DLLs) exporting this symbol with this value will be
|
||||
// automatically directed to the high-performance GPU on AMD PowerXpress systems
|
||||
// with up-to-date drivers
|
||||
//
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
|
||||
@@ -67,29 +68,29 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
||||
if (!_glfw.win32.winmm.instance)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
|
||||
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
|
||||
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
||||
|
||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
||||
if (!_glfw.win32.user32.instance)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
_glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)
|
||||
_glfw.win32.user32.SetProcessDPIAware = (PFN_SetProcessDPIAware)
|
||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
||||
_glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
|
||||
_glfw.win32.user32.ChangeWindowMessageFilterEx = (PFN_ChangeWindowMessageFilterEx)
|
||||
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
||||
|
||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
_glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
|
||||
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
||||
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
||||
}
|
||||
|
||||
@@ -110,9 +111,9 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
||||
if (_glfw.win32.xinput.instance)
|
||||
{
|
||||
_glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
|
||||
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
||||
_glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
|
||||
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
|
||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
||||
|
||||
break;
|
||||
@@ -123,16 +124,16 @@ static GLFWbool loadLibraries(void)
|
||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
||||
if (_glfw.win32.dwmapi.instance)
|
||||
{
|
||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
|
||||
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
||||
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
|
||||
_glfw.win32.dwmapi.DwmFlush = (PFN_DwmFlush)
|
||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||
}
|
||||
|
||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||
if (_glfw.win32.shcore.instance)
|
||||
{
|
||||
_glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)
|
||||
_glfw.win32.shcore.SetProcessDpiAwareness = (PFN_SetProcessDpiAwareness)
|
||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
||||
}
|
||||
|
||||
@@ -168,135 +169,135 @@ static void createKeyTables(void)
|
||||
{
|
||||
int scancode;
|
||||
|
||||
memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
|
||||
memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys));
|
||||
memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
|
||||
memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
|
||||
|
||||
_glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
|
||||
_glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
|
||||
_glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
|
||||
_glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
|
||||
_glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
|
||||
_glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
|
||||
_glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
|
||||
_glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
|
||||
_glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
|
||||
_glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
|
||||
_glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
|
||||
_glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
|
||||
_glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
|
||||
_glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
|
||||
_glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
|
||||
_glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
|
||||
_glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
|
||||
_glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
|
||||
_glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
|
||||
_glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
|
||||
_glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
|
||||
_glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
|
||||
_glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
|
||||
_glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
|
||||
_glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
|
||||
_glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
|
||||
_glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
|
||||
_glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
|
||||
_glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
|
||||
_glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
|
||||
_glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
|
||||
_glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
|
||||
_glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
|
||||
_glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
|
||||
_glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
|
||||
_glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;
|
||||
_glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
|
||||
_glfw.win32.keycodes[0x002] = GLFW_KEY_1;
|
||||
_glfw.win32.keycodes[0x003] = GLFW_KEY_2;
|
||||
_glfw.win32.keycodes[0x004] = GLFW_KEY_3;
|
||||
_glfw.win32.keycodes[0x005] = GLFW_KEY_4;
|
||||
_glfw.win32.keycodes[0x006] = GLFW_KEY_5;
|
||||
_glfw.win32.keycodes[0x007] = GLFW_KEY_6;
|
||||
_glfw.win32.keycodes[0x008] = GLFW_KEY_7;
|
||||
_glfw.win32.keycodes[0x009] = GLFW_KEY_8;
|
||||
_glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
|
||||
_glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
|
||||
_glfw.win32.keycodes[0x030] = GLFW_KEY_B;
|
||||
_glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
|
||||
_glfw.win32.keycodes[0x020] = GLFW_KEY_D;
|
||||
_glfw.win32.keycodes[0x012] = GLFW_KEY_E;
|
||||
_glfw.win32.keycodes[0x021] = GLFW_KEY_F;
|
||||
_glfw.win32.keycodes[0x022] = GLFW_KEY_G;
|
||||
_glfw.win32.keycodes[0x023] = GLFW_KEY_H;
|
||||
_glfw.win32.keycodes[0x017] = GLFW_KEY_I;
|
||||
_glfw.win32.keycodes[0x024] = GLFW_KEY_J;
|
||||
_glfw.win32.keycodes[0x025] = GLFW_KEY_K;
|
||||
_glfw.win32.keycodes[0x026] = GLFW_KEY_L;
|
||||
_glfw.win32.keycodes[0x032] = GLFW_KEY_M;
|
||||
_glfw.win32.keycodes[0x031] = GLFW_KEY_N;
|
||||
_glfw.win32.keycodes[0x018] = GLFW_KEY_O;
|
||||
_glfw.win32.keycodes[0x019] = GLFW_KEY_P;
|
||||
_glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
|
||||
_glfw.win32.keycodes[0x013] = GLFW_KEY_R;
|
||||
_glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
|
||||
_glfw.win32.keycodes[0x014] = GLFW_KEY_T;
|
||||
_glfw.win32.keycodes[0x016] = GLFW_KEY_U;
|
||||
_glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
|
||||
_glfw.win32.keycodes[0x011] = GLFW_KEY_W;
|
||||
_glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
|
||||
_glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
|
||||
_glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
|
||||
|
||||
_glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
|
||||
_glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
|
||||
_glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
|
||||
_glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
|
||||
_glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
|
||||
_glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;
|
||||
_glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
|
||||
_glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
|
||||
_glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
|
||||
_glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
|
||||
_glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
|
||||
_glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
|
||||
|
||||
_glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
|
||||
_glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
|
||||
_glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
|
||||
_glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
|
||||
_glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
|
||||
_glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
|
||||
_glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
|
||||
_glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
|
||||
_glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
|
||||
_glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
|
||||
_glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
|
||||
_glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
|
||||
_glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
|
||||
_glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
|
||||
_glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
|
||||
_glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
|
||||
_glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
|
||||
_glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
|
||||
_glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
|
||||
_glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
|
||||
_glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
|
||||
_glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
|
||||
_glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
|
||||
_glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
|
||||
_glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
|
||||
_glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
|
||||
_glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
|
||||
_glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
|
||||
_glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
|
||||
_glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
|
||||
_glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
|
||||
_glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
|
||||
_glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
|
||||
_glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
|
||||
_glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
|
||||
_glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
|
||||
_glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;
|
||||
_glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
|
||||
_glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
|
||||
_glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
|
||||
_glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
|
||||
_glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
|
||||
_glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
|
||||
_glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
|
||||
_glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
|
||||
_glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
|
||||
_glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
|
||||
_glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
|
||||
_glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
|
||||
_glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
|
||||
_glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
|
||||
_glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
|
||||
_glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
|
||||
_glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
|
||||
_glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
|
||||
_glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
|
||||
_glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
|
||||
_glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
|
||||
_glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
|
||||
_glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
|
||||
_glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
|
||||
_glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
|
||||
_glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
|
||||
_glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
|
||||
_glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
|
||||
_glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
|
||||
_glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
|
||||
_glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
|
||||
_glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
|
||||
_glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
|
||||
_glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
|
||||
_glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
|
||||
_glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
|
||||
_glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
|
||||
_glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
|
||||
|
||||
_glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
|
||||
_glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
|
||||
_glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
|
||||
_glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
|
||||
_glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
|
||||
_glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
|
||||
_glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
|
||||
_glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
|
||||
_glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
|
||||
_glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
|
||||
_glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
|
||||
_glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
|
||||
_glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
|
||||
_glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
|
||||
_glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
|
||||
_glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
|
||||
_glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
|
||||
_glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
|
||||
_glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
|
||||
_glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
|
||||
_glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
|
||||
_glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
|
||||
_glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
|
||||
_glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
|
||||
_glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
|
||||
|
||||
for (scancode = 0; scancode < 512; scancode++)
|
||||
{
|
||||
if (_glfw.win32.publicKeys[scancode] > 0)
|
||||
_glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;
|
||||
if (_glfw.win32.keycodes[scancode] > 0)
|
||||
_glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,21 +305,26 @@ static void createKeyTables(void)
|
||||
//
|
||||
static HWND createHelperWindow(void)
|
||||
{
|
||||
MSG msg;
|
||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
L"GLFW helper window",
|
||||
L"GLFW message window",
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
||||
0, 0, 1, 1,
|
||||
HWND_MESSAGE, NULL,
|
||||
NULL, NULL,
|
||||
GetModuleHandleW(NULL),
|
||||
NULL);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create helper window");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create helper window");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// HACK: The first call to ShowWindow is ignored if the parent process
|
||||
// passed along a STARTUPINFO, so clear that flag with a no-op call
|
||||
ShowWindow(window, SW_HIDE);
|
||||
|
||||
// Register for HID device notifications
|
||||
{
|
||||
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
|
||||
@@ -332,6 +338,12 @@ static HWND createHelperWindow(void)
|
||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
}
|
||||
|
||||
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -349,12 +361,18 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
||||
|
||||
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
||||
if (!length)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(length, sizeof(WCHAR));
|
||||
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string from UTF-8");
|
||||
free(target);
|
||||
return NULL;
|
||||
}
|
||||
@@ -371,12 +389,18 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
|
||||
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
||||
if (!length)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target = calloc(length, sizeof(char));
|
||||
target = calloc(length, 1);
|
||||
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
free(target);
|
||||
return NULL;
|
||||
}
|
||||
@@ -384,6 +408,27 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
return target;
|
||||
}
|
||||
|
||||
// Reports the specified error, appending information about the last Win32 error
|
||||
//
|
||||
void _glfwInputErrorWin32(int error, const char* description)
|
||||
{
|
||||
WCHAR buffer[1024] = L"";
|
||||
char message[2048] = "";
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
NULL,
|
||||
GetLastError() & 0xffff,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
NULL);
|
||||
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
|
||||
|
||||
_glfwInputError(error, "%s: %s", description, message);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
@@ -391,9 +436,6 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
||||
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
if (!_glfwInitThreadLocalStorageWin32())
|
||||
return GLFW_FALSE;
|
||||
|
||||
// To make SetForegroundWindow work as we want, we need to fiddle
|
||||
// with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
|
||||
// as possible in the hope of still being the foreground process)
|
||||
@@ -419,15 +461,10 @@ int _glfwPlatformInit(void)
|
||||
if (!_glfw.win32.helperWindowHandle)
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwPlatformPollEvents();
|
||||
|
||||
if (!_glfwInitWGL())
|
||||
return GLFW_FALSE;
|
||||
|
||||
_glfwInitEGL();
|
||||
_glfwInitTimerWin32();
|
||||
_glfwInitJoysticksWin32();
|
||||
|
||||
_glfwPollMonitorsWin32();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
@@ -444,12 +481,12 @@ void _glfwPlatformTerminate(void)
|
||||
SPIF_SENDCHANGE);
|
||||
|
||||
free(_glfw.win32.clipboardString);
|
||||
free(_glfw.win32.rawInput);
|
||||
|
||||
_glfwTerminateWGL();
|
||||
_glfwTerminateEGL();
|
||||
|
||||
_glfwTerminateJoysticksWin32();
|
||||
_glfwTerminateThreadLocalStorageWin32();
|
||||
|
||||
freeLibraries();
|
||||
}
|
||||
|
||||
+307
-307
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.1 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -27,13 +27,9 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#define _GLFW_PRESENCE_ONLY 1
|
||||
#define _GLFW_UPDATE_STATE 2
|
||||
|
||||
#define _GLFW_TYPE_AXIS 0
|
||||
#define _GLFW_TYPE_SLIDER 1
|
||||
#define _GLFW_TYPE_BUTTON 2
|
||||
@@ -52,18 +48,29 @@ typedef struct _GLFWobjenumWin32
|
||||
int povCount;
|
||||
} _GLFWobjenumWin32;
|
||||
|
||||
// Define only the necessary GUIDs (it's bad enough that we're exporting these)
|
||||
// Define local copies of the necessary GUIDs
|
||||
//
|
||||
DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
|
||||
DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
|
||||
static const GUID _glfw_IID_IDirectInput8W = {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
|
||||
static const GUID _glfw_GUID_XAxis = {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_YAxis = {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_ZAxis = {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RxAxis = {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RyAxis = {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_RzAxis = {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Slider = {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_Button = {0xa36d02f0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
static const GUID _glfw_GUID_POV = {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
|
||||
|
||||
#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
|
||||
#define GUID_XAxis _glfw_GUID_XAxis
|
||||
#define GUID_YAxis _glfw_GUID_YAxis
|
||||
#define GUID_ZAxis _glfw_GUID_ZAxis
|
||||
#define GUID_RxAxis _glfw_GUID_RxAxis
|
||||
#define GUID_RyAxis _glfw_GUID_RyAxis
|
||||
#define GUID_RzAxis _glfw_GUID_RzAxis
|
||||
#define GUID_Slider _glfw_GUID_Slider
|
||||
#define GUID_Button _glfw_GUID_Button
|
||||
#define GUID_POV _glfw_GUID_POV
|
||||
|
||||
// Object data array for our clone of c_dfDIJoystick
|
||||
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
||||
@@ -149,9 +156,9 @@ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
||||
{
|
||||
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
||||
return "Wireless Xbox 360 Controller";
|
||||
return "Wireless Xbox Controller";
|
||||
else
|
||||
return "Xbox 360 Controller";
|
||||
return "Xbox Controller";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +183,7 @@ static int compareJoystickObjects(const void* first, const void* second)
|
||||
//
|
||||
static GLFWbool supportsXInput(const GUID* guid)
|
||||
{
|
||||
UINT i, count;
|
||||
UINT i, count = 0;
|
||||
RAWINPUTDEVICELIST* ridl;
|
||||
GLFWbool result = GLFW_FALSE;
|
||||
|
||||
@@ -185,7 +192,7 @@ static GLFWbool supportsXInput(const GUID* guid)
|
||||
|
||||
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
|
||||
|
||||
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == -1)
|
||||
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
|
||||
{
|
||||
free(ridl);
|
||||
return GLFW_FALSE;
|
||||
@@ -211,7 +218,7 @@ static GLFWbool supportsXInput(const GUID* guid)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != guid->Data1)
|
||||
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
|
||||
continue;
|
||||
|
||||
memset(name, 0, sizeof(name));
|
||||
@@ -238,25 +245,20 @@ static GLFWbool supportsXInput(const GUID* guid)
|
||||
|
||||
// Frees all resources associated with the specified joystick
|
||||
//
|
||||
static void closeJoystick(_GLFWjoystickWin32* js)
|
||||
static void closeJoystick(_GLFWjoystick* js)
|
||||
{
|
||||
if (js->device)
|
||||
if (js->win32.device)
|
||||
{
|
||||
IDirectInputDevice8_Unacquire(js->device);
|
||||
IDirectInputDevice8_Release(js->device);
|
||||
IDirectInputDevice8_Unacquire(js->win32.device);
|
||||
IDirectInputDevice8_Release(js->win32.device);
|
||||
}
|
||||
|
||||
free(js->name);
|
||||
free(js->axes);
|
||||
free(js->buttons);
|
||||
free(js->objects);
|
||||
memset(js, 0, sizeof(_GLFWjoystickWin32));
|
||||
|
||||
_glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
|
||||
_glfwFreeJoystick(js);
|
||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
||||
}
|
||||
|
||||
// DirectInput device object enumeration callback
|
||||
// Insights gleaned from SDL2
|
||||
// Insights gleaned from SDL
|
||||
//
|
||||
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||
void* user)
|
||||
@@ -332,28 +334,23 @@ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
||||
//
|
||||
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
{
|
||||
int joy = 0;
|
||||
int jid = 0;
|
||||
DIDEVCAPS dc;
|
||||
DIPROPDWORD dipd;
|
||||
IDirectInputDevice8* device;
|
||||
_GLFWobjenumWin32 data;
|
||||
_GLFWjoystickWin32* js;
|
||||
_GLFWjoystick* js;
|
||||
char guid[33];
|
||||
char name[256];
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
if (memcmp(&_glfw.joysticks[jid].win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
{
|
||||
if (!_glfw.win32_js[joy].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
return DIENUM_STOP;
|
||||
|
||||
if (supportsXInput(&di->guidProduct))
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
@@ -362,14 +359,14 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
&device,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to set device data format");
|
||||
"Win32: Failed to set device data format");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@@ -381,7 +378,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to query device capabilities");
|
||||
"Win32: Failed to query device capabilities");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@@ -398,7 +395,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
&dipd.diph)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to set device axis mode");
|
||||
"Win32: Failed to set device axis mode");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
return DIENUM_CONTINUE;
|
||||
@@ -415,7 +412,7 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to enumerate device objects");
|
||||
"Win32: Failed to enumerate device objects");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
@@ -426,224 +423,54 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
||||
sizeof(_GLFWjoyobjectWin32),
|
||||
compareJoystickObjects);
|
||||
|
||||
js = _glfw.win32_js + joy;
|
||||
js->device = device;
|
||||
js->guid = di->guidInstance;
|
||||
js->axisCount = data.axisCount + data.sliderCount;
|
||||
js->axes = calloc(js->axisCount, sizeof(float));
|
||||
js->buttonCount += data.buttonCount + data.povCount * 4;
|
||||
js->buttons = calloc(js->buttonCount, 1);
|
||||
js->objects = data.objects;
|
||||
js->objectCount = data.objectCount;
|
||||
js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
|
||||
js->present = GLFW_TRUE;
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
// TODO: Pack state arrays for non-gamepad devices
|
||||
//
|
||||
static GLFWbool openXinputDevice(DWORD index)
|
||||
{
|
||||
int joy;
|
||||
XINPUT_CAPABILITIES xic;
|
||||
_GLFWjoystickWin32* js;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0,
|
||||
di->tszInstanceName, -1,
|
||||
name, sizeof(name),
|
||||
NULL, NULL))
|
||||
{
|
||||
if (_glfw.win32_js[joy].present &&
|
||||
_glfw.win32_js[joy].device == NULL &&
|
||||
_glfw.win32_js[joy].index == index)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert joystick name to UTF-8");
|
||||
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
||||
{
|
||||
if (!_glfw.win32_js[joy].present)
|
||||
break;
|
||||
}
|
||||
|
||||
if (joy > GLFW_JOYSTICK_LAST)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
return GLFW_FALSE;
|
||||
|
||||
js = _glfw.win32_js + joy;
|
||||
js->axisCount = 6;
|
||||
js->axes = calloc(js->axisCount, sizeof(float));
|
||||
js->buttonCount = 14;
|
||||
js->buttons = calloc(js->buttonCount, 1);
|
||||
js->present = GLFW_TRUE;
|
||||
js->name = strdup(getDeviceDescription(&xic));
|
||||
js->index = index;
|
||||
|
||||
_glfwInputJoystickChange(joy, GLFW_CONNECTED);
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Polls for and processes events the specified joystick
|
||||
//
|
||||
static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
|
||||
{
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (js->device)
|
||||
{
|
||||
int i, j, ai = 0, bi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
|
||||
IDirectInputDevice8_Poll(js->device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||
{
|
||||
IDirectInputDevice8_Acquire(js->device);
|
||||
IDirectInputDevice8_Poll(js->device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
closeJoystick(js);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_PRESENCE_ONLY)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; i < js->objectCount; i++)
|
||||
{
|
||||
const void* data = (char*) &state + js->objects[i].offset;
|
||||
|
||||
switch (js->objects[i].type)
|
||||
{
|
||||
case _GLFW_TYPE_AXIS:
|
||||
case _GLFW_TYPE_SLIDER:
|
||||
{
|
||||
js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_BUTTON:
|
||||
{
|
||||
if (*((BYTE*) data) & 0x80)
|
||||
js->buttons[bi++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[bi++] = GLFW_RELEASE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_POV:
|
||||
{
|
||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
|
||||
// Screams of horror are appropriate at this point
|
||||
int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (value < 0 || value > 8)
|
||||
value = 8;
|
||||
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (directions[value] & (1 << j))
|
||||
js->buttons[bi++] = GLFW_PRESS;
|
||||
else
|
||||
js->buttons[bi++] = GLFW_RELEASE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
|
||||
(uint8_t) di->guidProduct.Data1,
|
||||
(uint8_t) (di->guidProduct.Data1 >> 8),
|
||||
(uint8_t) (di->guidProduct.Data1 >> 16),
|
||||
(uint8_t) (di->guidProduct.Data1 >> 24));
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
const WORD buttons[14] =
|
||||
{
|
||||
XINPUT_GAMEPAD_A,
|
||||
XINPUT_GAMEPAD_B,
|
||||
XINPUT_GAMEPAD_X,
|
||||
XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB,
|
||||
XINPUT_GAMEPAD_DPAD_UP,
|
||||
XINPUT_GAMEPAD_DPAD_RIGHT,
|
||||
XINPUT_GAMEPAD_DPAD_DOWN,
|
||||
XINPUT_GAMEPAD_DPAD_LEFT
|
||||
};
|
||||
|
||||
result = _glfw_XInputGetState(js->index, &xis);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||
closeJoystick(js);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_PRESENCE_ONLY)
|
||||
return GLFW_TRUE;
|
||||
|
||||
if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||
xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
|
||||
(double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||
{
|
||||
js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||
js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
js->axes[0] = 0.f;
|
||||
js->axes[1] = 0.f;
|
||||
}
|
||||
|
||||
if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||
xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
|
||||
(double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||
{
|
||||
js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||
js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
js->axes[2] = 0.f;
|
||||
js->axes[3] = 0.f;
|
||||
}
|
||||
|
||||
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||
else
|
||||
js->axes[4] = -1.f;
|
||||
|
||||
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||
else
|
||||
js->axes[5] = -1.f;
|
||||
|
||||
for (i = 0; i < 14; i++)
|
||||
js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||
|
||||
return GLFW_TRUE;
|
||||
sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
|
||||
name[0], name[1], name[2], name[3],
|
||||
name[4], name[5], name[6], name[7],
|
||||
name[8], name[9], name[10]);
|
||||
}
|
||||
|
||||
js = _glfwAllocJoystick(name, guid,
|
||||
data.axisCount + data.sliderCount,
|
||||
data.buttonCount,
|
||||
data.povCount);
|
||||
if (!js)
|
||||
{
|
||||
IDirectInputDevice8_Release(device);
|
||||
free(data.objects);
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
js->win32.device = device;
|
||||
js->win32.guid = di->guidInstance;
|
||||
js->win32.objects = data.objects;
|
||||
js->win32.objectCount = data.objectCount;
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -657,14 +484,14 @@ void _glfwInitJoysticksWin32(void)
|
||||
{
|
||||
if (_glfw.win32.dinput8.instance)
|
||||
{
|
||||
if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
||||
DIRECTINPUT_VERSION,
|
||||
&IID_IDirectInput8W,
|
||||
(void**) &_glfw.win32.dinput8.api,
|
||||
NULL)))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"DI: Failed to create interface");
|
||||
"Win32: Failed to create interface");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,10 +502,10 @@ void _glfwInitJoysticksWin32(void)
|
||||
//
|
||||
void _glfwTerminateJoysticksWin32(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
closeJoystick(_glfw.win32_js + joy);
|
||||
for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
closeJoystick(_glfw.joysticks + jid);
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
IDirectInput8_Release(_glfw.win32.dinput8.api);
|
||||
@@ -690,10 +517,43 @@ void _glfwDetectJoystickConnectionWin32(void)
|
||||
{
|
||||
if (_glfw.win32.xinput.instance)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD index;
|
||||
|
||||
for (i = 0; i < XUSER_MAX_COUNT; i++)
|
||||
openXinputDevice(i);
|
||||
for (index = 0; index < XUSER_MAX_COUNT; index++)
|
||||
{
|
||||
int jid;
|
||||
char guid[33];
|
||||
XINPUT_CAPABILITIES xic;
|
||||
_GLFWjoystick* js;
|
||||
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
if (_glfw.joysticks[jid].present &&
|
||||
_glfw.joysticks[jid].win32.device == NULL &&
|
||||
_glfw.joysticks[jid].win32.index == index)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jid <= GLFW_JOYSTICK_LAST)
|
||||
continue;
|
||||
|
||||
if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
|
||||
continue;
|
||||
|
||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||
sprintf(guid, "78696e707574%02x000000000000000000",
|
||||
xic.SubType & 0xff);
|
||||
|
||||
js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
|
||||
if (!js)
|
||||
continue;
|
||||
|
||||
js->win32.index = index;
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
if (_glfw.win32.dinput8.api)
|
||||
@@ -715,10 +575,14 @@ void _glfwDetectJoystickConnectionWin32(void)
|
||||
//
|
||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
{
|
||||
int joy;
|
||||
int jid;
|
||||
|
||||
for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
|
||||
pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
|
||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||
{
|
||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
||||
if (js->present)
|
||||
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -726,38 +590,174 @@ void _glfwDetectJoystickDisconnectionWin32(void)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int _glfwPlatformJoystickPresent(int joy)
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
|
||||
if (js->win32.device)
|
||||
{
|
||||
int i, ai = 0, bi = 0, pi = 0;
|
||||
HRESULT result;
|
||||
DIJOYSTATE state;
|
||||
|
||||
IDirectInputDevice8_Poll(js->win32.device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
|
||||
{
|
||||
IDirectInputDevice8_Acquire(js->win32.device);
|
||||
IDirectInputDevice8_Poll(js->win32.device);
|
||||
result = IDirectInputDevice8_GetDeviceState(js->win32.device,
|
||||
sizeof(state),
|
||||
&state);
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
closeJoystick(js);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_POLL_PRESENCE)
|
||||
return GLFW_TRUE;
|
||||
|
||||
for (i = 0; i < js->win32.objectCount; i++)
|
||||
{
|
||||
const void* data = (char*) &state + js->win32.objects[i].offset;
|
||||
|
||||
switch (js->win32.objects[i].type)
|
||||
{
|
||||
case _GLFW_TYPE_AXIS:
|
||||
case _GLFW_TYPE_SLIDER:
|
||||
{
|
||||
const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
|
||||
_glfwInputJoystickAxis(js, ai, value);
|
||||
ai++;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_BUTTON:
|
||||
{
|
||||
const char value = (*((BYTE*) data) & 0x80) != 0;
|
||||
_glfwInputJoystickButton(js, bi, value);
|
||||
bi++;
|
||||
break;
|
||||
}
|
||||
|
||||
case _GLFW_TYPE_POV:
|
||||
{
|
||||
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
|
||||
int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
|
||||
if (state < 0 || state > 8)
|
||||
state = 8;
|
||||
|
||||
_glfwInputJoystickHat(js, pi, states[state]);
|
||||
pi++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, dpad = 0;
|
||||
DWORD result;
|
||||
XINPUT_STATE xis;
|
||||
float axes[6] = { 0.f, 0.f, 0.f, 0.f, -1.f, -1.f };
|
||||
const WORD buttons[10] =
|
||||
{
|
||||
XINPUT_GAMEPAD_A,
|
||||
XINPUT_GAMEPAD_B,
|
||||
XINPUT_GAMEPAD_X,
|
||||
XINPUT_GAMEPAD_Y,
|
||||
XINPUT_GAMEPAD_LEFT_SHOULDER,
|
||||
XINPUT_GAMEPAD_RIGHT_SHOULDER,
|
||||
XINPUT_GAMEPAD_BACK,
|
||||
XINPUT_GAMEPAD_START,
|
||||
XINPUT_GAMEPAD_LEFT_THUMB,
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB
|
||||
};
|
||||
|
||||
result = XInputGetState(js->win32.index, &xis);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
if (result == ERROR_DEVICE_NOT_CONNECTED)
|
||||
closeJoystick(js);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
if (mode == _GLFW_POLL_PRESENCE)
|
||||
return GLFW_TRUE;
|
||||
|
||||
if ((float) xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
|
||||
(float) xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY >
|
||||
(float) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE *
|
||||
XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
|
||||
{
|
||||
axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
|
||||
axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
|
||||
}
|
||||
|
||||
if ((float) xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
|
||||
(float) xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY >
|
||||
(float) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE *
|
||||
XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
|
||||
{
|
||||
axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
|
||||
axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
|
||||
}
|
||||
|
||||
if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
|
||||
|
||||
if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
|
||||
axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
_glfwInputJoystickAxis(js, i, axes[i]);
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
|
||||
_glfwInputJoystickButton(js, 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(js, 0, dpad);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
*count = js->axisCount;
|
||||
return js->axes;
|
||||
}
|
||||
|
||||
const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
|
||||
return NULL;
|
||||
|
||||
*count = js->buttonCount;
|
||||
return js->buttons;
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetJoystickName(int joy)
|
||||
{
|
||||
_GLFWjoystickWin32* js = _glfw.win32_js + joy;
|
||||
if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
|
||||
return NULL;
|
||||
|
||||
return js->name;
|
||||
if (strcmp(guid + 20, "504944564944") == 0)
|
||||
{
|
||||
char original[33];
|
||||
strcpy(original, guid);
|
||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||
original, original + 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-14
@@ -1,7 +1,7 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -24,13 +24,12 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_win32_joystick_h_
|
||||
#define _glfw3_win32_joystick_h_
|
||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
|
||||
|
||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
|
||||
_GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
|
||||
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
||||
|
||||
// Spoo
|
||||
// Joystick element (axis, button or slider)
|
||||
//
|
||||
typedef struct _GLFWjoyobjectWin32
|
||||
{
|
||||
@@ -42,14 +41,8 @@ typedef struct _GLFWjoyobjectWin32
|
||||
//
|
||||
typedef struct _GLFWjoystickWin32
|
||||
{
|
||||
GLFWbool present;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
int buttonCount;
|
||||
_GLFWjoyobjectWin32* objects;
|
||||
int objectCount;
|
||||
char* name;
|
||||
IDirectInputDevice8W* device;
|
||||
DWORD index;
|
||||
GUID guid;
|
||||
@@ -61,4 +54,3 @@ void _glfwTerminateJoysticksWin32(void);
|
||||
void _glfwDetectJoystickConnectionWin32(void);
|
||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
||||
|
||||
#endif // _glfw3_win32_joystick_h_
|
||||
|
||||
+140
-97
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -47,11 +47,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
else
|
||||
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
||||
if (!name)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
||||
|
||||
@@ -90,6 +86,116 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Poll for changes in the set of connected monitors
|
||||
//
|
||||
void _glfwPollMonitorsWin32(void)
|
||||
{
|
||||
int i, disconnectedCount;
|
||||
_GLFWmonitor** disconnected = NULL;
|
||||
DWORD adapterIndex, displayIndex;
|
||||
DISPLAY_DEVICEW adapter, display;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
disconnectedCount = _glfw.monitorCount;
|
||||
if (disconnectedCount)
|
||||
{
|
||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||
memcpy(disconnected,
|
||||
_glfw.monitors,
|
||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||
}
|
||||
|
||||
for (adapterIndex = 0; ; adapterIndex++)
|
||||
{
|
||||
int type = _GLFW_INSERT_LAST;
|
||||
|
||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
|
||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||
type = _GLFW_INSERT_FIRST;
|
||||
|
||||
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++)
|
||||
{
|
||||
if (disconnected[i] &&
|
||||
wcscmp(disconnected[i]->win32.displayName,
|
||||
display.DeviceName) == 0)
|
||||
{
|
||||
disconnected[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < disconnectedCount)
|
||||
continue;
|
||||
|
||||
monitor = createMonitor(&adapter, &display);
|
||||
if (!monitor)
|
||||
{
|
||||
free(disconnected);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||
|
||||
type = _GLFW_INSERT_LAST;
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
if (disconnected[i] &&
|
||||
wcscmp(disconnected[i]->win32.adapterName,
|
||||
adapter.DeviceName) == 0)
|
||||
{
|
||||
disconnected[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < disconnectedCount)
|
||||
continue;
|
||||
|
||||
monitor = createMonitor(&adapter, NULL);
|
||||
if (!monitor)
|
||||
{
|
||||
free(disconnected);
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, type);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < disconnectedCount; i++)
|
||||
{
|
||||
if (disconnected[i])
|
||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||
}
|
||||
|
||||
free(disconnected);
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
//
|
||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||
@@ -97,6 +203,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
|
||||
GLFWvidmode current;
|
||||
const GLFWvidmode* best;
|
||||
DEVMODEW dm;
|
||||
LONG result;
|
||||
|
||||
best = _glfwChooseVideoMode(monitor, desired);
|
||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||
@@ -115,13 +222,34 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
|
||||
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
||||
dm.dmBitsPerPel = 32;
|
||||
|
||||
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||
&dm,
|
||||
NULL,
|
||||
CDS_FULLSCREEN,
|
||||
NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
||||
&dm,
|
||||
NULL,
|
||||
CDS_FULLSCREEN,
|
||||
NULL);
|
||||
if (result != DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
|
||||
const char* description = "Unknown error";
|
||||
|
||||
if (result == DISP_CHANGE_BADDUALVIEW)
|
||||
description = "The system uses DualView";
|
||||
else if (result == DISP_CHANGE_BADFLAGS)
|
||||
description = "Invalid flags";
|
||||
else if (result == DISP_CHANGE_BADMODE)
|
||||
description = "Graphics mode not supported";
|
||||
else if (result == DISP_CHANGE_BADPARAM)
|
||||
description = "Invalid parameter";
|
||||
else if (result == DISP_CHANGE_FAILED)
|
||||
description = "Graphics mode failed";
|
||||
else if (result == DISP_CHANGE_NOTUPDATED)
|
||||
description = "Failed to write to registry";
|
||||
else if (result == DISP_CHANGE_RESTART)
|
||||
description = "Computer restart required";
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to set video mode: %s",
|
||||
description);
|
||||
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -146,91 +274,6 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
|
||||
{
|
||||
int found = 0;
|
||||
DWORD adapterIndex, displayIndex, primaryIndex = 0;
|
||||
DISPLAY_DEVICEW adapter, display;
|
||||
GLFWbool hasDisplays = GLFW_FALSE;
|
||||
_GLFWmonitor** monitors = NULL;
|
||||
|
||||
*count = 0;
|
||||
|
||||
// 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++)
|
||||
{
|
||||
ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
|
||||
adapter.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
|
||||
break;
|
||||
|
||||
if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
|
||||
continue;
|
||||
|
||||
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||
primaryIndex = found;
|
||||
|
||||
if (hasDisplays)
|
||||
{
|
||||
for (displayIndex = 0; ; displayIndex++)
|
||||
{
|
||||
ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
|
||||
display.cb = sizeof(DISPLAY_DEVICEW);
|
||||
|
||||
if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
|
||||
break;
|
||||
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[found - 1] = createMonitor(&adapter, &display);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found++;
|
||||
monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
|
||||
monitors[found - 1] = createMonitor(&adapter, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
_GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
|
||||
|
||||
*count = found;
|
||||
return monitors;
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
|
||||
{
|
||||
if (wcslen(first->win32.displayName))
|
||||
return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
|
||||
else
|
||||
return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
{
|
||||
DEVMODEW settings;
|
||||
|
||||
+58
-53
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -25,9 +25,6 @@
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _glfw3_win32_platform_h_
|
||||
#define _glfw3_win32_platform_h_
|
||||
|
||||
// We don't need all the fancy stuff
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
@@ -161,33 +158,33 @@ typedef enum PROCESS_DPI_AWARENESS
|
||||
#endif
|
||||
|
||||
// winmm.dll function pointer typedefs
|
||||
typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
|
||||
#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
|
||||
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
||||
#define timeGetTime _glfw.win32.winmm.GetTime
|
||||
|
||||
// xinput.dll function pointer typedefs
|
||||
typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||
typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
|
||||
#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
|
||||
#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
|
||||
typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
|
||||
typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
|
||||
#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
|
||||
#define XInputGetState _glfw.win32.xinput.GetState
|
||||
|
||||
// dinput8.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||
#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
|
||||
typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
||||
#define DirectInput8Create _glfw.win32.dinput8.Create
|
||||
|
||||
// user32.dll function pointer typedefs
|
||||
typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
|
||||
typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
||||
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
|
||||
#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
|
||||
#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
|
||||
|
||||
// dwmapi.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
|
||||
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
|
||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
|
||||
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
|
||||
|
||||
// shcore.dll function pointer typedefs
|
||||
typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
|
||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||
#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
|
||||
|
||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
||||
@@ -207,6 +204,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
||||
#include "win32_joystick.h"
|
||||
#include "wgl_context.h"
|
||||
#include "egl_context.h"
|
||||
#include "osmesa_context.h"
|
||||
|
||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
||||
|
||||
@@ -219,10 +217,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(
|
||||
|
||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
|
||||
#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
|
||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerWin32 win32
|
||||
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
|
||||
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
|
||||
#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32
|
||||
#define _GLFW_PLATFORM_MUTEX_STATE _GLFWmutexWin32 win32
|
||||
|
||||
|
||||
// Win32-specific per-window data
|
||||
@@ -235,65 +234,67 @@ typedef struct _GLFWwindowWin32
|
||||
|
||||
GLFWbool cursorTracked;
|
||||
GLFWbool iconified;
|
||||
GLFWbool maximized;
|
||||
|
||||
// The last received cursor position, regardless of source
|
||||
int lastCursorPosX, lastCursorPosY;
|
||||
|
||||
} _GLFWwindowWin32;
|
||||
|
||||
|
||||
// Win32-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryWin32
|
||||
{
|
||||
HWND helperWindowHandle;
|
||||
DWORD foregroundLockTimeout;
|
||||
int acquiredMonitorCount;
|
||||
char* clipboardString;
|
||||
char keyName[64];
|
||||
short int publicKeys[512];
|
||||
short int nativeKeys[GLFW_KEY_LAST + 1];
|
||||
short int keycodes[512];
|
||||
short int scancodes[GLFW_KEY_LAST + 1];
|
||||
// Where to place the cursor when re-enabled
|
||||
double restoreCursorPosX, restoreCursorPosY;
|
||||
// The window whose disabled cursor mode is active
|
||||
_GLFWwindow* disabledCursorWindow;
|
||||
RAWINPUT* rawInput;
|
||||
int rawInputSize;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
TIMEGETTIME_T timeGetTime;
|
||||
HINSTANCE instance;
|
||||
PFN_timeGetTime GetTime;
|
||||
} winmm;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
DIRECTINPUT8CREATE_T DirectInput8Create;
|
||||
IDirectInput8W* api;
|
||||
HINSTANCE instance;
|
||||
PFN_DirectInput8Create Create;
|
||||
IDirectInput8W* api;
|
||||
} dinput8;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
XINPUTGETCAPABILITIES_T XInputGetCapabilities;
|
||||
XINPUTGETSTATE_T XInputGetState;
|
||||
HINSTANCE instance;
|
||||
PFN_XInputGetCapabilities GetCapabilities;
|
||||
PFN_XInputGetState GetState;
|
||||
} xinput;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
SETPROCESSDPIAWARE_T SetProcessDPIAware;
|
||||
CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
|
||||
HINSTANCE instance;
|
||||
PFN_SetProcessDPIAware SetProcessDPIAware;
|
||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx;
|
||||
} user32;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
|
||||
DWMFLUSH_T DwmFlush;
|
||||
HINSTANCE instance;
|
||||
PFN_DwmIsCompositionEnabled DwmIsCompositionEnabled;
|
||||
PFN_DwmFlush DwmFlush;
|
||||
} dwmapi;
|
||||
|
||||
struct {
|
||||
HINSTANCE instance;
|
||||
SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
|
||||
HINSTANCE instance;
|
||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness;
|
||||
} shcore;
|
||||
|
||||
} _GLFWlibraryWin32;
|
||||
|
||||
|
||||
// Win32-specific per-monitor data
|
||||
//
|
||||
typedef struct _GLFWmonitorWin32
|
||||
@@ -308,48 +309,52 @@ typedef struct _GLFWmonitorWin32
|
||||
|
||||
} _GLFWmonitorWin32;
|
||||
|
||||
|
||||
// Win32-specific per-cursor data
|
||||
//
|
||||
typedef struct _GLFWcursorWin32
|
||||
{
|
||||
HCURSOR handle;
|
||||
HCURSOR handle;
|
||||
|
||||
} _GLFWcursorWin32;
|
||||
|
||||
|
||||
// Win32-specific global timer data
|
||||
//
|
||||
typedef struct _GLFWtimeWin32
|
||||
typedef struct _GLFWtimerWin32
|
||||
{
|
||||
GLFWbool hasPC;
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimeWin32;
|
||||
} _GLFWtimerWin32;
|
||||
|
||||
|
||||
// Win32-specific global TLS data
|
||||
// Win32-specific thread local storage data
|
||||
//
|
||||
typedef struct _GLFWtlsWin32
|
||||
{
|
||||
GLFWbool allocated;
|
||||
DWORD context;
|
||||
GLFWbool allocated;
|
||||
DWORD index;
|
||||
|
||||
} _GLFWtlsWin32;
|
||||
|
||||
// Win32-specific mutex data
|
||||
//
|
||||
typedef struct _GLFWmutexWin32
|
||||
{
|
||||
GLFWbool allocated;
|
||||
CRITICAL_SECTION section;
|
||||
|
||||
} _GLFWmutexWin32;
|
||||
|
||||
|
||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
||||
void _glfwUnregisterWindowClassWin32(void);
|
||||
|
||||
GLFWbool _glfwInitThreadLocalStorageWin32(void);
|
||||
void _glfwTerminateThreadLocalStorageWin32(void);
|
||||
|
||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
||||
void _glfwInputErrorWin32(int error, const char* description);
|
||||
|
||||
void _glfwInitTimerWin32(void);
|
||||
|
||||
void _glfwPollMonitorsWin32(void);
|
||||
GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
||||
|
||||
#endif // _glfw3_win32_platform_h_
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//========================================================================
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW platform API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_FALSE);
|
||||
InitializeCriticalSection(&mutex->win32.section);
|
||||
return mutex->win32.allocated = GLFW_TRUE;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
if (mutex->win32.allocated)
|
||||
DeleteCriticalSection(&mutex->win32.section);
|
||||
memset(mutex, 0, sizeof(_GLFWmutex));
|
||||
}
|
||||
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||
EnterCriticalSection(&mutex->win32.section);
|
||||
}
|
||||
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->win32.allocated == GLFW_TRUE);
|
||||
LeaveCriticalSection(&mutex->win32.section);
|
||||
}
|
||||
|
||||
+9
-9
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -40,13 +40,13 @@ void _glfwInitTimerWin32(void)
|
||||
|
||||
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
||||
{
|
||||
_glfw.win32_time.hasPC = GLFW_TRUE;
|
||||
_glfw.win32_time.frequency = frequency;
|
||||
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
||||
_glfw.timer.win32.frequency = frequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfw.win32_time.hasPC = GLFW_FALSE;
|
||||
_glfw.win32_time.frequency = 1000;
|
||||
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
||||
_glfw.timer.win32.frequency = 1000;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,18 +57,18 @@ void _glfwInitTimerWin32(void)
|
||||
|
||||
uint64_t _glfwPlatformGetTimerValue(void)
|
||||
{
|
||||
if (_glfw.win32_time.hasPC)
|
||||
if (_glfw.timer.win32.hasPC)
|
||||
{
|
||||
uint64_t value;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
return (uint64_t) _glfw_timeGetTime();
|
||||
return (uint64_t) timeGetTime();
|
||||
}
|
||||
|
||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
||||
{
|
||||
return _glfw.win32_time.frequency;
|
||||
return _glfw.timer.win32.frequency;
|
||||
}
|
||||
|
||||
|
||||
+306
-231
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Win32 - www.glfw.org
|
||||
// GLFW 3.3 Win32 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
@@ -46,9 +46,11 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
|
||||
style |= WS_POPUP;
|
||||
else
|
||||
{
|
||||
style |= WS_SYSMENU | WS_MINIMIZEBOX;
|
||||
|
||||
if (window->decorated)
|
||||
{
|
||||
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
|
||||
style |= WS_CAPTION;
|
||||
|
||||
if (window->resizable)
|
||||
style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
|
||||
@@ -131,16 +133,16 @@ static HICON createIcon(const GLFWimage* image,
|
||||
|
||||
if (!color)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create RGBA bitmap");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create RGBA bitmap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
|
||||
if (!mask)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create mask bitmap");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create mask bitmap");
|
||||
DeleteObject(color);
|
||||
return NULL;
|
||||
}
|
||||
@@ -170,9 +172,15 @@ static HICON createIcon(const GLFWimage* image,
|
||||
if (!handle)
|
||||
{
|
||||
if (icon)
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create icon");
|
||||
}
|
||||
else
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create cursor");
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
@@ -278,6 +286,26 @@ static void updateClipRect(_GLFWwindow* window)
|
||||
ClipCursor(NULL);
|
||||
}
|
||||
|
||||
// Update native window styles to match attributes
|
||||
//
|
||||
static void updateWindowStyles(const _GLFWwindow* window)
|
||||
{
|
||||
RECT rect;
|
||||
DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
|
||||
style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
|
||||
style |= getWindowStyle(window);
|
||||
|
||||
GetClientRect(window->win32.handle, &rect);
|
||||
AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.left);
|
||||
ClientToScreen(window->win32.handle, (POINT*) &rect.right);
|
||||
SetWindowLongW(window->win32.handle, GWL_STYLE, style);
|
||||
SetWindowPos(window->win32.handle, HWND_TOP,
|
||||
rect.left, rect.top,
|
||||
rect.right - rect.left, rect.bottom - rect.top,
|
||||
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
// Translates a GLFW standard cursor to a resource ID
|
||||
//
|
||||
static LPWSTR translateCursorShape(int shape)
|
||||
@@ -341,20 +369,19 @@ static int getAsyncKeyMods(void)
|
||||
//
|
||||
static int translateKey(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// The Ctrl keys require special handling
|
||||
if (wParam == VK_CONTROL)
|
||||
{
|
||||
// The CTRL keys require special handling
|
||||
|
||||
MSG next;
|
||||
DWORD time;
|
||||
|
||||
// Is this an extended key (i.e. right key)?
|
||||
// Right side keys have the extended key bit set
|
||||
if (lParam & 0x01000000)
|
||||
return GLFW_KEY_RIGHT_CONTROL;
|
||||
|
||||
// Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
|
||||
// want the RALT message, so we try to see if the next message
|
||||
// is a RALT message. In that case, this is a false LCTRL!
|
||||
// HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
|
||||
// We only want the Right Alt message, so if the next message is
|
||||
// Right Alt we ignore this (synthetic) Left Ctrl message
|
||||
time = GetMessageTime();
|
||||
|
||||
if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
|
||||
@@ -368,8 +395,7 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
|
||||
(next.lParam & 0x01000000) &&
|
||||
next.time == time)
|
||||
{
|
||||
// Next message is a RALT down message, which
|
||||
// means that this is not a proper LCTRL message
|
||||
// Next message is Right Alt down so discard this
|
||||
return _GLFW_KEY_INVALID;
|
||||
}
|
||||
}
|
||||
@@ -385,7 +411,7 @@ static int translateKey(WPARAM wParam, LPARAM lParam)
|
||||
return _GLFW_KEY_INVALID;
|
||||
}
|
||||
|
||||
return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
|
||||
return _glfw.win32.keycodes[HIWORD(lParam) & 0x1FF];
|
||||
}
|
||||
|
||||
// Make the specified window and its video mode active on its monitor
|
||||
@@ -396,6 +422,11 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
|
||||
GLFWbool status;
|
||||
int xpos, ypos;
|
||||
|
||||
if (!_glfw.win32.acquiredMonitorCount)
|
||||
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
if (!window->monitor->window)
|
||||
_glfw.win32.acquiredMonitorCount++;
|
||||
|
||||
status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
|
||||
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
@@ -405,7 +436,7 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
|
||||
xpos, ypos, mode.width, mode.height,
|
||||
SWP_NOACTIVATE | SWP_NOCOPYBITS);
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, window);
|
||||
_glfwInputMonitorWindow(window->monitor, window);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -416,7 +447,11 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
if (window->monitor->window != window)
|
||||
return;
|
||||
|
||||
_glfwInputMonitorWindowChange(window->monitor, NULL);
|
||||
_glfw.win32.acquiredMonitorCount--;
|
||||
if (!_glfw.win32.acquiredMonitorCount)
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
|
||||
_glfwInputMonitorWindow(window->monitor, NULL);
|
||||
_glfwRestoreVideoModeWin32(window->monitor);
|
||||
}
|
||||
|
||||
@@ -432,30 +467,23 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DISPLAYCHANGE:
|
||||
_glfwPollMonitorsWin32();
|
||||
break;
|
||||
|
||||
case WM_DEVICECHANGE:
|
||||
{
|
||||
if (wParam == DBT_DEVNODES_CHANGED)
|
||||
{
|
||||
_glfwInputMonitorChange();
|
||||
return TRUE;
|
||||
}
|
||||
else if (wParam == DBT_DEVICEARRIVAL)
|
||||
if (wParam == DBT_DEVICEARRIVAL)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh)
|
||||
{
|
||||
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
}
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickConnectionWin32();
|
||||
}
|
||||
else if (wParam == DBT_DEVICEREMOVECOMPLETE)
|
||||
{
|
||||
DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
|
||||
if (dbh)
|
||||
{
|
||||
if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickDisconnectionWin32();
|
||||
}
|
||||
if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
_glfwDetectJoystickDisconnectionWin32();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -552,14 +580,15 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
|
||||
if (action == GLFW_RELEASE && wParam == VK_SHIFT)
|
||||
{
|
||||
// Release both Shift keys on Shift up event, as only one event
|
||||
// is sent even if both keys are released
|
||||
// HACK: Release both Shift keys on Shift up event, as when both
|
||||
// are pressed the first release does not emit any event
|
||||
// NOTE: The other half of this is in _glfwPlatformPollEvents
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
|
||||
}
|
||||
else if (wParam == VK_SNAPSHOT)
|
||||
{
|
||||
// Key down is not reported for the Print Screen key
|
||||
// HACK: Key down is not reported for the Print Screen key
|
||||
_glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
|
||||
_glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
|
||||
}
|
||||
@@ -578,7 +607,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_MBUTTONUP:
|
||||
case WM_XBUTTONUP:
|
||||
{
|
||||
int button, action;
|
||||
int i, button, action;
|
||||
|
||||
if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
|
||||
button = GLFW_MOUSE_BUTTON_LEFT;
|
||||
@@ -595,16 +624,30 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
|
||||
{
|
||||
action = GLFW_PRESS;
|
||||
SetCapture(hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = GLFW_RELEASE;
|
||||
ReleaseCapture();
|
||||
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > GLFW_MOUSE_BUTTON_LAST)
|
||||
SetCapture(hWnd);
|
||||
|
||||
_glfwInputMouseClick(window, button, action, getKeyMods());
|
||||
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
{
|
||||
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > GLFW_MOUSE_BUTTON_LAST)
|
||||
ReleaseCapture();
|
||||
|
||||
if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
|
||||
return TRUE;
|
||||
|
||||
@@ -616,20 +659,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
const int x = GET_X_LPARAM(lParam);
|
||||
const int y = GET_Y_LPARAM(lParam);
|
||||
|
||||
// Disabled cursor motion input is provided by WM_INPUT
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
const int dx = x - window->win32.lastCursorPosX;
|
||||
const int dy = y - window->win32.lastCursorPosY;
|
||||
break;
|
||||
|
||||
if (_glfw.win32.disabledCursorWindow != window)
|
||||
break;
|
||||
|
||||
_glfwInputCursorPos(window,
|
||||
window->virtualCursorPosX + dx,
|
||||
window->virtualCursorPosY + dy);
|
||||
}
|
||||
else
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
|
||||
window->win32.lastCursorPosX = x;
|
||||
window->win32.lastCursorPosY = y;
|
||||
@@ -650,6 +684,56 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_INPUT:
|
||||
{
|
||||
UINT size;
|
||||
HRAWINPUT ri = (HRAWINPUT) lParam;
|
||||
RAWINPUT* data;
|
||||
int dx, dy;
|
||||
|
||||
// Only process input when disabled cursor mode is applied
|
||||
if (_glfw.win32.disabledCursorWindow != window)
|
||||
break;
|
||||
|
||||
GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
|
||||
if (size > (UINT) _glfw.win32.rawInputSize)
|
||||
{
|
||||
free(_glfw.win32.rawInput);
|
||||
_glfw.win32.rawInput = calloc(size, 1);
|
||||
_glfw.win32.rawInputSize = size;
|
||||
}
|
||||
|
||||
size = _glfw.win32.rawInputSize;
|
||||
if (GetRawInputData(ri, RID_INPUT,
|
||||
_glfw.win32.rawInput, &size,
|
||||
sizeof(RAWINPUTHEADER)) == (UINT) -1)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to retrieve raw input data");
|
||||
break;
|
||||
}
|
||||
|
||||
data = _glfw.win32.rawInput;
|
||||
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
|
||||
{
|
||||
dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
|
||||
dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
|
||||
}
|
||||
else
|
||||
{
|
||||
dx = data->data.mouse.lLastX;
|
||||
dy = data->data.mouse.lLastY;
|
||||
}
|
||||
|
||||
_glfwInputCursorPos(window,
|
||||
window->virtualCursorPosX + dx,
|
||||
window->virtualCursorPosY + dy);
|
||||
|
||||
window->win32.lastCursorPosX += dx;
|
||||
window->win32.lastCursorPosY += dy;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
{
|
||||
window->win32.cursorTracked = GLFW_FALSE;
|
||||
@@ -666,7 +750,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
case WM_MOUSEHWHEEL:
|
||||
{
|
||||
// This message is only sent on Windows Vista and later
|
||||
// NOTE: The X-axis is inverted for consistency with OS X and X11.
|
||||
// NOTE: The X-axis is inverted for consistency with macOS and X11
|
||||
_glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
|
||||
return 0;
|
||||
}
|
||||
@@ -691,36 +775,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
|
||||
case WM_SIZE:
|
||||
{
|
||||
const GLFWbool iconified =
|
||||
!window->win32.iconified && wParam == SIZE_MINIMIZED;
|
||||
const GLFWbool restored =
|
||||
window->win32.iconified &&
|
||||
(wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);
|
||||
const GLFWbool iconified = wParam == SIZE_MINIMIZED;
|
||||
const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
|
||||
(window->win32.maximized &&
|
||||
wParam != SIZE_RESTORED);
|
||||
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
updateClipRect(window);
|
||||
|
||||
if (iconified)
|
||||
_glfwInputWindowIconify(window, GLFW_TRUE);
|
||||
else if (restored)
|
||||
_glfwInputWindowIconify(window, GLFW_FALSE);
|
||||
if (window->win32.iconified != iconified)
|
||||
_glfwInputWindowIconify(window, iconified);
|
||||
|
||||
if (window->win32.maximized != maximized)
|
||||
_glfwInputWindowMaximize(window, maximized);
|
||||
|
||||
_glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
|
||||
_glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
|
||||
|
||||
if (iconified)
|
||||
if (window->monitor && window->win32.iconified != iconified)
|
||||
{
|
||||
window->win32.iconified = GLFW_TRUE;
|
||||
if (window->monitor)
|
||||
if (iconified)
|
||||
releaseMonitor(window);
|
||||
}
|
||||
else if (restored)
|
||||
{
|
||||
window->win32.iconified = GLFW_FALSE;
|
||||
if (window->monitor)
|
||||
else
|
||||
acquireMonitor(window);
|
||||
}
|
||||
|
||||
window->win32.iconified = iconified;
|
||||
window->win32.maximized = maximized;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -850,9 +931,10 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
||||
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
// Creates the GLFW window and rendering context
|
||||
// Creates the GLFW window
|
||||
//
|
||||
static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||
static int createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig)
|
||||
{
|
||||
int xpos, ypos, fullWidth, fullHeight;
|
||||
WCHAR* wideTitle;
|
||||
@@ -865,7 +947,7 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||
|
||||
// NOTE: This window placement is temporary and approximate, as the
|
||||
// correct position and size cannot be known until the monitor
|
||||
// video mode has been set
|
||||
// video mode has been picked in _glfwSetVideoModeWin32
|
||||
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
||||
fullWidth = mode.width;
|
||||
@@ -886,11 +968,7 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||
|
||||
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
|
||||
if (!wideTitle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert window title to UTF-16");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
window->win32.handle = CreateWindowExW(exStyle,
|
||||
_GLFW_WNDCLASSNAME,
|
||||
@@ -907,7 +985,8 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||
|
||||
if (!window->win32.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create window");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -928,21 +1007,6 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
|
||||
// Destroys the GLFW window and rendering context
|
||||
//
|
||||
static void destroyWindow(_GLFWwindow* window)
|
||||
{
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
|
||||
if (window->win32.handle)
|
||||
{
|
||||
RemovePropW(window->win32.handle, L"GLFW");
|
||||
DestroyWindow(window->win32.handle);
|
||||
window->win32.handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// GLFW internal API //////
|
||||
@@ -976,8 +1040,8 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
|
||||
|
||||
if (!RegisterClassExW(&wc))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register window class");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register window class");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -1001,63 +1065,32 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!createWindow(window, wndconfig))
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitWGL())
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
|
||||
status = _glfwAnalyzeContextWGL(window, ctxconfig, fbconfig);
|
||||
|
||||
if (status == _GLFW_RECREATION_IMPOSSIBLE)
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (status == _GLFW_RECREATION_REQUIRED)
|
||||
{
|
||||
// Some window hints require us to re-create the context using WGL
|
||||
// extensions retrieved through the current context, as we cannot
|
||||
// check for WGL extensions or retrieve WGL entry points before we
|
||||
// have a current context (actually until we have implicitly loaded
|
||||
// the vendor ICD)
|
||||
|
||||
// Yes, this is strange, and yes, this is the proper way on WGL
|
||||
|
||||
// As Windows only allows you to set the pixel format once for
|
||||
// a window, we need to destroy the current window and create a new
|
||||
// one to be able to use the new pixel format
|
||||
|
||||
// Technically, it may be possible to keep the old window around if
|
||||
// we're just creating an OpenGL 3.0+ context with the same pixel
|
||||
// format, but it's not worth the added code complexity
|
||||
|
||||
// First we clear the current context (the one we just created)
|
||||
// This is usually done by glfwDestroyWindow, but as we're not doing
|
||||
// full GLFW window destruction, it's duplicated here
|
||||
window->context.makeCurrent(NULL);
|
||||
|
||||
// Next destroy the Win32 window and WGL context (without resetting
|
||||
// or destroying the GLFW window object)
|
||||
window->context.destroy(window);
|
||||
destroyWindow(window);
|
||||
|
||||
// ...and then create them again, this time with better APIs
|
||||
if (!createWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
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 (window->monitor)
|
||||
@@ -1067,7 +1100,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (!acquireMonitor(window))
|
||||
return GLFW_FALSE;
|
||||
|
||||
centerCursor(window);
|
||||
if (wndconfig->centerCursor)
|
||||
centerCursor(window);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
@@ -1078,10 +1112,18 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
if (window->monitor)
|
||||
releaseMonitor(window);
|
||||
|
||||
if (window->context.client != GLFW_NO_API)
|
||||
if (window->context.destroy)
|
||||
window->context.destroy(window);
|
||||
|
||||
destroyWindow(window);
|
||||
if (_glfw.win32.disabledCursorWindow == window)
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
|
||||
if (window->win32.handle)
|
||||
{
|
||||
RemovePropW(window->win32.handle, L"GLFW");
|
||||
DestroyWindow(window->win32.handle);
|
||||
window->win32.handle = NULL;
|
||||
}
|
||||
|
||||
if (window->win32.bigIcon)
|
||||
DestroyIcon(window->win32.bigIcon);
|
||||
@@ -1094,11 +1136,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
{
|
||||
WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
|
||||
if (!wideTitle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert window title to UTF-16");
|
||||
return;
|
||||
}
|
||||
|
||||
SetWindowTextW(window->win32.handle, wideTitle);
|
||||
free(wideTitle);
|
||||
@@ -1278,6 +1316,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
||||
ShowWindow(window->win32.handle, SW_HIDE);
|
||||
}
|
||||
|
||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
{
|
||||
FlashWindow(window->win32.handle, TRUE);
|
||||
}
|
||||
|
||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
{
|
||||
BringWindowToTop(window->win32.handle);
|
||||
@@ -1285,6 +1328,12 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
SetFocus(window->win32.handle);
|
||||
}
|
||||
|
||||
void _glfwPlatformDragWindow(_GLFWwindow* window)
|
||||
{
|
||||
ReleaseCapture();
|
||||
SendMessage(window->win32.handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
_GLFWmonitor* monitor,
|
||||
int xpos, int ypos,
|
||||
@@ -1391,6 +1440,23 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
return IsZoomed(window->win32.handle);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
updateWindowStyles(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
updateWindowStyles(window);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
||||
{
|
||||
const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
|
||||
SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
MSG msg;
|
||||
@@ -1401,9 +1467,9 @@ void _glfwPlatformPollEvents(void)
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
// Treat WM_QUIT as a close on all windows
|
||||
// While GLFW does not itself post WM_QUIT, other processes may post
|
||||
// it to this one, for example Task Manager
|
||||
// NOTE: While GLFW does not itself post WM_QUIT, other processes
|
||||
// may post it to this one, for example Task Manager
|
||||
// HACK: Treat WM_QUIT as a close on all windows
|
||||
|
||||
window = _glfw.windowListHead;
|
||||
while (window)
|
||||
@@ -1422,25 +1488,28 @@ void _glfwPlatformPollEvents(void)
|
||||
handle = GetActiveWindow();
|
||||
if (handle)
|
||||
{
|
||||
// LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
|
||||
// This is the only async event handling in GLFW, but it solves some
|
||||
// nasty problems
|
||||
// NOTE: Shift keys on Windows tend to "stick" when both are pressed as
|
||||
// no key up message is generated by the first key release
|
||||
// The other half of this is in the handling of WM_KEYUP
|
||||
// HACK: Query actual key state and synthesize release events as needed
|
||||
window = GetPropW(handle, L"GLFW");
|
||||
if (window)
|
||||
{
|
||||
const int mods = getAsyncKeyMods();
|
||||
const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
|
||||
const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
|
||||
|
||||
// Get current state of left and right shift keys
|
||||
const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
|
||||
const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
|
||||
|
||||
// See if this differs from our belief of what has happened
|
||||
// (we only have to check for lost key up events)
|
||||
if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);
|
||||
|
||||
if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
|
||||
if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
|
||||
{
|
||||
const int mods = getAsyncKeyMods();
|
||||
const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
|
||||
_glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
|
||||
}
|
||||
else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
|
||||
{
|
||||
const int mods = getAsyncKeyMods();
|
||||
const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
|
||||
_glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1476,8 +1545,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
|
||||
void _glfwPlatformPostEmptyEvent(void)
|
||||
{
|
||||
_GLFWwindow* window = _glfw.windowListHead;
|
||||
PostMessage(window->win32.handle, WM_NULL, 0, 0);
|
||||
PostMessage(_glfw.win32.helperWindowHandle, WM_NULL, 0, 0);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||
@@ -1511,36 +1579,46 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
||||
{
|
||||
if (mode == GLFW_CURSOR_DISABLED)
|
||||
{
|
||||
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
|
||||
|
||||
_glfw.win32.disabledCursorWindow = window;
|
||||
_glfwPlatformGetCursorPos(window,
|
||||
&_glfw.win32.restoreCursorPosX,
|
||||
&_glfw.win32.restoreCursorPosY);
|
||||
centerCursor(window);
|
||||
updateClipRect(window);
|
||||
|
||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to register raw input device");
|
||||
}
|
||||
}
|
||||
else if (_glfw.win32.disabledCursorWindow == window)
|
||||
{
|
||||
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
|
||||
|
||||
_glfw.win32.disabledCursorWindow = NULL;
|
||||
updateClipRect(NULL);
|
||||
_glfwPlatformSetCursorPos(window,
|
||||
_glfw.win32.restoreCursorPosX,
|
||||
_glfw.win32.restoreCursorPosY);
|
||||
|
||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to remove raw input device");
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorInClientArea(window))
|
||||
updateCursorImage(window);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
||||
{
|
||||
WCHAR name[16];
|
||||
|
||||
if (key != GLFW_KEY_UNKNOWN)
|
||||
scancode = _glfw.win32.nativeKeys[key];
|
||||
|
||||
if (!_glfwIsPrintable(_glfw.win32.publicKeys[scancode]))
|
||||
return NULL;
|
||||
|
||||
if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR)))
|
||||
return NULL;
|
||||
|
||||
@@ -1555,6 +1633,11 @@ const char* _glfwPlatformGetKeyName(int key, int scancode)
|
||||
return _glfw.win32.keyName;
|
||||
}
|
||||
|
||||
int _glfwPlatformGetKeyScancode(int key)
|
||||
{
|
||||
return _glfw.win32.scancodes[key];
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
@@ -1572,8 +1655,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
|
||||
if (!cursor->win32.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create standard cursor");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create standard cursor");
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
@@ -1594,101 +1677,93 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||
|
||||
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
|
||||
{
|
||||
WCHAR* wideString;
|
||||
HANDLE stringHandle;
|
||||
size_t wideSize;
|
||||
int characterCount;
|
||||
HANDLE object;
|
||||
WCHAR* buffer;
|
||||
|
||||
wideString = _glfwCreateWideStringFromUTF8Win32(string);
|
||||
if (!wideString)
|
||||
characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
|
||||
if (!characterCount)
|
||||
return;
|
||||
|
||||
object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
|
||||
if (!object)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert string to UTF-16");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to allocate global handle for clipboard");
|
||||
return;
|
||||
}
|
||||
|
||||
wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR);
|
||||
|
||||
stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize);
|
||||
if (!stringHandle)
|
||||
buffer = GlobalLock(object);
|
||||
if (!buffer)
|
||||
{
|
||||
free(wideString);
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to allocate global handle for clipboard");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to lock global handle");
|
||||
GlobalFree(object);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(GlobalLock(stringHandle), wideString, wideSize);
|
||||
GlobalUnlock(stringHandle);
|
||||
MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
|
||||
GlobalUnlock(object);
|
||||
|
||||
if (!OpenClipboard(_glfw.win32.helperWindowHandle))
|
||||
{
|
||||
GlobalFree(stringHandle);
|
||||
free(wideString);
|
||||
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to open clipboard");
|
||||
GlobalFree(object);
|
||||
return;
|
||||
}
|
||||
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_UNICODETEXT, stringHandle);
|
||||
SetClipboardData(CF_UNICODETEXT, object);
|
||||
CloseClipboard();
|
||||
|
||||
free(wideString);
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
|
||||
{
|
||||
HANDLE stringHandle;
|
||||
HANDLE object;
|
||||
WCHAR* buffer;
|
||||
|
||||
if (!OpenClipboard(_glfw.win32.helperWindowHandle))
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to open clipboard");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stringHandle = GetClipboardData(CF_UNICODETEXT);
|
||||
if (!stringHandle)
|
||||
object = GetClipboardData(CF_UNICODETEXT);
|
||||
if (!object)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
|
||||
"Win32: Failed to convert clipboard to string");
|
||||
CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"Win32: Failed to convert clipboard to string");
|
||||
buffer = GlobalLock(object);
|
||||
if (!buffer)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to lock global handle");
|
||||
CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(_glfw.win32.clipboardString);
|
||||
_glfw.win32.clipboardString =
|
||||
_glfwCreateUTF8FromWideStringWin32(GlobalLock(stringHandle));
|
||||
_glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
|
||||
|
||||
GlobalUnlock(stringHandle);
|
||||
GlobalUnlock(object);
|
||||
CloseClipboard();
|
||||
|
||||
if (!_glfw.win32.clipboardString)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to convert wide string to UTF-8");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return _glfw.win32.clipboardString;
|
||||
}
|
||||
|
||||
char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
char** extensions;
|
||||
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
|
||||
return;
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!_glfw.vk.KHR_win32_surface)
|
||||
return NULL;
|
||||
|
||||
extensions = calloc(2, sizeof(char*));
|
||||
extensions[0] = strdup("VK_KHR_surface");
|
||||
extensions[1] = strdup("VK_KHR_win32_surface");
|
||||
|
||||
*count = 2;
|
||||
return extensions;
|
||||
extensions[0] = "VK_KHR_surface";
|
||||
extensions[1] = "VK_KHR_win32_surface";
|
||||
}
|
||||
|
||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
|
||||
+145
-31
@@ -1,8 +1,8 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 - www.glfw.org
|
||||
// GLFW 3.3 - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
@@ -40,30 +40,26 @@
|
||||
|
||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
||||
{
|
||||
if (focused)
|
||||
{
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
|
||||
if (window->callbacks.focus)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
if (!focused)
|
||||
{
|
||||
int key, button;
|
||||
|
||||
// Release all pressed keyboard keys
|
||||
for (i = 0; i <= GLFW_KEY_LAST; i++)
|
||||
for (key = 0; key <= GLFW_KEY_LAST; key++)
|
||||
{
|
||||
if (window->keys[i] == GLFW_PRESS)
|
||||
_glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
|
||||
if (window->keys[key] == GLFW_PRESS)
|
||||
{
|
||||
const int scancode = _glfwPlatformGetKeyScancode(key);
|
||||
_glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Release all pressed mouse buttons
|
||||
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||
for (button = 0; button <= GLFW_MOUSE_BUTTON_LAST; button++)
|
||||
{
|
||||
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||
_glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
|
||||
if (window->mouseButtons[button] == GLFW_PRESS)
|
||||
_glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +82,12 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
||||
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
||||
}
|
||||
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
||||
{
|
||||
if (window->callbacks.maximize)
|
||||
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
||||
}
|
||||
|
||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
||||
{
|
||||
if (window->callbacks.fbsize)
|
||||
@@ -100,7 +102,7 @@ void _glfwInputWindowDamage(_GLFWwindow* window)
|
||||
|
||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||
{
|
||||
window->closed = GLFW_TRUE;
|
||||
window->shouldClose = GLFW_TRUE;
|
||||
|
||||
if (window->callbacks.close)
|
||||
window->callbacks.close((GLFWwindow*) window);
|
||||
@@ -128,6 +130,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
_GLFWwindow* previous;
|
||||
|
||||
assert(title != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
@@ -151,7 +155,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
|
||||
if (ctxconfig.share)
|
||||
{
|
||||
if (ctxconfig.share->context.client == GLFW_NO_API)
|
||||
if (ctxconfig.client == GLFW_NO_API ||
|
||||
ctxconfig.share->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return NULL;
|
||||
@@ -187,7 +192,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
window->denom = GLFW_DONT_CARE;
|
||||
|
||||
// Save the currently current context so it can be restored later
|
||||
previous = _glfwPlatformGetCurrentContext();
|
||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
if (ctxconfig.client != GLFW_NO_API)
|
||||
glfwMakeContextCurrent(NULL);
|
||||
|
||||
@@ -232,15 +237,15 @@ void glfwDefaultWindowHints(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
|
||||
|
||||
// The default is OpenGL with minimum version 1.0
|
||||
memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
|
||||
_glfw.hints.context.client = GLFW_OPENGL_API;
|
||||
_glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
|
||||
_glfw.hints.context.major = 1;
|
||||
_glfw.hints.context.minor = 0;
|
||||
|
||||
// The default is a focused, visible, resizable window with decorations
|
||||
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||
_glfw.hints.window.visible = GLFW_TRUE;
|
||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||
@@ -249,6 +254,7 @@ void glfwDefaultWindowHints(void)
|
||||
|
||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||
// double buffered
|
||||
memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
|
||||
_glfw.hints.framebuffer.redBits = 8;
|
||||
_glfw.hints.framebuffer.greenBits = 8;
|
||||
_glfw.hints.framebuffer.blueBits = 8;
|
||||
@@ -259,6 +265,9 @@ void glfwDefaultWindowHints(void)
|
||||
|
||||
// The default is to select the highest available refresh rate
|
||||
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
||||
|
||||
// The default is to use full Retina resolution framebuffers
|
||||
_glfw.hints.window.ns.retina = GLFW_TRUE;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
@@ -333,6 +342,18 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
case GLFW_VISIBLE:
|
||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
case GLFW_COCOA_FRAME_AUTOSAVE:
|
||||
_glfw.hints.window.ns.frame = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
||||
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
case GLFW_CENTER_CURSOR:
|
||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
break;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
break;
|
||||
@@ -367,7 +388,7 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
_glfw.hints.refreshRate = value;
|
||||
break;
|
||||
default:
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -387,7 +408,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
|
||||
|
||||
// The window's context must not be current on another thread when the
|
||||
// window is destroyed
|
||||
if (window == _glfwPlatformGetCurrentContext())
|
||||
if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
|
||||
glfwMakeContextCurrent(NULL);
|
||||
|
||||
_glfwPlatformDestroyWindow(window);
|
||||
@@ -411,7 +432,7 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||
return window->closed;
|
||||
return window->shouldClose;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
|
||||
@@ -420,14 +441,13 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
window->closed = value;
|
||||
window->shouldClose = value;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
assert(title != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
@@ -491,6 +511,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -549,6 +571,8 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
assert(numer != 0);
|
||||
assert(denom != 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -627,7 +651,13 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow* handle)
|
||||
GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (window->monitor)
|
||||
return;
|
||||
|
||||
_glfwPlatformMaximizeWindow(window);
|
||||
}
|
||||
|
||||
@@ -645,6 +675,16 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
_glfwPlatformRequestWindowAttention(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -668,6 +708,16 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI void glfwDragWindow(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
_glfwPlatformDragWindow(window);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -691,6 +741,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return window->decorated;
|
||||
case GLFW_FLOATING:
|
||||
return window->floating;
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
return window->autoIconify;
|
||||
case GLFW_CLIENT_API:
|
||||
return window->context.client;
|
||||
case GLFW_CONTEXT_CREATION_API:
|
||||
@@ -715,10 +767,56 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return window->context.noerror;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
|
||||
switch (attrib)
|
||||
{
|
||||
case GLFW_RESIZABLE:
|
||||
if (window->resizable != value)
|
||||
{
|
||||
window->resizable = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowResizable(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_DECORATED:
|
||||
if (window->decorated != value)
|
||||
{
|
||||
window->decorated = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowDecorated(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_FLOATING:
|
||||
if (window->floating != value)
|
||||
{
|
||||
window->floating = value;
|
||||
if (!window->monitor)
|
||||
_glfwPlatformSetWindowFloating(window, value);
|
||||
}
|
||||
return;
|
||||
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
window->autoIconify = value;
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
|
||||
}
|
||||
|
||||
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -737,6 +835,8 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
||||
_GLFWwindow* window = (_GLFWwindow*) wh;
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
|
||||
assert(window != NULL);
|
||||
assert(width >= 0);
|
||||
assert(height >= 0);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
@@ -849,6 +949,17 @@ GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
|
||||
GLFWwindowmaximizefun cbfun)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
_GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
|
||||
return cbfun;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
|
||||
GLFWframebuffersizefun cbfun)
|
||||
{
|
||||
@@ -879,6 +990,9 @@ GLFWAPI void glfwWaitEvents(void)
|
||||
GLFWAPI void glfwWaitEventsTimeout(double timeout)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
assert(timeout == timeout);
|
||||
assert(timeout >= 0.0);
|
||||
assert(timeout <= DBL_MAX);
|
||||
|
||||
if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
|
||||
{
|
||||
|
||||
+259
-174
@@ -1,5 +1,5 @@
|
||||
//========================================================================
|
||||
// GLFW 3.2 Wayland - www.glfw.org
|
||||
// GLFW 3.3 Wayland - www.glfw.org
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||
//
|
||||
@@ -109,6 +109,8 @@ static void pointerHandleButton(void* data,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
_glfw.wl.pointerSerial = serial;
|
||||
|
||||
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
|
||||
* codes. */
|
||||
glfwButton = button - BTN_LEFT;
|
||||
@@ -128,7 +130,7 @@ static void pointerHandleAxis(void* data,
|
||||
wl_fixed_t value)
|
||||
{
|
||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||
double scroll_factor;
|
||||
double scrollFactor;
|
||||
double x, y;
|
||||
|
||||
if (!window)
|
||||
@@ -137,17 +139,17 @@ static void pointerHandleAxis(void* data,
|
||||
/* Wayland scroll events are in pointer motion coordinate space (think
|
||||
* two finger scroll). The factor 10 is commonly used to convert to
|
||||
* "scroll step means 1.0. */
|
||||
scroll_factor = 1.0/10.0;
|
||||
scrollFactor = 1.0/10.0;
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
|
||||
x = wl_fixed_to_double(value) * scroll_factor;
|
||||
x = wl_fixed_to_double(value) * scrollFactor;
|
||||
y = 0.0;
|
||||
break;
|
||||
case WL_POINTER_AXIS_VERTICAL_SCROLL:
|
||||
x = 0.0;
|
||||
y = wl_fixed_to_double(value) * scroll_factor;
|
||||
y = wl_fixed_to_double(value) * scrollFactor;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -172,7 +174,10 @@ static void keyboardHandleKeymap(void* data,
|
||||
{
|
||||
struct xkb_keymap* keymap;
|
||||
struct xkb_state* state;
|
||||
struct xkb_compose_table* composeTable;
|
||||
struct xkb_compose_state* composeState;
|
||||
char* mapStr;
|
||||
const char* locale;
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||
{
|
||||
@@ -186,10 +191,10 @@ static void keyboardHandleKeymap(void* data,
|
||||
return;
|
||||
}
|
||||
|
||||
keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
|
||||
mapStr,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
0);
|
||||
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
|
||||
mapStr,
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
||||
0);
|
||||
munmap(mapStr, size);
|
||||
close(fd);
|
||||
|
||||
@@ -205,23 +210,52 @@ static void keyboardHandleKeymap(void* data,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB state");
|
||||
xkb_map_unref(keymap);
|
||||
xkb_keymap_unref(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
// Look up the preferred locale, falling back to "C" as default.
|
||||
locale = getenv("LC_ALL");
|
||||
if (!locale)
|
||||
locale = getenv("LC_CTYPE");
|
||||
if (!locale)
|
||||
locale = getenv("LANG");
|
||||
if (!locale)
|
||||
locale = "C";
|
||||
|
||||
composeTable =
|
||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
if (composeTable)
|
||||
{
|
||||
composeState =
|
||||
xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
xkb_compose_table_unref(composeTable);
|
||||
if (composeState)
|
||||
_glfw.wl.xkb.composeState = composeState;
|
||||
else
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB compose state");
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to create XKB compose table");
|
||||
}
|
||||
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
_glfw.wl.xkb.keymap = keymap;
|
||||
_glfw.wl.xkb.state = state;
|
||||
|
||||
_glfw.wl.xkb.control_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
||||
_glfw.wl.xkb.alt_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
||||
_glfw.wl.xkb.shift_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||
_glfw.wl.xkb.super_mask =
|
||||
1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||
_glfw.wl.xkb.controlMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
||||
_glfw.wl.xkb.altMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
||||
_glfw.wl.xkb.shiftMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
||||
_glfw.wl.xkb.superMask =
|
||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
||||
}
|
||||
|
||||
static void keyboardHandleEnter(void* data,
|
||||
@@ -252,12 +286,55 @@ static void keyboardHandleLeave(void* data,
|
||||
|
||||
static int toGLFWKeyCode(uint32_t key)
|
||||
{
|
||||
if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))
|
||||
return _glfw.wl.publicKeys[key];
|
||||
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
||||
return _glfw.wl.keycodes[key];
|
||||
|
||||
return GLFW_KEY_UNKNOWN;
|
||||
}
|
||||
|
||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||
{
|
||||
if (sym == XKB_KEY_NoSymbol)
|
||||
return sym;
|
||||
if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
|
||||
!= XKB_COMPOSE_FEED_ACCEPTED)
|
||||
return sym;
|
||||
switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
|
||||
{
|
||||
case XKB_COMPOSE_COMPOSED:
|
||||
return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
|
||||
case XKB_COMPOSE_COMPOSING:
|
||||
case XKB_COMPOSE_CANCELLED:
|
||||
return XKB_KEY_NoSymbol;
|
||||
case XKB_COMPOSE_NOTHING:
|
||||
default:
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
|
||||
static void inputChar(_GLFWwindow* window, uint32_t key)
|
||||
{
|
||||
uint32_t code, numSyms;
|
||||
long cp;
|
||||
const xkb_keysym_t *syms;
|
||||
xkb_keysym_t sym;
|
||||
|
||||
code = key + 8;
|
||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||
|
||||
if (numSyms == 1)
|
||||
{
|
||||
sym = composeSymbol(syms[0]);
|
||||
cp = _glfwKeySym2Unicode(sym);
|
||||
if (cp != -1)
|
||||
{
|
||||
const int mods = _glfw.wl.xkb.modifiers;
|
||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||
_glfwInputChar(window, cp, mods, plain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboardHandleKey(void* data,
|
||||
struct wl_keyboard* keyboard,
|
||||
uint32_t serial,
|
||||
@@ -265,11 +342,8 @@ static void keyboardHandleKey(void* data,
|
||||
uint32_t key,
|
||||
uint32_t state)
|
||||
{
|
||||
uint32_t code, num_syms;
|
||||
long cp;
|
||||
int keyCode;
|
||||
int action;
|
||||
const xkb_keysym_t *syms;
|
||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||
|
||||
if (!window)
|
||||
@@ -282,19 +356,8 @@ static void keyboardHandleKey(void* data,
|
||||
_glfwInputKey(window, keyCode, key, action,
|
||||
_glfw.wl.xkb.modifiers);
|
||||
|
||||
code = key + 8;
|
||||
num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||
|
||||
if (num_syms == 1)
|
||||
{
|
||||
cp = _glfwKeySym2Unicode(syms[0]);
|
||||
if (cp != -1)
|
||||
{
|
||||
const int mods = _glfw.wl.xkb.modifiers;
|
||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||
_glfwInputChar(window, cp, mods, plain);
|
||||
}
|
||||
}
|
||||
if (action == GLFW_PRESS)
|
||||
inputChar(window, key);
|
||||
}
|
||||
|
||||
static void keyboardHandleModifiers(void* data,
|
||||
@@ -320,15 +383,17 @@ static void keyboardHandleModifiers(void* data,
|
||||
group);
|
||||
|
||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
||||
XKB_STATE_DEPRESSED |
|
||||
XKB_STATE_LATCHED);
|
||||
if (mask & _glfw.wl.xkb.control_mask)
|
||||
XKB_STATE_MODS_DEPRESSED |
|
||||
XKB_STATE_LAYOUT_DEPRESSED |
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_LAYOUT_LATCHED);
|
||||
if (mask & _glfw.wl.xkb.controlMask)
|
||||
modifiers |= GLFW_MOD_CONTROL;
|
||||
if (mask & _glfw.wl.xkb.alt_mask)
|
||||
if (mask & _glfw.wl.xkb.altMask)
|
||||
modifiers |= GLFW_MOD_ALT;
|
||||
if (mask & _glfw.wl.xkb.shift_mask)
|
||||
if (mask & _glfw.wl.xkb.shiftMask)
|
||||
modifiers |= GLFW_MOD_SHIFT;
|
||||
if (mask & _glfw.wl.xkb.super_mask)
|
||||
if (mask & _glfw.wl.xkb.superMask)
|
||||
modifiers |= GLFW_MOD_SUPER;
|
||||
_glfw.wl.xkb.modifiers = modifiers;
|
||||
}
|
||||
@@ -380,10 +445,10 @@ static void registryHandleGlobal(void* data,
|
||||
{
|
||||
if (strcmp(interface, "wl_compositor") == 0)
|
||||
{
|
||||
_glfw.wl.wl_compositor_version = min(3, version);
|
||||
_glfw.wl.compositorVersion = min(3, version);
|
||||
_glfw.wl.compositor =
|
||||
wl_registry_bind(registry, name, &wl_compositor_interface,
|
||||
_glfw.wl.wl_compositor_version);
|
||||
_glfw.wl.compositorVersion);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shm") == 0)
|
||||
{
|
||||
@@ -440,124 +505,134 @@ static const struct wl_registry_listener registryListener = {
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
{
|
||||
memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys));
|
||||
int scancode;
|
||||
|
||||
_glfw.wl.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.wl.publicKeys[KEY_1] = GLFW_KEY_1;
|
||||
_glfw.wl.publicKeys[KEY_2] = GLFW_KEY_2;
|
||||
_glfw.wl.publicKeys[KEY_3] = GLFW_KEY_3;
|
||||
_glfw.wl.publicKeys[KEY_4] = GLFW_KEY_4;
|
||||
_glfw.wl.publicKeys[KEY_5] = GLFW_KEY_5;
|
||||
_glfw.wl.publicKeys[KEY_6] = GLFW_KEY_6;
|
||||
_glfw.wl.publicKeys[KEY_7] = GLFW_KEY_7;
|
||||
_glfw.wl.publicKeys[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.wl.publicKeys[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.wl.publicKeys[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.wl.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.wl.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.wl.publicKeys[KEY_Q] = GLFW_KEY_Q;
|
||||
_glfw.wl.publicKeys[KEY_W] = GLFW_KEY_W;
|
||||
_glfw.wl.publicKeys[KEY_E] = GLFW_KEY_E;
|
||||
_glfw.wl.publicKeys[KEY_R] = GLFW_KEY_R;
|
||||
_glfw.wl.publicKeys[KEY_T] = GLFW_KEY_T;
|
||||
_glfw.wl.publicKeys[KEY_Y] = GLFW_KEY_Y;
|
||||
_glfw.wl.publicKeys[KEY_U] = GLFW_KEY_U;
|
||||
_glfw.wl.publicKeys[KEY_I] = GLFW_KEY_I;
|
||||
_glfw.wl.publicKeys[KEY_O] = GLFW_KEY_O;
|
||||
_glfw.wl.publicKeys[KEY_P] = GLFW_KEY_P;
|
||||
_glfw.wl.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.wl.publicKeys[KEY_A] = GLFW_KEY_A;
|
||||
_glfw.wl.publicKeys[KEY_S] = GLFW_KEY_S;
|
||||
_glfw.wl.publicKeys[KEY_D] = GLFW_KEY_D;
|
||||
_glfw.wl.publicKeys[KEY_F] = GLFW_KEY_F;
|
||||
_glfw.wl.publicKeys[KEY_G] = GLFW_KEY_G;
|
||||
_glfw.wl.publicKeys[KEY_H] = GLFW_KEY_H;
|
||||
_glfw.wl.publicKeys[KEY_J] = GLFW_KEY_J;
|
||||
_glfw.wl.publicKeys[KEY_K] = GLFW_KEY_K;
|
||||
_glfw.wl.publicKeys[KEY_L] = GLFW_KEY_L;
|
||||
_glfw.wl.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.wl.publicKeys[KEY_Z] = GLFW_KEY_Z;
|
||||
_glfw.wl.publicKeys[KEY_X] = GLFW_KEY_X;
|
||||
_glfw.wl.publicKeys[KEY_C] = GLFW_KEY_C;
|
||||
_glfw.wl.publicKeys[KEY_V] = GLFW_KEY_V;
|
||||
_glfw.wl.publicKeys[KEY_B] = GLFW_KEY_B;
|
||||
_glfw.wl.publicKeys[KEY_N] = GLFW_KEY_N;
|
||||
_glfw.wl.publicKeys[KEY_M] = GLFW_KEY_M;
|
||||
_glfw.wl.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
|
||||
_glfw.wl.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
|
||||
_glfw.wl.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
|
||||
_glfw.wl.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.wl.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
|
||||
_glfw.wl.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
|
||||
_glfw.wl.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.wl.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.wl.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.wl.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.wl.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.wl.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.wl.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.wl.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
|
||||
_glfw.wl.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.wl.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.wl.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.wl.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
||||
_glfw.wl.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
|
||||
_glfw.wl.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.wl.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
|
||||
_glfw.wl.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
|
||||
_glfw.wl.publicKeys[KEY_END] = GLFW_KEY_END;
|
||||
_glfw.wl.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.wl.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.wl.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
|
||||
_glfw.wl.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
|
||||
_glfw.wl.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
||||
_glfw.wl.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
|
||||
_glfw.wl.publicKeys[KEY_UP] = GLFW_KEY_UP;
|
||||
_glfw.wl.publicKeys[KEY_F1] = GLFW_KEY_F1;
|
||||
_glfw.wl.publicKeys[KEY_F2] = GLFW_KEY_F2;
|
||||
_glfw.wl.publicKeys[KEY_F3] = GLFW_KEY_F3;
|
||||
_glfw.wl.publicKeys[KEY_F4] = GLFW_KEY_F4;
|
||||
_glfw.wl.publicKeys[KEY_F5] = GLFW_KEY_F5;
|
||||
_glfw.wl.publicKeys[KEY_F6] = GLFW_KEY_F6;
|
||||
_glfw.wl.publicKeys[KEY_F7] = GLFW_KEY_F7;
|
||||
_glfw.wl.publicKeys[KEY_F8] = GLFW_KEY_F8;
|
||||
_glfw.wl.publicKeys[KEY_F9] = GLFW_KEY_F9;
|
||||
_glfw.wl.publicKeys[KEY_F10] = GLFW_KEY_F10;
|
||||
_glfw.wl.publicKeys[KEY_F11] = GLFW_KEY_F11;
|
||||
_glfw.wl.publicKeys[KEY_F12] = GLFW_KEY_F12;
|
||||
_glfw.wl.publicKeys[KEY_F13] = GLFW_KEY_F13;
|
||||
_glfw.wl.publicKeys[KEY_F14] = GLFW_KEY_F14;
|
||||
_glfw.wl.publicKeys[KEY_F15] = GLFW_KEY_F15;
|
||||
_glfw.wl.publicKeys[KEY_F16] = GLFW_KEY_F16;
|
||||
_glfw.wl.publicKeys[KEY_F17] = GLFW_KEY_F17;
|
||||
_glfw.wl.publicKeys[KEY_F18] = GLFW_KEY_F18;
|
||||
_glfw.wl.publicKeys[KEY_F19] = GLFW_KEY_F19;
|
||||
_glfw.wl.publicKeys[KEY_F20] = GLFW_KEY_F20;
|
||||
_glfw.wl.publicKeys[KEY_F21] = GLFW_KEY_F21;
|
||||
_glfw.wl.publicKeys[KEY_F22] = GLFW_KEY_F22;
|
||||
_glfw.wl.publicKeys[KEY_F23] = GLFW_KEY_F23;
|
||||
_glfw.wl.publicKeys[KEY_F24] = GLFW_KEY_F24;
|
||||
_glfw.wl.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.wl.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.wl.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.wl.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_glfw.wl.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
|
||||
_glfw.wl.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
|
||||
_glfw.wl.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
|
||||
_glfw.wl.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
|
||||
_glfw.wl.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
|
||||
_glfw.wl.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
|
||||
_glfw.wl.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
|
||||
_glfw.wl.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
|
||||
_glfw.wl.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
|
||||
_glfw.wl.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
|
||||
_glfw.wl.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.wl.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.wl.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
|
||||
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
|
||||
|
||||
_glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
||||
_glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
|
||||
_glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
|
||||
_glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
|
||||
_glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
|
||||
_glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
|
||||
_glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
|
||||
_glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
|
||||
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
|
||||
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
||||
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
||||
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
||||
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
||||
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
||||
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
||||
_glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
|
||||
_glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
|
||||
_glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
|
||||
_glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
|
||||
_glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
|
||||
_glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
|
||||
_glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
|
||||
_glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
|
||||
_glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
|
||||
_glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
||||
_glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
||||
_glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
|
||||
_glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
|
||||
_glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
|
||||
_glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
|
||||
_glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
|
||||
_glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
|
||||
_glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
|
||||
_glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
|
||||
_glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
|
||||
_glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
||||
_glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
||||
_glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
|
||||
_glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
|
||||
_glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
|
||||
_glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
|
||||
_glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
|
||||
_glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
|
||||
_glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
|
||||
_glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
||||
_glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
||||
_glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
||||
_glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
||||
_glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
||||
_glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
||||
_glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
||||
_glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
||||
_glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
||||
_glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
||||
_glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
||||
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
||||
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
||||
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
||||
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
||||
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
||||
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
||||
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
||||
_glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
||||
_glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
||||
_glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
||||
_glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
||||
_glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
||||
_glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
||||
_glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
|
||||
_glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
||||
_glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
||||
_glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
||||
_glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
||||
_glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
||||
_glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
||||
_glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
|
||||
_glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
|
||||
_glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
|
||||
_glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
|
||||
_glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
|
||||
_glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
|
||||
_glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
|
||||
_glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
|
||||
_glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
|
||||
_glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
|
||||
_glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
|
||||
_glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
|
||||
_glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
|
||||
_glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
|
||||
_glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
|
||||
_glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
|
||||
_glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
|
||||
_glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
|
||||
_glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
|
||||
_glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
|
||||
_glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
|
||||
_glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
|
||||
_glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
|
||||
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
||||
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
||||
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
||||
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
||||
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
||||
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
||||
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
||||
_glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
||||
_glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
||||
_glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
||||
_glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
||||
_glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
||||
_glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
||||
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
||||
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
||||
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
||||
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
||||
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
||||
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
||||
|
||||
for (scancode = 0; scancode < 256; scancode++)
|
||||
{
|
||||
if (_glfw.wl.keycodes[scancode] > 0)
|
||||
_glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -578,9 +653,6 @@ int _glfwPlatformInit(void)
|
||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||
|
||||
_glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
|
||||
_glfw.wl.monitorsSize = 4;
|
||||
|
||||
createKeyTables();
|
||||
|
||||
_glfw.wl.xkb.context = xkb_context_new(0);
|
||||
@@ -597,12 +669,6 @@ int _glfwPlatformInit(void)
|
||||
// Sync so we got all initial output events
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
|
||||
if (!_glfwInitThreadLocalStoragePOSIX())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
|
||||
@@ -628,18 +694,39 @@ void _glfwPlatformTerminate(void)
|
||||
{
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateJoysticksLinux();
|
||||
_glfwTerminateThreadLocalStoragePOSIX();
|
||||
|
||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
||||
xkb_state_unref(_glfw.wl.xkb.state);
|
||||
xkb_context_unref(_glfw.wl.xkb.context);
|
||||
|
||||
if (_glfw.wl.cursorTheme)
|
||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||
if (_glfw.wl.cursorSurface)
|
||||
wl_surface_destroy(_glfw.wl.cursorSurface);
|
||||
if (_glfw.wl.compositor)
|
||||
wl_compositor_destroy(_glfw.wl.compositor);
|
||||
if (_glfw.wl.shm)
|
||||
wl_shm_destroy(_glfw.wl.shm);
|
||||
if (_glfw.wl.shell)
|
||||
wl_shell_destroy(_glfw.wl.shell);
|
||||
if (_glfw.wl.pointer)
|
||||
wl_pointer_destroy(_glfw.wl.pointer);
|
||||
if (_glfw.wl.keyboard)
|
||||
wl_keyboard_destroy(_glfw.wl.keyboard);
|
||||
if (_glfw.wl.seat)
|
||||
wl_seat_destroy(_glfw.wl.seat);
|
||||
if (_glfw.wl.relativePointerManager)
|
||||
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
|
||||
if (_glfw.wl.pointerConstraints)
|
||||
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
if (_glfw.wl.display)
|
||||
{
|
||||
wl_display_flush(_glfw.wl.display);
|
||||
if (_glfw.wl.display)
|
||||
wl_display_disconnect(_glfw.wl.display);
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
@@ -650,9 +737,7 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#else
|
||||
" gettimeofday"
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
" /dev/js"
|
||||
#endif
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" shared"
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user