Compare commits
499 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65b95999c1 | ||
|
|
056012871f | ||
|
|
c7b377080c | ||
|
|
47acc9ff2f | ||
|
|
fe62700825 | ||
|
|
6bcab56988 | ||
|
|
fbc4d3e1be | ||
|
|
c89d1643f4 | ||
|
|
e2226a1509 | ||
|
|
656916e0fa | ||
|
|
4a55eb9e7f | ||
|
|
9c8cf04a80 | ||
|
|
e846bc9308 | ||
|
|
3c7a71772c | ||
|
|
857a53e80f | ||
|
|
84fcabe5cf | ||
|
|
9dc410c9fd | ||
|
|
8ebad06e7e | ||
|
|
5db1a07f81 | ||
|
|
48e5c8edb3 | ||
|
|
eefc21920e | ||
|
|
d7dd9c295b | ||
|
|
4faf71bd03 | ||
|
|
2751dbdb94 | ||
|
|
fe329cb4ab | ||
|
|
741e719ff8 | ||
|
|
866bb32046 | ||
|
|
7f01e758b3 | ||
|
|
03003d270e | ||
|
|
3d313016ba | ||
|
|
1292c752a8 | ||
|
|
4783947135 | ||
|
|
c9045788f5 | ||
|
|
4eed8463b3 | ||
|
|
303711ab8d | ||
|
|
98d7fc9f39 | ||
|
|
c0a96f2087 | ||
|
|
c509ecca52 | ||
|
|
e5d8eb7845 | ||
|
|
277f43aed6 | ||
|
|
f1494b64e5 | ||
|
|
6b9c71ec62 | ||
|
|
d12a4b0a1a | ||
|
|
a75d075dd1 | ||
|
|
8f8a37bf94 | ||
|
|
03f692fed8 | ||
|
|
614416d4b0 | ||
|
|
feb851716e | ||
|
|
2b095f720e | ||
|
|
d6e750727f | ||
|
|
961ff8633d | ||
|
|
8406d4a8f1 | ||
|
|
e25b64ae15 | ||
|
|
59205a4caf | ||
|
|
5001797179 | ||
|
|
b24dd69067 | ||
|
|
4f163338dd | ||
|
|
1e8f1f8cc6 | ||
|
|
5c3e2e6877 | ||
|
|
ff52ff7865 | ||
|
|
f6f55aaa9a | ||
|
|
6f1aecab99 | ||
|
|
f33205a490 | ||
|
|
2920638a3d | ||
|
|
1ae32b5742 | ||
|
|
4e9dabfb25 | ||
|
|
ca2c419c9b | ||
|
|
020c1311ca | ||
|
|
8193b2a44b | ||
|
|
324a000777 | ||
|
|
951b1c1e83 | ||
|
|
8e57fd93c6 | ||
|
|
d262f43b5b | ||
|
|
73224e7d95 | ||
|
|
19463c81a3 | ||
|
|
6f2bb31068 | ||
|
|
abf9c4117d | ||
|
|
39f50830d7 | ||
|
|
c2fd7005cb | ||
|
|
52f2ed33f5 | ||
|
|
a51239c6ae | ||
|
|
e6217e1428 | ||
|
|
f61dfb0828 | ||
|
|
00fe963e7c | ||
|
|
009ea1c8cd | ||
|
|
72069015b9 | ||
|
|
6c0c67dd7b | ||
|
|
3c090519a0 | ||
|
|
5da70929f6 | ||
|
|
5b66d6209f | ||
|
|
9f7f353485 | ||
|
|
05f01525c3 | ||
|
|
3aa016940c | ||
|
|
a792c94ccf | ||
|
|
249e59b310 | ||
|
|
3b43b76222 | ||
|
|
398f5cfbdc | ||
|
|
bc47be64b0 | ||
|
|
59c6fb9ce7 | ||
|
|
8b99d0a432 | ||
|
|
639b18c7e8 | ||
|
|
701942f6ef | ||
|
|
9d8e6a2b30 | ||
|
|
581deb6073 | ||
|
|
9849a69afd | ||
|
|
5f33d907aa | ||
|
|
0919eda640 | ||
|
|
5952a140e0 | ||
|
|
6d92996661 | ||
|
|
04e4b0c469 | ||
|
|
20f4a9a942 | ||
|
|
5552679c11 | ||
|
|
1369a36178 | ||
|
|
529337e00a | ||
|
|
fe882dad15 | ||
|
|
4fff84b4b9 | ||
|
|
3e964163c0 | ||
|
|
10a987b908 | ||
|
|
03e417e1be | ||
|
|
c95d3b19b3 | ||
|
|
1fa9b8f102 | ||
|
|
c27cf31a7c | ||
|
|
ad672fc9d6 | ||
|
|
a0f298ddb0 | ||
|
|
9b740849ed | ||
|
|
a3f9835b7b | ||
|
|
f4294b83fb | ||
|
|
4fa4a20b22 | ||
|
|
af2c9a49b1 | ||
|
|
bdeec61266 | ||
|
|
268e5cef3b | ||
|
|
b37f4333e2 | ||
|
|
f0c663d42d | ||
|
|
e36e44ab3a | ||
|
|
2dceec444f | ||
|
|
eaba3cff0b | ||
|
|
ec31a348cf | ||
|
|
d6a6e26500 | ||
|
|
cab1ba4e50 | ||
|
|
a2f589be00 | ||
|
|
7622cbaed5 | ||
|
|
53df123c0d | ||
|
|
c660840c19 | ||
|
|
c6d3ede57e | ||
|
|
6037167336 | ||
|
|
0804447881 | ||
|
|
83482873dc | ||
|
|
5e351e4d65 | ||
|
|
408cd9cf9b | ||
|
|
8b47e63136 | ||
|
|
379ec88776 | ||
|
|
a320e8bc25 | ||
|
|
1c4f5b471d | ||
|
|
d5846282a9 | ||
|
|
8b56f1ced6 | ||
|
|
0987a536b1 | ||
|
|
099510f4d1 | ||
|
|
35c6014025 | ||
|
|
895ac26d43 | ||
|
|
da999f730b | ||
|
|
47969e9f18 | ||
|
|
b6267d4a8c | ||
|
|
2df97e309b | ||
|
|
078b23e6aa | ||
|
|
d8eeed2296 | ||
|
|
e5afc5297a | ||
|
|
465ed48e73 | ||
|
|
f8b311b289 | ||
|
|
934336e642 | ||
|
|
6f5ff05c56 | ||
|
|
2376b7c255 | ||
|
|
ef86f8a20c | ||
|
|
b3f1acd400 | ||
|
|
5c4462281e | ||
|
|
91d94f262c | ||
|
|
2651acce91 | ||
|
|
25cfcdba76 | ||
|
|
6f5004fc13 | ||
|
|
df9c1aea64 | ||
|
|
a309069b6b | ||
|
|
beb90f2c55 | ||
|
|
0e0aba7a5e | ||
|
|
6e9b41314e | ||
|
|
dbeac923ed | ||
|
|
5953c2097d | ||
|
|
8969206450 | ||
|
|
41318d763b | ||
|
|
8251b906b6 | ||
|
|
790d630d17 | ||
|
|
c9644039b1 | ||
|
|
34de072a10 | ||
|
|
f6d7b3aa04 | ||
|
|
5c31c2b98e | ||
|
|
2cc779b667 | ||
|
|
7f4294f68c | ||
|
|
fd2515da5c | ||
|
|
db1f53fc29 | ||
|
|
96f5c66755 | ||
|
|
4baf7b5bba | ||
|
|
58bb5a7d1f | ||
|
|
c63dd76814 | ||
|
|
8d3e6b4796 | ||
|
|
b10312e249 | ||
|
|
6f3a9d6d29 | ||
|
|
c4e89d9d0c | ||
|
|
00a2126152 | ||
|
|
e7099cc771 | ||
|
|
b6724ed177 | ||
|
|
fcedc9f5c3 | ||
|
|
cb095be0cc | ||
|
|
ecf2c86787 | ||
|
|
971c28ce97 | ||
|
|
482129ff35 | ||
|
|
65c75859bc | ||
|
|
fcb26e5dc7 | ||
|
|
0dc6ac26c3 | ||
|
|
48303bac75 | ||
|
|
5ab8a665be | ||
|
|
733158a2de | ||
|
|
a2e47d2d0e | ||
|
|
bfb97a6e6f | ||
|
|
fc1a8351b0 | ||
|
|
be7a4a5868 | ||
|
|
493892a4df | ||
|
|
106dc2b03b | ||
|
|
d5490475f1 | ||
|
|
999a6a288c | ||
|
|
7d9d096fbf | ||
|
|
c129dd9331 | ||
|
|
5c75ac0a96 | ||
|
|
bafedf8376 | ||
|
|
136f15e647 | ||
|
|
e9e4ac13ee | ||
|
|
e24c758341 | ||
|
|
4b65b4ac2b | ||
|
|
d8d7765a82 | ||
|
|
b98bc1c787 | ||
|
|
4b08ce2a09 | ||
|
|
ed62e72a98 | ||
|
|
a28710c1fc | ||
|
|
764a058cf6 | ||
|
|
a538663679 | ||
|
|
8920d64f7d | ||
|
|
a051cb9ee3 | ||
|
|
56864cdfb7 | ||
|
|
428c600788 | ||
|
|
748f1a90b9 | ||
|
|
d3cee832ce | ||
|
|
8129246a10 | ||
|
|
a2789650e5 | ||
|
|
af376cf27e | ||
|
|
6c8ccbd73a | ||
|
|
626ac0d5b8 | ||
|
|
2550bc910d | ||
|
|
0a153e2524 | ||
|
|
facd353228 | ||
|
|
5b7eac280c | ||
|
|
7ab63525c7 | ||
|
|
a1c49a0f7f | ||
|
|
4c4c6ab0e6 | ||
|
|
2e0d39b512 | ||
|
|
0899019518 | ||
|
|
db16996181 | ||
|
|
aa2b21456f | ||
|
|
7e8e1e9e89 | ||
|
|
01e9702958 | ||
|
|
6d970c1175 | ||
|
|
16c0871e22 | ||
|
|
fd7ddc2905 | ||
|
|
c181919a57 | ||
|
|
5955b44c74 | ||
|
|
8b5f02bb0b | ||
|
|
f2a1ff2584 | ||
|
|
11522ccc92 | ||
|
|
bb97c589c1 | ||
|
|
4a5a9b2888 | ||
|
|
b1bd581065 | ||
|
|
3bd1ca0ac3 | ||
|
|
bbeb08ba08 | ||
|
|
66dbdf4b40 | ||
|
|
f0a2c34eca | ||
|
|
9f35b9281b | ||
|
|
7624578c21 | ||
|
|
d4b477ad78 | ||
|
|
e6d5eea7eb | ||
|
|
bef9490fa8 | ||
|
|
d593ccba2f | ||
|
|
1902d8bb19 | ||
|
|
f10c65f1bf | ||
|
|
da507dfd19 | ||
|
|
13254ac4d5 | ||
|
|
fc9ffb3115 | ||
|
|
f64ffcac48 | ||
|
|
f2a6cb3dbb | ||
|
|
4767d2b8d6 | ||
|
|
1ceb8b1b0b | ||
|
|
719a9a5b64 | ||
|
|
5adf7c2a3a | ||
|
|
1c9d6bf9e6 | ||
|
|
f85dfe91a9 | ||
|
|
749fb84053 | ||
|
|
e33af8b2f8 | ||
|
|
61a9f7baae | ||
|
|
4d4b690a99 | ||
|
|
d4c2293d56 | ||
|
|
3b34cec64c | ||
|
|
a1e9b854e3 | ||
|
|
01ed1e1604 | ||
|
|
b7b1a1f1c6 | ||
|
|
c9446727d3 | ||
|
|
cff79bc9d4 | ||
|
|
72ccf87d19 | ||
|
|
2387c71b3c | ||
|
|
47a2120023 | ||
|
|
b777353766 | ||
|
|
5d4491667b | ||
|
|
9fbd14f815 | ||
|
|
f38b27e923 | ||
|
|
cb8116e2af | ||
|
|
2066dd0077 | ||
|
|
37afd7aaa7 | ||
|
|
8df9ccc72c | ||
|
|
862075bd65 | ||
|
|
27ffed5a1a | ||
|
|
bf2c50b58b | ||
|
|
34c35ff4ca | ||
|
|
174a45b4bd | ||
|
|
e44b331cc3 | ||
|
|
aed504efdc | ||
|
|
ca38568187 | ||
|
|
a653c17e8a | ||
|
|
6bbd33eca4 | ||
|
|
494235750e | ||
|
|
076c81c4ee | ||
|
|
abd4de7311 | ||
|
|
4629ef627f | ||
|
|
b1c2e90a05 | ||
|
|
c19cbaad24 | ||
|
|
1a3fdac4e4 | ||
|
|
d343981faa | ||
|
|
51c0c51884 | ||
|
|
cb2d162bec | ||
|
|
6507fd1ac2 | ||
|
|
442f2adf23 | ||
|
|
702613915b | ||
|
|
8ebc9553c3 | ||
|
|
ae8076e411 | ||
|
|
f3974671f6 | ||
|
|
dcb2d95f9a | ||
|
|
c8bb7aae40 | ||
|
|
4711e10df2 | ||
|
|
28f1b8a7a0 | ||
|
|
104e213934 | ||
|
|
fe3a432845 | ||
|
|
423f8e59cc | ||
|
|
1c468b2931 | ||
|
|
85faad5ec7 | ||
|
|
869152750c | ||
|
|
7fd4ec50c9 | ||
|
|
8de4dd334b | ||
|
|
c5cc208397 | ||
|
|
718e6fa93d | ||
|
|
0833697c49 | ||
|
|
112ae0edab | ||
|
|
502c31b408 | ||
|
|
062563a562 | ||
|
|
c385532b10 | ||
|
|
81f4b4cece | ||
|
|
23482e3cf4 | ||
|
|
b49b34c4c1 | ||
|
|
b40ca5800d | ||
|
|
3b25081353 | ||
|
|
5726466db3 | ||
|
|
27acd4c7d4 | ||
|
|
f98d780f3e | ||
|
|
8177cfac2a | ||
|
|
fb4123a6f2 | ||
|
|
191913b7eb | ||
|
|
3a3f745d31 | ||
|
|
eebe12a972 | ||
|
|
274dd2f3fe | ||
|
|
fb5dbc811b | ||
|
|
c31c32f921 | ||
|
|
22b756753a | ||
|
|
cb7eb48768 | ||
|
|
22ed014123 | ||
|
|
419b078104 | ||
|
|
b51584525a | ||
|
|
728dbbfff0 | ||
|
|
7485269c37 | ||
|
|
cffaa54a78 | ||
|
|
1f597fd2b3 | ||
|
|
48d792bc19 | ||
|
|
5da123c632 | ||
|
|
27887ada45 | ||
|
|
4c9a6ed56c | ||
|
|
1bf2864638 | ||
|
|
c8bd61b345 | ||
|
|
7ee04b37ac | ||
|
|
5957befaad | ||
|
|
17a16ccd21 | ||
|
|
1de940d7b4 | ||
|
|
9a2ff9e419 | ||
|
|
84caf787aa | ||
|
|
e9d0d40809 | ||
|
|
0e2a5c63c6 | ||
|
|
9916802a69 | ||
|
|
bfac482940 | ||
|
|
8778cf63c4 | ||
|
|
d5d1e6c11e | ||
|
|
8e6780e761 | ||
|
|
ddb961f9af | ||
|
|
670de085a3 | ||
|
|
4c49573465 | ||
|
|
13d478ffca | ||
|
|
1cc95a605c | ||
|
|
e19f180c71 | ||
|
|
d3ad15dc51 | ||
|
|
3aaa69b36c | ||
|
|
41906cf7db | ||
|
|
f3696da0ff | ||
|
|
fab723b9bc | ||
|
|
d3a3a89098 | ||
|
|
68313e99a7 | ||
|
|
9b73d25151 | ||
|
|
440db8f4bd | ||
|
|
6690c4f916 | ||
|
|
6d3ad7d903 | ||
|
|
0d60b88f1d | ||
|
|
aa82d8fddd | ||
|
|
10f5461cd8 | ||
|
|
c7a0626c69 | ||
|
|
6a9a7dee55 | ||
|
|
8952afd6cc | ||
|
|
526c526bf3 | ||
|
|
12e269e791 | ||
|
|
c2f6450af3 | ||
|
|
c8dfe955d7 | ||
|
|
71091e73a4 | ||
|
|
25d1b2328f | ||
|
|
4085fe2e8e | ||
|
|
74445674f2 | ||
|
|
c343bdd120 | ||
|
|
5ff4a6f4d8 | ||
|
|
5172597d96 | ||
|
|
a09fb7b20d | ||
|
|
af9e633d56 | ||
|
|
df62478418 | ||
|
|
c623cd5d01 | ||
|
|
3126f31cbf | ||
|
|
c33c88b2c6 | ||
|
|
36d5afef9f | ||
|
|
c8ed52f600 | ||
|
|
8d7e083e64 | ||
|
|
2144f43142 | ||
|
|
66d2930b7e | ||
|
|
4dcaec0997 | ||
|
|
33da5ca869 | ||
|
|
4c1a69a98c | ||
|
|
d613962f5b | ||
|
|
8f7cef1232 | ||
|
|
7a91ba3699 | ||
|
|
14018a5e54 | ||
|
|
81a03fcea8 | ||
|
|
48962a58ae | ||
|
|
8c9c777ad3 | ||
|
|
dc6e276e39 | ||
|
|
8182fcecd2 | ||
|
|
4d082dbf80 | ||
|
|
5b5c49d317 | ||
|
|
51b5510669 | ||
|
|
7a4b438dc6 | ||
|
|
1a29de5ac9 | ||
|
|
ed8edf3e4c | ||
|
|
9fcde9d81d | ||
|
|
81ffa7e948 | ||
|
|
93d2d30867 | ||
|
|
42e05c5ad2 | ||
|
|
d37e815f13 | ||
|
|
a1f454937c | ||
|
|
b041dcc8ce | ||
|
|
22c65c5d03 | ||
|
|
60b64dadfe | ||
|
|
edb25314c5 | ||
|
|
19bce0c23c | ||
|
|
8ceb941051 | ||
|
|
8b28cbb30c | ||
|
|
de130787f6 | ||
|
|
6e94dae9cd | ||
|
|
d2431783f1 | ||
|
|
5787b472c0 | ||
|
|
6bdfc0387b | ||
|
|
7ba98344b6 | ||
|
|
c887df6ab4 | ||
|
|
a8ad4461a1 | ||
|
|
32a0e28686 | ||
|
|
df13f0ce5a | ||
|
|
972f0c0e2b | ||
|
|
c7a3a4d421 |
94
.circleci/config.yml
Normal file
94
.circleci/config.yml
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
lin-sys:
|
||||||
|
docker:
|
||||||
|
- image: kovidgoyal/kitty-test:latest
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
|
||||||
|
- run: python3 -m flake8 --count .
|
||||||
|
- run: python3 setup.py build --debug --verbose
|
||||||
|
- run: python3 test.py
|
||||||
|
- run: make FAIL_WARN=-W man
|
||||||
|
- run: make FAIL_WARN=-W html
|
||||||
|
- run: python3 setup.py linux-package --update-check-interval=0
|
||||||
|
|
||||||
|
lin-35:
|
||||||
|
docker:
|
||||||
|
- image: kovidgoyal/kitty-test:latest
|
||||||
|
environment:
|
||||||
|
CC: gcc
|
||||||
|
CFLAGS: -funsigned-char
|
||||||
|
LD_LIBRARY_PATH: /opt/py3.5/lib
|
||||||
|
ASAN_OPTIONS: leak_check_at_exit=0
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: /opt/py3.5/bin/python3 setup.py build --debug --verbose --sanitize
|
||||||
|
- run: ./asan-launcher test.py
|
||||||
|
|
||||||
|
lin-37:
|
||||||
|
docker:
|
||||||
|
- image: kovidgoyal/kitty-test:latest
|
||||||
|
environment:
|
||||||
|
CC: clang
|
||||||
|
LD_LIBRARY_PATH: /opt/py3.7/lib
|
||||||
|
ASAN_OPTIONS: leak_check_at_exit=0
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: /opt/py3.7/bin/python3 setup.py build --debug --verbose --sanitize
|
||||||
|
- run: ./asan-launcher test.py
|
||||||
|
|
||||||
|
lin-bundle:
|
||||||
|
docker:
|
||||||
|
- image: kovidgoyal/kitty-test:latest
|
||||||
|
environment:
|
||||||
|
ASAN_OPTIONS: leak_check_at_exit=0
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: echo "export LD_LIBRARY_PATH=$SW/lib" >> $BASH_ENV
|
||||||
|
- run: echo "export PKG_CONFIG_PATH=$SW/lib/pkgconfig" >> $BASH_ENV
|
||||||
|
- run: $SW/bin/python3 setup.py build --debug --verbose
|
||||||
|
- run: $SW/bin/python3 test.py
|
||||||
|
|
||||||
|
mac-bundle:
|
||||||
|
macos:
|
||||||
|
xcode: "10.1.0"
|
||||||
|
environment:
|
||||||
|
LC_ALL: en_US.UTF-8
|
||||||
|
LANG: en_US.UTF-8
|
||||||
|
SW: /Users/Shared/buildbot/sw/sw
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: mkdir -p $SW
|
||||||
|
- run: curl https://download.calibre-ebook.com/travis/kitty/osx.tar.xz | tar xJ -C $SW
|
||||||
|
- run: echo "export PATH=$SW/bin:$PATH" >> $BASH_ENV
|
||||||
|
- run: python3 setup.py build --debug --verbose
|
||||||
|
- run: python3 test.py
|
||||||
|
|
||||||
|
mac-brew:
|
||||||
|
macos:
|
||||||
|
xcode: "10.1.0"
|
||||||
|
environment:
|
||||||
|
LC_ALL: en_US.UTF-8
|
||||||
|
LANG: en_US.UTF-8
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run: brew bundle
|
||||||
|
- run: python3 logo/make.py
|
||||||
|
- run: python3 setup.py build --debug --verbose
|
||||||
|
- run: python3 test.py
|
||||||
|
- run: python3 setup.py macos-bundle
|
||||||
|
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
all_jobs:
|
||||||
|
jobs:
|
||||||
|
- mac-bundle
|
||||||
|
- lin-sys
|
||||||
|
- lin-35
|
||||||
|
- lin-37
|
||||||
|
- lin-bundle
|
||||||
|
- mac-brew
|
||||||
55
.circleci/images/Dockerfile
Normal file
55
.circleci/images/Dockerfile
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# When changing this file, go to
|
||||||
|
# https://cloud.docker.com/repository/docker/kovidgoyal/kitty-test/builds and
|
||||||
|
# click the "Trigger" button under Automated builds to rebuild
|
||||||
|
FROM ubuntu:latest
|
||||||
|
|
||||||
|
# make Apt non-interactive
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/90circleci \
|
||||||
|
&& echo 'DPkg::Options "--force-confnew";' >> /etc/apt/apt.conf.d/90circleci \
|
||||||
|
&& echo 'Acquire::Languages "none";' >> /etc/apt/apt.conf.d/90circleci
|
||||||
|
|
||||||
|
# System setup
|
||||||
|
RUN apt-get update && mkdir -p /usr/share/man/man1 && apt-get install -y python3-flake8 python3-pip python3-pil clang git apt locales sudo openssh-client ca-certificates tar gzip parallel net-tools netcat unzip zip bzip2 gnupg curl wget build-essential apt-utils
|
||||||
|
|
||||||
|
# Setup circleci user
|
||||||
|
RUN groupadd --gid 3434 circleci \
|
||||||
|
&& useradd --uid 3434 --gid circleci --shell /bin/bash --create-home circleci \
|
||||||
|
&& echo 'circleci ALL=NOPASSWD: ALL' >> /etc/sudoers.d/50-circleci \
|
||||||
|
&& echo 'Defaults env_keep += "DEBIAN_FRONTEND"' >> /etc/sudoers.d/env_keep \
|
||||||
|
&& echo 'Defaults env_keep += "SW"' >> /etc/sudoers.d/env_keep \
|
||||||
|
&& echo 'Defaults env_keep += "LANG"' >> /etc/sudoers.d/env_keep
|
||||||
|
|
||||||
|
# Set timezone to UTC by default
|
||||||
|
RUN ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime
|
||||||
|
|
||||||
|
# Use unicode
|
||||||
|
RUN locale-gen en_US.UTF-8 || true
|
||||||
|
ENV LANG=en_US.UTF-8
|
||||||
|
|
||||||
|
# Deps needed for building python
|
||||||
|
RUN apt-get install -y libreadline-dev zlib1g-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev
|
||||||
|
|
||||||
|
# kitty deps
|
||||||
|
RUN apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libpng-dev libfontconfig-dev libpython3-dev libxkbcommon-x11-dev python3-pygments
|
||||||
|
|
||||||
|
# Needed to build kitty docs
|
||||||
|
RUN pip3 install sphinx
|
||||||
|
|
||||||
|
# Install multiple pythons
|
||||||
|
ADD install-python.py /tmp/install-python.py
|
||||||
|
RUN python3 /tmp/install-python.py py3.5 https://www.python.org/ftp/python/3.5.6/Python-3.5.6.tar.xz
|
||||||
|
RUN python3 /tmp/install-python.py py3.7 https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
|
||||||
|
|
||||||
|
# Install kitty bundle
|
||||||
|
ENV SW=/home/circleci/sw
|
||||||
|
RUN python3 /tmp/install-python.py bundle https://download.calibre-ebook.com/travis/kitty/linux-64.tar.xz
|
||||||
|
RUN echo SW=$SW >> /etc/environment
|
||||||
|
|
||||||
|
# Clean unused files
|
||||||
|
RUN apt-get clean -y
|
||||||
|
|
||||||
|
USER circleci
|
||||||
|
|
||||||
|
LABEL com.circleci.preserve-entrypoint=true
|
||||||
|
ENTRYPOINT sleep 2h
|
||||||
60
.circleci/images/install-python.py
Normal file
60
.circleci/images/install-python.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tarfile
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
PY, URL = sys.argv[1], sys.argv[2]
|
||||||
|
if PY == 'bundle':
|
||||||
|
SW = os.environ['SW']
|
||||||
|
os.mkdir(SW)
|
||||||
|
os.chdir(SW)
|
||||||
|
else:
|
||||||
|
os.chdir('/usr/src')
|
||||||
|
|
||||||
|
|
||||||
|
def run(cmd):
|
||||||
|
cmd = shlex.split(cmd)
|
||||||
|
p = subprocess.Popen(cmd)
|
||||||
|
if p.wait() != 0:
|
||||||
|
raise SystemExit(p.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
with urlopen(URL) as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
with tarfile.open(fileobj=io.BytesIO(data), mode='r:xz') as tf:
|
||||||
|
tf.extractall()
|
||||||
|
|
||||||
|
|
||||||
|
def replace_in_file(path, src, dest):
|
||||||
|
with open(path, 'r+') as f:
|
||||||
|
n = f.read().replace(src, dest)
|
||||||
|
f.seek(0), f.truncate()
|
||||||
|
f.write(n)
|
||||||
|
|
||||||
|
|
||||||
|
if PY == 'bundle':
|
||||||
|
replaced = 0
|
||||||
|
for dirpath, dirnames, filenames in os.walk(SW):
|
||||||
|
for f in filenames:
|
||||||
|
if f.endswith('.pc') or (f.endswith('.py') and f.startswith('_sysconfig')):
|
||||||
|
replace_in_file(os.path.join(dirpath, f), '/sw/sw', SW)
|
||||||
|
replaced += 1
|
||||||
|
if replaced < 2:
|
||||||
|
raise SystemExit('Failed to replace path to SW in bundle')
|
||||||
|
else:
|
||||||
|
src = os.path.abspath(tuple(os.listdir('.'))[0])
|
||||||
|
os.chdir(src)
|
||||||
|
run(f'./configure --prefix=/opt/{PY} --enable-shared --with-system-expat --without-ensurepip')
|
||||||
|
run(f'make -j {os.cpu_count()}')
|
||||||
|
run('make install')
|
||||||
|
os.chdir('/')
|
||||||
|
shutil.rmtree(src)
|
||||||
172
.travis.yml
172
.travis.yml
@@ -1,172 +0,0 @@
|
|||||||
git:
|
|
||||||
depth: false
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
dist: xenial
|
|
||||||
group: beta
|
|
||||||
language: python
|
|
||||||
sudo: false
|
|
||||||
env: USE_BUNDLE=1 SW=$HOME/sw PKG_CONFIG_PATH=$SW/lib/pkgconfig LD_LIBRARY_PATH=$SW/lib PYTHON=$SW/bin/python3
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libgl1-mesa-dev
|
|
||||||
- libxi-dev
|
|
||||||
- libxrandr-dev
|
|
||||||
- libxinerama-dev
|
|
||||||
- libxcursor-dev
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libdbus-1-dev
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: xenial
|
|
||||||
group: beta
|
|
||||||
sudo: false
|
|
||||||
env:
|
|
||||||
- CC=gcc CFLAGS=-funsigned-char SANITIZE_ARG=--sanitize
|
|
||||||
language: python
|
|
||||||
python: "3.5"
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libgl1-mesa-dev
|
|
||||||
- libfontconfig1-dev
|
|
||||||
- libharfbuzz-dev
|
|
||||||
- libxi-dev
|
|
||||||
- libxrandr-dev
|
|
||||||
- libxinerama-dev
|
|
||||||
- libxcursor-dev
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libpng-dev
|
|
||||||
- libdbus-1-dev
|
|
||||||
- python3-pil
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: xenial
|
|
||||||
group: beta
|
|
||||||
sudo: false
|
|
||||||
env:
|
|
||||||
- CC=clang SANITIZE_ARG=--sanitize
|
|
||||||
language: python
|
|
||||||
python: "3.5"
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libgl1-mesa-dev
|
|
||||||
- libfontconfig1-dev
|
|
||||||
- libharfbuzz-dev
|
|
||||||
- libxi-dev
|
|
||||||
- libxrandr-dev
|
|
||||||
- libxinerama-dev
|
|
||||||
- libxcursor-dev
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libpng-dev
|
|
||||||
- libdbus-1-dev
|
|
||||||
- python3-pil
|
|
||||||
|
|
||||||
- os: linux
|
|
||||||
dist: xenial
|
|
||||||
group: beta
|
|
||||||
sudo: false
|
|
||||||
env:
|
|
||||||
- RUN_FLAKE=1 BUILD_PKG=linux-package
|
|
||||||
language: python
|
|
||||||
python: "3.6"
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- libgl1-mesa-dev
|
|
||||||
- libfontconfig1-dev
|
|
||||||
- libharfbuzz-dev
|
|
||||||
- libxi-dev
|
|
||||||
- libxrandr-dev
|
|
||||||
- libxinerama-dev
|
|
||||||
- libxcursor-dev
|
|
||||||
- libxcb-xkb-dev
|
|
||||||
- libpng-dev
|
|
||||||
- libdbus-1-dev
|
|
||||||
- python3-pil
|
|
||||||
- clang
|
|
||||||
- os: osx
|
|
||||||
language: generic
|
|
||||||
env: SWBASE=/Users/Shared/buildbot/sw SW=$SWBASE/sw PATH=$SW/bin:$PATH
|
|
||||||
|
|
||||||
- os: osx
|
|
||||||
language: generic
|
|
||||||
addons:
|
|
||||||
homebrew:
|
|
||||||
update: true
|
|
||||||
brewfile: true
|
|
||||||
env: USE_BREW=1 BUILD_PKG=osx-bundle
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- PYTHON=python3
|
|
||||||
- PKG_CONFIG_PATH=$HOME/harfbuzz/lib/pkgconfig:$PKG_CONFIG_PATH
|
|
||||||
- LD_LIBRARY_PATH=$HOME/harfbuzz/lib:$LD_LIBRARY_PATH
|
|
||||||
- ASAN_OPTIONS=leak_check_at_exit=0
|
|
||||||
|
|
||||||
install: |
|
|
||||||
set -e
|
|
||||||
if [[ "$RUN_FLAKE" == "1" ]]; then pip install flake8; fi
|
|
||||||
if [[ "$TRAVIS_OS_NAME" == 'osx' ]]; then
|
|
||||||
if [[ "$USE_BREW" == "1" ]]; then
|
|
||||||
logo/make.py
|
|
||||||
else
|
|
||||||
mkdir -p $SW;
|
|
||||||
curl https://download.calibre-ebook.com/travis/kitty/osx.tar.xz | tar xJ -C $SW;
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [[ "$USE_BUNDLE" == "1" ]]; then
|
|
||||||
mkdir -p $SW;
|
|
||||||
curl https://download.calibre-ebook.com/travis/kitty/linux-64.tar.xz | tar xJ -C $SW;
|
|
||||||
find $SW -type f -name '*.pc' -exec sed -i "s,/sw/sw,$SW,g" {} \;;
|
|
||||||
find $SW -type f -name '_sysconfig*.py' -exec sed -i "s,/sw/sw,$SW,g" {} \;;
|
|
||||||
else
|
|
||||||
pushd /tmp
|
|
||||||
wget --no-check-certificate http://xkbcommon.org/download/libxkbcommon-0.6.1.tar.xz
|
|
||||||
tar xf libxkbcommon-0.6.1.tar.xz
|
|
||||||
cd libxkbcommon-0.6.1
|
|
||||||
./configure --prefix=$HOME/harfbuzz --disable-dependency-tracking --disable-static
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
wget https://github.com/behdad/harfbuzz/releases/download/1.6.3/harfbuzz-1.6.3.tar.bz2
|
|
||||||
tar xf harfbuzz-1.6.3.tar.bz2
|
|
||||||
cd harfbuzz-1.6.3
|
|
||||||
./configure --prefix=$HOME/harfbuzz --disable-dependency-tracking --disable-static --with-glib=no --with-gobject=no --with-cairo=no --with-fontconfig=no --with-icu=no --with-directwrite=no --with-freetype=yes
|
|
||||||
make -j2
|
|
||||||
make install
|
|
||||||
cd ..
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
if [[ "$BUILD_PKG" == "linux-package" ]]; then
|
|
||||||
pip install sphinx
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
pkg-config --cflags harfbuzz
|
|
||||||
if [[ "$TRAVIS_OS_NAME" != 'osx' ]]; then
|
|
||||||
PLIB=$(ldd `which python` | grep libpython | cut -d ' ' -f 3)
|
|
||||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`dirname $PLIB`
|
|
||||||
fi
|
|
||||||
set +e
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
|
||||||
- $PYTHON setup.py build --debug --verbose $SANITIZE_ARG;
|
|
||||||
|
|
||||||
script: |
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
|
|
||||||
|
|
||||||
if [[ -z "$SANITIZE_ARG" ]]; then $PYTHON test.py; else ./asan-launcher test.py; fi
|
|
||||||
|
|
||||||
if [[ "$RUN_FLAKE" == "1" ]]; then flake8 --count .; fi
|
|
||||||
|
|
||||||
if [[ "$BUILD_PKG" == "linux-package" ]]; then make FAIL_WARN=-W man && make FAIL_WARN=-W html; fi
|
|
||||||
|
|
||||||
if [[ ! -z "$BUILD_PKG" ]]; then $PYTHON setup.py $BUILD_PKG; fi
|
|
||||||
|
|
||||||
set +e
|
|
||||||
1
Brewfile
1
Brewfile
@@ -1,3 +1,4 @@
|
|||||||
|
brew 'pkg-config'
|
||||||
brew 'imagemagick'
|
brew 'imagemagick'
|
||||||
brew 'optipng'
|
brew 'optipng'
|
||||||
brew 'librsvg'
|
brew 'librsvg'
|
||||||
|
|||||||
8
LICENSE
8
LICENSE
@@ -1,7 +1,7 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
The GNU General Public License does not permit incorporating your program
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|||||||
3
Makefile
3
Makefile
@@ -18,6 +18,9 @@ clean:
|
|||||||
debug:
|
debug:
|
||||||
python3 setup.py build $(VVAL) --debug
|
python3 setup.py build $(VVAL) --debug
|
||||||
|
|
||||||
|
debug-event-loop:
|
||||||
|
python3 setup.py build $(VVAL) --debug --extra-logging=event-loop
|
||||||
|
|
||||||
# Build with the ASAN and UBSAN sanitizers
|
# Build with the ASAN and UBSAN sanitizers
|
||||||
asan:
|
asan:
|
||||||
python3 setup.py build $(VVAL) --debug --sanitize
|
python3 setup.py build $(VVAL) --debug --sanitize
|
||||||
|
|||||||
@@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
See https://sw.kovidgoyal.net/kitty
|
See https://sw.kovidgoyal.net/kitty
|
||||||
|
|
||||||
image::https://travis-ci.org/kovidgoyal/kitty.svg?branch=master[Build status, link=https://travis-ci.org/kovidgoyal/kitty]
|
image:https://circleci.com/gh/kovidgoyal/kitty.svg?style=svg["Build status", link="https://circleci.com/gh/kovidgoyal/kitty"]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ def setup_openssl_environment():
|
|||||||
# Workaround for Linux distros that have still failed to get their heads
|
# Workaround for Linux distros that have still failed to get their heads
|
||||||
# out of their asses and implement a common location for SSL certificates.
|
# out of their asses and implement a common location for SSL certificates.
|
||||||
# It's not that hard people, there exists a wonderful tool called the symlink
|
# It's not that hard people, there exists a wonderful tool called the symlink
|
||||||
# See http://www.mobileread.com/forums/showthread.php?t=256095
|
# See https://www.mobileread.com/forums/showthread.php?t=256095
|
||||||
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
|
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
|
||||||
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
||||||
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
|
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* linux-launcher.c
|
* asan-launcher.c
|
||||||
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
*
|
*
|
||||||
* Distributed under terms of the GPL3 license.
|
* Distributed under terms of the GPL3 license.
|
||||||
|
|||||||
@@ -1,24 +1,48 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import glob
|
||||||
import os
|
import os
|
||||||
import sys
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
base = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
os.chdir(base)
|
|
||||||
sys.path.insert(0, base)
|
|
||||||
|
|
||||||
from kitty.terminfo import generate_terminfo # noqa
|
def compile_terminfo(base):
|
||||||
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
|
proc = subprocess.run(['tic', '-x', '-o' + tdir, 'terminfo/kitty.terminfo'], check=True, stderr=subprocess.PIPE)
|
||||||
|
regex = '^"terminfo/kitty.terminfo", line [0-9]+, col [0-9]+, terminal \'xterm-kitty\': older tic versions may treat the description field as an alias$'
|
||||||
|
for error in proc.stderr.decode('utf-8').splitlines():
|
||||||
|
if not re.match(regex, error):
|
||||||
|
print(error, file=sys.stderr)
|
||||||
|
tfiles = glob.glob(os.path.join(tdir, '*', 'xterm-kitty'))
|
||||||
|
if not tfiles:
|
||||||
|
raise SystemExit('tic failed to output the compiled kitty terminfo file')
|
||||||
|
|
||||||
with open('terminfo/kitty.terminfo', 'w') as f:
|
tfile = tfiles[0]
|
||||||
f.write(generate_terminfo())
|
directory, xterm_kitty = os.path.split(tfile)
|
||||||
|
_, directory = os.path.split(directory)
|
||||||
|
odir = os.path.join(base, directory)
|
||||||
|
os.makedirs(odir, exist_ok=True)
|
||||||
|
ofile = os.path.join(odir, xterm_kitty)
|
||||||
|
shutil.move(tfile, ofile)
|
||||||
|
|
||||||
os.environ['TERMINFO'] = os.path.join(base, 'terminfo')
|
|
||||||
subprocess.check_call(['tic', '-x', 'terminfo/kitty.terminfo'])
|
def generate_terminfo():
|
||||||
# On OS X tic puts the compiled database into a different directory
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
try:
|
os.chdir(base)
|
||||||
os.mkdir('terminfo/78')
|
sys.path.insert(0, base)
|
||||||
except FileExistsError:
|
|
||||||
pass
|
from kitty.terminfo import generate_terminfo
|
||||||
shutil.copy2('terminfo/x/xterm-kitty', 'terminfo/78')
|
|
||||||
|
with open('terminfo/kitty.terminfo', 'w') as f:
|
||||||
|
f.write(generate_terminfo())
|
||||||
|
|
||||||
|
compile_terminfo(os.path.join(base, 'terminfo'))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
generate_terminfo()
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
cloc --exclude-list-file <(echo -e 'kitty/wcwidth-std.h\nkitty/glfw.c\nkitty/keys.h\nkitty/charsets.c\nkitty/unicode-data.c\nkitty/key_encoding.py\nkitty/rgb.py\nkitty/gl.h\nkitty/gl-wrapper.h\nkitty/gl-wrapper.c\nkitty/khrplatform.h\nkitty/glfw-wrapper.h\nkitty/glfw-wrapper.c\nkitty/emoji.h\nkittens/unicode_input/names.h') kitty kittens
|
cloc --exclude-list-file <(echo -e 'kitty/wcwidth-std.h\nkitty/glfw.c\nkitty/keys.h\nkitty/charsets.c\nkitty/unicode-data.c\nkitty/key_encoding.py\nkitty/rgb.py\nkitty/gl.h\nkitty/gl-wrapper.h\nkitty/gl-wrapper.c\nkitty/khrplatform.h\nkitty/glfw-wrapper.h\nkitty/glfw-wrapper.c\nkitty/emoji.h\nkittens/unicode_input/names.h') kitty kittens
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
SPHINXOPTS = -T $(FAIL_WARN)
|
SPHINXOPTS = -j auto -T $(FAIL_WARN)
|
||||||
SPHINXBUILD = python3 .. +launch :sphinx-build
|
SPHINXBUILD = sphinx-build
|
||||||
SPHINXPROJ = kitty
|
SPHINXPROJ = kitty
|
||||||
SOURCEDIR = .
|
SOURCEDIR = .
|
||||||
BUILDDIR = _build
|
BUILDDIR = _build
|
||||||
|
|||||||
9
docs/_templates/layout.html
vendored
9
docs/_templates/layout.html
vendored
@@ -1,13 +1,6 @@
|
|||||||
{% extends "!layout.html" %}
|
{% extends "!layout.html" %}
|
||||||
|
|
||||||
{%- block extrahead %}
|
{%- block extrahead %}
|
||||||
<!-- Google Analytics -->
|
<!-- kitty analytics placeholder -->
|
||||||
<script>
|
|
||||||
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
|
|
||||||
ga('create', 'UA-20736318-2', 'auto');
|
|
||||||
ga('send', 'pageview');
|
|
||||||
</script>
|
|
||||||
<script async="async" src='https://www.google-analytics.com/analytics.js'></script>
|
|
||||||
<!-- End Google Analytics -->
|
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Building kitty from source
|
Building kitty from source
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
.. image:: https://travis-ci.org/kovidgoyal/kitty.svg?branch=master
|
.. image:: https://circleci.com/gh/kovidgoyal/kitty.svg?style=svg
|
||||||
:alt: Build status
|
:alt: Build status
|
||||||
:target: https://travis-ci.org/kovidgoyal/kitty
|
:target: https://circleci.com/gh/kovidgoyal/kitty
|
||||||
|
|
||||||
|
|
||||||
|kitty| is designed to run from source, for easy hackability. Make sure
|
|kitty| is designed to run from source, for easy hackability. Make sure
|
||||||
@@ -107,7 +107,13 @@ without needing to install all of |kitty|.
|
|||||||
development package of :file:`ncurses`. Also, if you are building from
|
development package of :file:`ncurses`. Also, if you are building from
|
||||||
a git checkout instead of the released source code tarball, you will
|
a git checkout instead of the released source code tarball, you will
|
||||||
need :file:`sphinx-build` from the `Sphinx documentation generator
|
need :file:`sphinx-build` from the `Sphinx documentation generator
|
||||||
<http://www.sphinx-doc.org/>`_.
|
<https://www.sphinx-doc.org/>`_.
|
||||||
|
|
||||||
This applies to creating packages for |kitty| for macOS package managers such as
|
This applies to creating packages for |kitty| for macOS package managers such as
|
||||||
brew or MacPorts as well.
|
brew or MacPorts as well.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|kitty| has its own update check mechanism, if you would like to turn
|
||||||
|
it off for your package, use
|
||||||
|
``python3 setup.py linux-package --update-check-interval=0``
|
||||||
|
|||||||
@@ -2,6 +2,219 @@ Changelog
|
|||||||
==============
|
==============
|
||||||
|
|
||||||
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
||||||
|
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||||
|
|
||||||
|
0.14.2 [2019-06-09]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Add an option :opt:`placement_strategy` to control how the cell area is
|
||||||
|
aligned inside the window when the window size is not an exact multiple
|
||||||
|
of the cell size (:pull:`1670`)
|
||||||
|
|
||||||
|
- hints kitten: Add a :option:`kitty +kitten hints --multiple-joiner` option to
|
||||||
|
control how multiple selections are serialized when copying to clipboard
|
||||||
|
or inserting into the terminal. You can have them on separate lines,
|
||||||
|
separated by arbitrary characters, or even serialized as JSON (:iss:`1665`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression in the previous release that broke using
|
||||||
|
:kbd:`ctrl+shift+tab` (:iss:`1671`)
|
||||||
|
|
||||||
|
- panel kitten: Fix the contents of the panel kitten not being positioned
|
||||||
|
correctly on the vertical axis
|
||||||
|
|
||||||
|
- icat kitten: Fix a regression that broke passing directories to icat
|
||||||
|
(:iss:`1683`)
|
||||||
|
|
||||||
|
- clipboard kitten: Add a :option:`kitty +kitten clipboard --wait-for-completion`
|
||||||
|
option to have the kitten wait till copying to clipboard is complete
|
||||||
|
(:iss:`1693`)
|
||||||
|
|
||||||
|
- Allow using the :doc:`pipe <pipe>` command to send screen and scrollback
|
||||||
|
contents directly to the clipboard (:iss:`1693`)
|
||||||
|
|
||||||
|
- Linux: Disable the Wayland backend on GNOME by default as GNOME has no
|
||||||
|
support for server side decorations. Can be controlled by
|
||||||
|
:opt:`linux_display_server`.
|
||||||
|
|
||||||
|
- Add an option to control the default :opt:`update_check_interval` when
|
||||||
|
building kitty packages
|
||||||
|
|
||||||
|
- Wayland: Fix resizing the window on a compositor that does not provide
|
||||||
|
server side window decorations, such a GNOME or Weston not working
|
||||||
|
correctly (:iss:`1659`)
|
||||||
|
|
||||||
|
- Wayland: Fix crash when enabling disabling monitors on sway (:iss:`1696`)
|
||||||
|
|
||||||
|
|
||||||
|
0.14.1 [2019-05-29]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Add an option :opt:`command_on_bell` to run an arbitrary command when
|
||||||
|
a bell occurs (:iss:`1660`)
|
||||||
|
|
||||||
|
- Add a shortcut to toggle maximized window state :sc:`toggle_maximized`
|
||||||
|
|
||||||
|
- Add support for the underscore key found in some keyboard layouts
|
||||||
|
(:iss:`1639`)
|
||||||
|
|
||||||
|
- Fix a missing newline when using the pipe command between the
|
||||||
|
scrollback and screen contents (:iss:`1642`)
|
||||||
|
|
||||||
|
- Fix colors not being preserved when using the pipe command with
|
||||||
|
the pager history buffer (:pull:`1657`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression that could cause rendering of a kitty window
|
||||||
|
to occasionally freeze in certain situations, such as moving it between
|
||||||
|
monitors or transitioning from/to fullscreen (:iss:`1641`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression that caused :kbd:`cmd+v` to double up in the dvorak
|
||||||
|
keyboard layout (:iss:`1652`)
|
||||||
|
|
||||||
|
- When resizing and only a single window is present in the current layout,
|
||||||
|
use that window's background color to fill in the blank areas.
|
||||||
|
|
||||||
|
- Linux: Automatically increase cell height if the font being used is broken
|
||||||
|
and draws the underscore outside the bounding box (:iss:`690`)
|
||||||
|
|
||||||
|
- Wayland: Fix maximizing the window on a compositor that does not provide
|
||||||
|
server side window decorations, such a GNOME or Weston not working
|
||||||
|
(:iss:`1662`)
|
||||||
|
|
||||||
|
|
||||||
|
0.14.0 [2019-05-24]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- macOS: The default behavior of the Option key has changed. It now generates
|
||||||
|
unicode characters rather than acting as the :kbd:`Alt` modifier. See
|
||||||
|
:opt:`macos_option_as_alt`.
|
||||||
|
|
||||||
|
- Support for an arbitrary number of internal clipboard buffers to copy/paste
|
||||||
|
from, see (:ref:`cpbuf`)
|
||||||
|
|
||||||
|
- Allow using the new private internal clipboard buffers with the
|
||||||
|
:opt:`copy_on_select` option (:iss:`1390`)
|
||||||
|
|
||||||
|
- macOS: Allow opening new kitty tabs/top-level windows from Finder
|
||||||
|
(:pull:`1350`)
|
||||||
|
|
||||||
|
- Add an option :opt:`disable_ligatures` to disable
|
||||||
|
multi-character ligatures under the cursor to make editing easier
|
||||||
|
or disable them completely (:iss:`461`)
|
||||||
|
|
||||||
|
- Allow creating new OS windows in session files (:iss:`1514`)
|
||||||
|
|
||||||
|
- Allow setting OS window size in session files
|
||||||
|
|
||||||
|
- Add an option :opt:`tab_switch_strategy` to control which
|
||||||
|
tab becomes active when the current tab is closed (:pull:`1524`)
|
||||||
|
|
||||||
|
- Allow specifying a value of ``none`` for the :opt:`selection_foreground`
|
||||||
|
which will cause kitty to not change text color in selections (:iss:`1358`)
|
||||||
|
|
||||||
|
- Make live resizing of OS windows smoother and add an option
|
||||||
|
:opt:`resize_draw_strategy` to control what is drawn while a
|
||||||
|
resize is in progress.
|
||||||
|
|
||||||
|
- macOS: Improve handling of IME extended input. Compose characters
|
||||||
|
are now highlighted and the IME panel moves along with the text
|
||||||
|
(:pull:`1586`). Also fixes handling of delete key in Chinese IME
|
||||||
|
(:iss:`1461`)
|
||||||
|
|
||||||
|
- When a window is closed, switch focus to the previously active window (if
|
||||||
|
any) instead of picking the previous window in the layout (:iss:`1450`)
|
||||||
|
|
||||||
|
- icat kitten: Add support for displaying images at http(s) URLs (:iss:`1340`)
|
||||||
|
|
||||||
|
- A new option :opt:`strip_trailing_spaces` to optionally remove trailing
|
||||||
|
spaces from lines when copying to clipboard.
|
||||||
|
|
||||||
|
- A new option :opt:`tab_bar_min_tabs` to control how many tabs must be
|
||||||
|
present before the tab-bar is shown (:iss:`1382`)
|
||||||
|
|
||||||
|
- Automatically check for new releases and notify when an update is available,
|
||||||
|
via the system notification facilities. Can be controlled by
|
||||||
|
:opt:`update_check_interval` (:iss:`1342`)
|
||||||
|
|
||||||
|
- macOS: Fix :kbd:`cmd+period` key not working (:iss:`1318`)
|
||||||
|
|
||||||
|
- macOS: Add an option :opt:`macos_show_window_title_in_menubar` to not
|
||||||
|
show the current window title in the menu-bar (:iss:`1066`)
|
||||||
|
|
||||||
|
- macOS: Workaround for cocoa bug that could cause the mouse cursor to become
|
||||||
|
hidden in other applications in rare circumstances (:iss:`1218`)
|
||||||
|
|
||||||
|
- macOS: Allow assigning only the left or right :kbd:`Option` key to work as the
|
||||||
|
:kbd:`Alt` key. See :opt:`macos_option_as_alt` for details (:iss:`1022`)
|
||||||
|
|
||||||
|
- Fix using remote control to set cursor text color causing errors when
|
||||||
|
creating new windows (:iss:`1326`)
|
||||||
|
|
||||||
|
- Fix window title for minimized windows not being updated (:iss:`1332`)
|
||||||
|
|
||||||
|
- macOS: Fix using multi-key sequences to input text ignoring the
|
||||||
|
first few key presses if the sequence is aborted (:iss:`1311`)
|
||||||
|
|
||||||
|
- macOS: Add a number of common macOS keyboard shortcuts
|
||||||
|
|
||||||
|
- macOS: Reduce energy consumption by not rendering occluded windows
|
||||||
|
|
||||||
|
- Fix scrollback pager history not being cleared when clearing the
|
||||||
|
main scrollback buffer (:iss:`1387`)
|
||||||
|
|
||||||
|
- macOS: When closing a top-level window only switch focus to the previous kitty
|
||||||
|
window if it is on the same workspace (:iss:`1379`)
|
||||||
|
|
||||||
|
- macOS: Fix :opt:`sync_to_monitor` not working on Mojave.
|
||||||
|
|
||||||
|
- macOS: Use the system cursor blink interval by default
|
||||||
|
:opt:`cursor_blink_interval`.
|
||||||
|
|
||||||
|
- Wayland: Use the kitty Wayland backend by default. Can be switched back
|
||||||
|
to using XWayland by setting the environment variable:
|
||||||
|
``KITTY_DISABLE_WAYLAND=1``
|
||||||
|
|
||||||
|
- Add a ``no-append`` setting to :opt:`clipboard_control` to disable
|
||||||
|
the kitty copy concatenation protocol extension for OSC 52.
|
||||||
|
|
||||||
|
- Update to using the Unicode 12 standard
|
||||||
|
|
||||||
|
- Unicode input kitten: Allow using the arrow keys in code mode to go to next
|
||||||
|
and previous unicode symbol.
|
||||||
|
|
||||||
|
- macOS: Fix specifying initial window size in cells not working correctly on
|
||||||
|
Retina screens (:iss:`1444`)
|
||||||
|
|
||||||
|
- Fix a regression in version 0.13.0 that caused background colors of space
|
||||||
|
characters after private use unicode characters to not be respected
|
||||||
|
(:iss:`1455`)
|
||||||
|
|
||||||
|
- Only update the selected text to clipboard when the selection is finished,
|
||||||
|
not continuously as it is updated. (:iss:`1460`)
|
||||||
|
|
||||||
|
- Allow setting :opt:`active_border_color` to ``none`` to not draw a border
|
||||||
|
around the active window (:iss:`805`)
|
||||||
|
|
||||||
|
- Use negative values for :opt:`mouse_hide_wait` to hide the mouse cursor
|
||||||
|
immediately when pressing a key (:iss:`1534`)
|
||||||
|
|
||||||
|
- When encountering errors in :file:`kitty.conf` report them to the user
|
||||||
|
instead of failing to start.
|
||||||
|
|
||||||
|
- Allow the user to control the resize debounce time via
|
||||||
|
:opt:`resize_debounce_time`.
|
||||||
|
|
||||||
|
- Remote control: Make the :ref:`at_set-font-size` command more capable.
|
||||||
|
It can now increment font size and reset it. It also only acts on the
|
||||||
|
active top-level window, by default (:iss:`1581`)
|
||||||
|
|
||||||
|
- When launching child processes set the :code:`PWD` environment variable
|
||||||
|
(:iss:`1595`)
|
||||||
|
|
||||||
|
- X11: use the window manager's native full-screen implementation when
|
||||||
|
making windows full-screen (:iss:`1605`)
|
||||||
|
|
||||||
|
- Mouse selection: When extending by word, fix extending selection to non-word
|
||||||
|
characters not working well (:iss:`1616`)
|
||||||
|
|
||||||
0.13.3 [2019-01-19]
|
0.13.3 [2019-01-19]
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|||||||
18
docs/conf.py
18
docs/conf.py
@@ -1,15 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Configuration file for the Sphinx documentation builder.
|
# Configuration file for the Sphinx documentation builder.
|
||||||
#
|
#
|
||||||
# This file does only contain a selection of the most common options. For a
|
# This file does only contain a selection of the most common options. For a
|
||||||
# full list see the documentation:
|
# full list see the documentation:
|
||||||
# http://www.sphinx-doc.org/en/master/config
|
# https://www.sphinx-doc.org/en/master/config
|
||||||
|
|
||||||
|
import importlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
@@ -19,15 +22,19 @@ from pygments.token import (
|
|||||||
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
||||||
)
|
)
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.util.logging import getLogger
|
from sphinx.util.logging import getLogger
|
||||||
|
|
||||||
from kitty.constants import str_version
|
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
if kitty_src not in sys.path:
|
||||||
|
sys.path.insert(0, kitty_src)
|
||||||
|
str_version = importlib.import_module('kitty.constants').str_version
|
||||||
|
|
||||||
# config {{{
|
# config {{{
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
project = 'kitty'
|
project = 'kitty'
|
||||||
copyright = '2018, Kovid Goyal'
|
copyright = time.strftime('%Y, Kovid Goyal')
|
||||||
author = 'Kovid Goyal'
|
author = 'Kovid Goyal'
|
||||||
building_man_pages = 'man' in sys.argv
|
building_man_pages = 'man' in sys.argv
|
||||||
|
|
||||||
@@ -175,7 +182,7 @@ texinfo_documents = [
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# GitHub linking inlne roles {{{
|
# GitHub linking inline roles {{{
|
||||||
|
|
||||||
def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||||
' Link to a github issue '
|
' Link to a github issue '
|
||||||
@@ -214,7 +221,8 @@ def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
|
|
||||||
# Sidebar ToC {{{
|
# Sidebar ToC {{{
|
||||||
def create_toc(app, pagename):
|
def create_toc(app, pagename):
|
||||||
toctree = app.env.get_toc_for(pagename, app.builder)
|
tt = TocTree(app.env)
|
||||||
|
toctree = tt.get_toc_for(pagename, app.builder)
|
||||||
if toctree is not None:
|
if toctree is not None:
|
||||||
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
||||||
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ You can also display the current configuration by running ``kitty
|
|||||||
:option:`kitty --config` option or use the ``KITTY_CONFIG_DIRECTORY``
|
:option:`kitty --config` option or use the ``KITTY_CONFIG_DIRECTORY``
|
||||||
environment variable. See the :option:`kitty --config` option for full details.
|
environment variable. See the :option:`kitty --config` option for full details.
|
||||||
|
|
||||||
|
Comments can be added to the config file as lines starting with the ``#``
|
||||||
|
character. This works only if the ``#`` character is the first character
|
||||||
|
in the line.
|
||||||
|
|
||||||
You can include secondary config files via the :code:`include` directive. If
|
You can include secondary config files via the :code:`include` directive. If
|
||||||
you use a relative path for include, it is resolved with respect to the
|
you use a relative path for include, it is resolved with respect to the
|
||||||
location of the current config file. Note that environment variables are
|
location of the current config file. Note that environment variables are
|
||||||
|
|||||||
10
docs/faq.rst
10
docs/faq.rst
@@ -81,6 +81,11 @@ Shell providing the right terminfo path::
|
|||||||
sudo … env TERMINFO=$HOME/.terminfo bash -i
|
sudo … env TERMINFO=$HOME/.terminfo bash -i
|
||||||
TERMINFO=/home/ORIGINALUSER/.terminfo exec bash -i
|
TERMINFO=/home/ORIGINALUSER/.terminfo exec bash -i
|
||||||
|
|
||||||
|
You can configure sudo to preserve TERMINFO by running ``sudo
|
||||||
|
visudo`` and adding the following line::
|
||||||
|
|
||||||
|
Defaults env_keep += "TERM TERMINFO"
|
||||||
|
|
||||||
If you have double width characters in your prompt, you may also need to
|
If you have double width characters in your prompt, you may also need to
|
||||||
explicitly set a UTF-8 locale, like::
|
explicitly set a UTF-8 locale, like::
|
||||||
|
|
||||||
@@ -91,10 +96,13 @@ How do I change the colors in a running kitty instance?
|
|||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
You can either use the
|
You can either use the
|
||||||
`OSC terminal escape codes <http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
|
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
|
||||||
to set colors or you can enable :doc:`remote control <remote-control>`
|
to set colors or you can enable :doc:`remote control <remote-control>`
|
||||||
for |kitty| and use :ref:`at_set-colors`.
|
for |kitty| and use :ref:`at_set-colors`.
|
||||||
|
|
||||||
|
A list of pre-made color themes for kitty is available at:
|
||||||
|
`kitty-themes <https://github.com/dexpota/kitty-themes>`_
|
||||||
|
|
||||||
|
|
||||||
How do I specify command line options for kitty on macOS?
|
How do I specify command line options for kitty on macOS?
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ kitty - the fast, featureful, GPU based terminal emulator
|
|||||||
separate window using arbitrary programs of your choice. This is useful for
|
separate window using arbitrary programs of your choice. This is useful for
|
||||||
browsing the history comfortably in a pager or editor.
|
browsing the history comfortably in a pager or editor.
|
||||||
|
|
||||||
|
* Has :ref:`multiple copy/paste buffers <cpbuf>`, like vim.
|
||||||
|
|
||||||
|
|
||||||
.. figure:: screenshots/screenshot.png
|
.. figure:: screenshots/screenshot.png
|
||||||
:alt: Screenshot, showing three programs in the 'Tall' layout
|
:alt: Screenshot, showing three programs in the 'Tall' layout
|
||||||
@@ -54,15 +56,18 @@ Pre-built binaries of |kitty| are available for both macOS and Linux.
|
|||||||
See the :doc:`binary install instructions </binary>`. You can also
|
See the :doc:`binary install instructions </binary>`. You can also
|
||||||
:doc:`build from source </build>`.
|
:doc:`build from source </build>`.
|
||||||
|
|
||||||
If you are on Linux, you can also use your distribution's |kitty| package.
|
You can also use your favorite package manager to install the |kitty| package.
|
||||||
|kitty| packages are available for:
|
|kitty| packages are available for:
|
||||||
|
`macOS with Homebrew (Cask) <https://formulae.brew.sh/cask/kitty>`_,
|
||||||
|
`macOS and Linux with Nix <https://nixos.org/nixos/packages.html#kitty>`_,
|
||||||
|
`Ubuntu <https://launchpad.net/ubuntu/+source/kitty>`_,
|
||||||
`Debian <https://packages.debian.org/buster/kitty>`_,
|
`Debian <https://packages.debian.org/buster/kitty>`_,
|
||||||
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
||||||
`Arch Linux <https://www.archlinux.org/packages/community/x86_64/kitty/>`_,
|
`Arch Linux <https://www.archlinux.org/packages/community/x86_64/kitty/>`_,
|
||||||
`NixOS <https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/misc/kitty/default.nix>`_,
|
|
||||||
`Gentoo <https://packages.gentoo.org/packages/x11-terms/kitty>`_,
|
`Gentoo <https://packages.gentoo.org/packages/x11-terms/kitty>`_,
|
||||||
`Fedora <https://copr.fedorainfracloud.org/coprs/gagbo/kitty-latest/>`_,
|
`Fedora <https://copr.fedorainfracloud.org/coprs/gagbo/kitty-latest/>`_,
|
||||||
`Void Linux <https://github.com/void-linux/void-packages/blob/master/srcpkgs/kitty/template>`_.
|
`Void Linux <https://github.com/void-linux/void-packages/blob/master/srcpkgs/kitty/template>`_,
|
||||||
|
and `Solus <https://dev.getsol.us/source/kitty/>`_.
|
||||||
|
|
||||||
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
See :doc:`Configuring kitty <conf>` for help on configuring |kitty| and
|
||||||
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
:doc:`Invocation <invocation>` for the command line arguments |kitty| supports.
|
||||||
@@ -90,7 +95,7 @@ formatting, etc. It even extends existing text formatting escape codes,
|
|||||||
to add support for features not available elsewhere, such as colored and
|
to add support for features not available elsewhere, such as colored and
|
||||||
styled (curly) underlines. One of the design goals of |kitty| is to be
|
styled (curly) underlines. One of the design goals of |kitty| is to be
|
||||||
easily extensible so that new features can be added in the future with
|
easily extensible so that new features can be added in the future with
|
||||||
relatively less effort.
|
relatively little effort.
|
||||||
|
|
||||||
Tabs and Windows
|
Tabs and Windows
|
||||||
-------------------
|
-------------------
|
||||||
@@ -108,12 +113,12 @@ Scrolling
|
|||||||
======================== =======================
|
======================== =======================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
======================== =======================
|
======================== =======================
|
||||||
Scroll line up :sc:`scroll_line_up`
|
Scroll line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS)
|
||||||
Scroll line down :sc:`scroll_line_down`
|
Scroll line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS)
|
||||||
Scroll page up :sc:`scroll_page_up`
|
Scroll page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS)
|
||||||
Scroll page down :sc:`scroll_page_down`
|
Scroll page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS)
|
||||||
Scroll to top :sc:`scroll_home`
|
Scroll to top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS)
|
||||||
Scroll to bottom :sc:`scroll_end`
|
Scroll to bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS)
|
||||||
======================== =======================
|
======================== =======================
|
||||||
|
|
||||||
Tabs
|
Tabs
|
||||||
@@ -123,13 +128,13 @@ Tabs
|
|||||||
Action Shortcut
|
Action Shortcut
|
||||||
======================== =======================
|
======================== =======================
|
||||||
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
|
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
|
||||||
Close tab :sc:`close_tab`
|
Close tab :sc:`close_tab` (also :kbd:`⌘+w` on macOS)
|
||||||
Next tab :sc:`next_tab` (also :kbd:`control+tab` on macOS)
|
Next tab :sc:`next_tab` (also :kbd:`^+⇥` and :kbd:`⇧+⌘+]` on macOS)
|
||||||
Previous tab :sc:`previous_tab` (also :kbd:`control+shift+tab` on macOS)
|
Previous tab :sc:`previous_tab` (also :kbd:`⇧+^+⇥` and :kbd:`⇧+⌘+[` on macOS)
|
||||||
Next layout :sc:`next_layout`
|
Next layout :sc:`next_layout`
|
||||||
Move tab forward :sc:`move_tab_forward`
|
Move tab forward :sc:`move_tab_forward`
|
||||||
Move tab backward :sc:`move_tab_backward`
|
Move tab backward :sc:`move_tab_backward`
|
||||||
Set tab title :sc:`set_tab_title`
|
Set tab title :sc:`set_tab_title` (also :kbd:`⇧+⌘+i` on macOS)
|
||||||
======================== =======================
|
======================== =======================
|
||||||
|
|
||||||
|
|
||||||
@@ -139,15 +144,16 @@ Windows
|
|||||||
======================== =======================
|
======================== =======================
|
||||||
Action Shortcut
|
Action Shortcut
|
||||||
======================== =======================
|
======================== =======================
|
||||||
New window :sc:`new_window`
|
New window :sc:`new_window` (also :kbd:`⌘+↩` on macOS)
|
||||||
New OS window :sc:`new_os_window` (also :kbd:`⌘+n` on macOS)
|
New OS window :sc:`new_os_window` (also :kbd:`⌘+n` on macOS)
|
||||||
Close window :sc:`close_window` (also :kbd:`⌘+w` on macOS)
|
Close window :sc:`close_window` (also :kbd:`⇧+⌘+d` on macOS)
|
||||||
Next window :sc:`next_window`
|
Next window :sc:`next_window`
|
||||||
Previous window :sc:`previous_window`
|
Previous window :sc:`previous_window`
|
||||||
Move window forward :sc:`move_window_forward`
|
Move window forward :sc:`move_window_forward`
|
||||||
Move window backward :sc:`move_window_backward`
|
Move window backward :sc:`move_window_backward`
|
||||||
Move window to top :sc:`move_window_to_top`
|
Move window to top :sc:`move_window_to_top`
|
||||||
Focus specific window :sc:`first_window`, :sc:`second_window` ... :sc:`tenth_window`
|
Focus specific window :sc:`first_window`, :sc:`second_window` ... :sc:`tenth_window`
|
||||||
|
(also :kbd:`⌘+1`, :kbd:`⌘+2` ... :kbd:`⌘+9` on macOS)
|
||||||
(clockwise from the top-left)
|
(clockwise from the top-left)
|
||||||
======================== =======================
|
======================== =======================
|
||||||
|
|
||||||
@@ -177,11 +183,11 @@ Action Shortcut
|
|||||||
Copy to clipboard :sc:`copy_to_clipboard` (also :kbd:`⌘+c` on macOS)
|
Copy to clipboard :sc:`copy_to_clipboard` (also :kbd:`⌘+c` on macOS)
|
||||||
Paste from clipboard :sc:`paste_from_clipboard` (also :kbd:`⌘+v` on macOS)
|
Paste from clipboard :sc:`paste_from_clipboard` (also :kbd:`⌘+v` on macOS)
|
||||||
Paste from selection :sc:`paste_from_selection`
|
Paste from selection :sc:`paste_from_selection`
|
||||||
Increase font size :sc:`increase_font_size`
|
Increase font size :sc:`increase_font_size` (also :kbd:`⌘++` on macOS)
|
||||||
Decrease font size :sc:`decrease_font_size`
|
Decrease font size :sc:`decrease_font_size` (also :kbd:`⌘+-` on macOS)
|
||||||
Restore font size :sc:`reset_font_size`
|
Restore font size :sc:`reset_font_size` (also :kbd:`⌘+0` on macOS)
|
||||||
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`^⌘+f` on macOS)
|
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`^+⌘+f` on macOS)
|
||||||
on
|
Toggle maximized :sc:`toggle_maximized`
|
||||||
Input unicode character :sc:`input_unicode_character`
|
Input unicode character :sc:`input_unicode_character`
|
||||||
Click URL using the keyboard :sc:`open_url`
|
Click URL using the keyboard :sc:`open_url`
|
||||||
Reset the terminal :sc:`reset_terminal`
|
Reset the terminal :sc:`reset_terminal`
|
||||||
@@ -216,7 +222,7 @@ You can switch between layouts using the :sc:`next_layout` key combination. You
|
|||||||
also create shortcuts to select particular layouts, and choose which layouts
|
also create shortcuts to select particular layouts, and choose which layouts
|
||||||
you want to enable/disable, see :ref:`conf-kitty-shortcuts.layout` for examples.
|
you want to enable/disable, see :ref:`conf-kitty-shortcuts.layout` for examples.
|
||||||
|
|
||||||
You can resize windows inside layouts. Press :sc:`start_resizing_window` to
|
You can resize windows inside layouts. Press :sc:`start_resizing_window` (also :kbd:`⌘+r` on macOS) to
|
||||||
enter resizing mode and follow the on-screen instructions. In a given window
|
enter resizing mode and follow the on-screen instructions. In a given window
|
||||||
layout only some operations may be possible for a particular window. For
|
layout only some operations may be possible for a particular window. For
|
||||||
example, in the Tall layout you can make the first window wider/narrower, but
|
example, in the Tall layout you can make the first window wider/narrower, but
|
||||||
@@ -340,6 +346,12 @@ For example:
|
|||||||
# Set the current layout
|
# Set the current layout
|
||||||
layout stack
|
layout stack
|
||||||
launch zsh
|
launch zsh
|
||||||
|
|
||||||
|
# Create a new OS window
|
||||||
|
new_os_window
|
||||||
|
# set new window size to 80x25 cells
|
||||||
|
os_window_size 80c 25c
|
||||||
|
launch sh
|
||||||
# Make the current window the active (focused) window
|
# Make the current window the active (focused) window
|
||||||
focus
|
focus
|
||||||
launch emacs
|
launch emacs
|
||||||
@@ -348,11 +360,14 @@ For example:
|
|||||||
Mouse features
|
Mouse features
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
* You can also hold down :kbd:`ctrl+shift` and click on a URL to open it in a browser.
|
* You can hold down :kbd:`ctrl+shift` and click on a URL to open it in a browser.
|
||||||
* You can double click to select a word and triple click to select a line.
|
* You can double click to select a word and then drag to select more words.
|
||||||
* You can right click to extend a previous selection
|
* You can triple click to select a line and then drag to select more lines.
|
||||||
|
* You can right click to extend a previous selection.
|
||||||
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
* You can hold down :kbd:`ctrl+alt` and drag with the mouse to select in
|
||||||
columns
|
columns.
|
||||||
|
* Selecting text automatically copies it to the primary clipboard (on
|
||||||
|
platforms with a primary clipboard).
|
||||||
|
|
||||||
|
|
||||||
Font control
|
Font control
|
||||||
@@ -394,6 +409,23 @@ If you wish to store very large amounts of scrollback to view using the piping o
|
|||||||
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
||||||
option.
|
option.
|
||||||
|
|
||||||
|
.. _cpbuf:
|
||||||
|
|
||||||
|
Multiple copy/paste buffers
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
In addition to being able to copy/paste from the system clipboard, in |kitty| you
|
||||||
|
can also setup an arbitrary number of copy paste buffers. To do so, simply add
|
||||||
|
something like the following to your :file:`kitty.conf`::
|
||||||
|
|
||||||
|
map f1 copy_to_buffer a
|
||||||
|
map f2 paste_from_buffer a
|
||||||
|
|
||||||
|
This will allow you to press :kbd:`F1` to copy the current selection to an
|
||||||
|
internal buffer named ``a`` and :kbd:`F2` to paste from that buffer. The buffer
|
||||||
|
names are arbitrary strings, so you can define as many such buffers as you
|
||||||
|
need.
|
||||||
|
|
||||||
Frequently Asked Questions
|
Frequently Asked Questions
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
@@ -72,7 +72,10 @@ class Reporter: # {{{
|
|||||||
def get_latest_release_data():
|
def get_latest_release_data():
|
||||||
print('Checking for latest release on GitHub...')
|
print('Checking for latest release on GitHub...')
|
||||||
req = urllib.Request('https://api.github.com/repos/kovidgoyal/kitty/releases/latest', headers={'Accept': 'application/vnd.github.v3+json'})
|
req = urllib.Request('https://api.github.com/repos/kovidgoyal/kitty/releases/latest', headers={'Accept': 'application/vnd.github.v3+json'})
|
||||||
res = urllib.urlopen(req).read().decode('utf-8')
|
try:
|
||||||
|
res = urllib.urlopen(req).read().decode('utf-8')
|
||||||
|
except Exception as err:
|
||||||
|
raise SystemExit('Failed to contact {} with error: {}'.format(req.get_full_url(), err))
|
||||||
data = json.loads(res)
|
data = json.loads(res)
|
||||||
html_url = data['html_url'].replace('/tag/', '/download/').rstrip('/')
|
html_url = data['html_url'].replace('/tag/', '/download/').rstrip('/')
|
||||||
for asset in data.get('assets', ()):
|
for asset in data.get('assets', ()):
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ In :guilabel:`Code` mode, you enter a unicode character by typing in the hex cod
|
|||||||
character and pressing enter, for example, type in ``2716`` and press enter to get
|
character and pressing enter, for example, type in ``2716`` and press enter to get
|
||||||
✖. You can also choose a character from the list of recently used characters by
|
✖. You can also choose a character from the list of recently used characters by
|
||||||
typing a leading period and then the two character index and pressing Enter.
|
typing a leading period and then the two character index and pressing Enter.
|
||||||
|
The up and down arrow keys can be used to choose the previous and next unicode
|
||||||
|
symbol respectively.
|
||||||
|
|
||||||
In :guilabel:`Name` mode you instead type words from the character name and use the arrow
|
In :guilabel:`Name` mode you instead type words from the character name and use the arrow
|
||||||
keys/tab to select the character from the displayed matches. You can also type
|
keys/tab to select the character from the displayed matches. You can also type
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ You can choose where to run the pipe program:
|
|||||||
``tab``
|
``tab``
|
||||||
A new window in a new tab
|
A new window in a new tab
|
||||||
|
|
||||||
|
``clipboard, primary``
|
||||||
|
Copy the text directly to the clipboard. In this case the specified program
|
||||||
|
is not run, so use some dummy program name for it.
|
||||||
|
|
||||||
``none``
|
``none``
|
||||||
Run it in the background
|
Run it in the background
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ To reset the underline color (also previously reserved and unused)::
|
|||||||
|
|
||||||
<ESC>[59m
|
<ESC>[59m
|
||||||
|
|
||||||
|
The underline color must remain the same under reverse video, if it has a
|
||||||
|
color, if not, it should follow the foreground color.
|
||||||
|
|
||||||
To detect support for this feature in a terminal emulator, query the terminfo database
|
To detect support for this feature in a terminal emulator, query the terminfo database
|
||||||
for the ``Su`` boolean capability.
|
for the ``Su`` boolean capability.
|
||||||
|
|
||||||
@@ -133,6 +136,10 @@ Alt -- ``0x2``, Control -- ``0x4`` and Super -- ``0x8``. ``<key>`` is a number
|
|||||||
(encoded in base85) corresponding to the key pressed. The key name to number
|
(encoded in base85) corresponding to the key pressed. The key name to number
|
||||||
mapping is defined in :doc:`this table <key-encoding>`.
|
mapping is defined in :doc:`this table <key-encoding>`.
|
||||||
|
|
||||||
|
Client programs must ignore events for keys they do not know. The mapping in
|
||||||
|
the above table is stable and will never change, however, new codes might be
|
||||||
|
added to it in the future, for new keys.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
<ESC>_KpGp<ESC>\ is <Ctrl>+<Alt>+x (press)
|
<ESC>_KpGp<ESC>\ is <Ctrl>+<Alt>+x (press)
|
||||||
@@ -141,6 +148,10 @@ For example::
|
|||||||
This encoding means each key event is represented by 8 or 9 printable ascii
|
This encoding means each key event is represented by 8 or 9 printable ascii
|
||||||
only bytes, for maximum robustness.
|
only bytes, for maximum robustness.
|
||||||
|
|
||||||
|
To see the full mode in action, run::
|
||||||
|
|
||||||
|
kitty +kitten key_demo
|
||||||
|
|
||||||
Support for this mode is indicated by the ``fullkbd`` boolean capability
|
Support for this mode is indicated by the ``fullkbd`` boolean capability
|
||||||
in the terminfo database, in case querying for it via DECQRM is inconvenient.
|
in the terminfo database, in case querying for it via DECQRM is inconvenient.
|
||||||
|
|
||||||
@@ -160,7 +171,7 @@ The motivation for this extension is the various problems with the existing
|
|||||||
solution for erasing to background color, namely the *background color erase
|
solution for erasing to background color, namely the *background color erase
|
||||||
(bce)* capability. See
|
(bce)* capability. See
|
||||||
`this discussion <https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545>`_
|
`this discussion <https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545>`_
|
||||||
and `this FAQ <http://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`_
|
and `this FAQ <https://invisible-island.net/ncurses/ncurses.faq.html#bce_mismatches>`_
|
||||||
for a summary of problems with *bce*.
|
for a summary of problems with *bce*.
|
||||||
|
|
||||||
For example, to set the background color to blue in a
|
For example, to set the background color to blue in a
|
||||||
@@ -208,3 +219,7 @@ first, for example::
|
|||||||
<ESC>]52;c;!<ESC>\
|
<ESC>]52;c;!<ESC>\
|
||||||
|
|
||||||
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
||||||
|
|
||||||
|
In case you're using software that can't be easily adapted to this
|
||||||
|
protocol extension, it can be disabled by specifying ``no-append`` to the
|
||||||
|
:opt:`clipboard_control` setting.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPLv3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ def generate(function_name, callback_name, report_name, keymap, command_class, i
|
|||||||
report_cmd = cmd_for_report(report_name, keymap, type_map, payload_allowed)
|
report_cmd = cmd_for_report(report_name, keymap, type_map, payload_allowed)
|
||||||
if payload_allowed:
|
if payload_allowed:
|
||||||
payload_after_value = "case ';': state = PAYLOAD; break;"
|
payload_after_value = "case ';': state = PAYLOAD; break;"
|
||||||
payload = payload = ', PAYLOAD'
|
payload = ', PAYLOAD'
|
||||||
parr = 'static uint8_t payload[4096];'
|
parr = 'static uint8_t payload[4096];'
|
||||||
payload_case = f'''
|
payload_case = f'''
|
||||||
case PAYLOAD: {{
|
case PAYLOAD: {{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
@@ -281,7 +282,8 @@ def gen_ucd():
|
|||||||
p('combining_type mark_for_codepoint(char_type c) {')
|
p('combining_type mark_for_codepoint(char_type c) {')
|
||||||
rmap = codepoint_to_mark_map(p, mark_map)
|
rmap = codepoint_to_mark_map(p, mark_map)
|
||||||
p('}\n')
|
p('}\n')
|
||||||
if rmap[0xfe0e] != 1281:
|
expected = int(re.search(r'^#define VS15 (\d+)', open('kitty/unicode-data.h').read(), re.M).group(1))
|
||||||
|
if rmap[0xfe0e] != expected:
|
||||||
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
|
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
|
||||||
rmap[0xfe0e], rmap[0xfe0f]
|
rmap[0xfe0e], rmap[0xfe0f]
|
||||||
))
|
))
|
||||||
|
|||||||
35
glfw/backend_utils.c
vendored
35
glfw/backend_utils.c
vendored
@@ -21,16 +21,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline double
|
static inline double
|
||||||
monotonic() {
|
monotonic(void) {
|
||||||
struct timespec ts = {0};
|
struct timespec ts = {0};
|
||||||
#ifdef CLOCK_HIGHRES
|
#ifdef CLOCK_HIGHRES
|
||||||
clock_gettime(CLOCK_HIGHRES, &ts);
|
clock_gettime(CLOCK_HIGHRES, &ts);
|
||||||
#elif CLOCK_MONOTONIC_RAW
|
#elif CLOCK_MONOTONIC_RAW
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||||
#else
|
#else
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
#endif
|
#endif
|
||||||
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
|
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -55,6 +55,7 @@ addWatch(EventLoopData *eld, const char* name, int fd, int events, int enabled,
|
|||||||
w->fd = fd; w->events = events; w->enabled = enabled;
|
w->fd = fd; w->events = events; w->enabled = enabled;
|
||||||
w->callback = cb;
|
w->callback = cb;
|
||||||
w->callback_data = cb_data;
|
w->callback_data = cb_data;
|
||||||
|
w->free = NULL;
|
||||||
w->id = ++watch_counter;
|
w->id = ++watch_counter;
|
||||||
update_fds(eld);
|
update_fds(eld);
|
||||||
return w->id;
|
return w->id;
|
||||||
@@ -64,6 +65,10 @@ addWatch(EventLoopData *eld, const char* name, int fd, int events, int enabled,
|
|||||||
for (nfds_t i = 0; i < eld->which##_count; i++) { \
|
for (nfds_t i = 0; i < eld->which##_count; i++) { \
|
||||||
if (eld->which[i].id == item_id) { \
|
if (eld->which[i].id == item_id) { \
|
||||||
eld->which##_count--; \
|
eld->which##_count--; \
|
||||||
|
if (eld->which[i].callback_data && eld->which[i].free) { \
|
||||||
|
eld->which[i].free(eld->which[i].id, eld->which[i].callback_data); \
|
||||||
|
eld->which[i].callback_data = NULL; eld->which[i].free = NULL; \
|
||||||
|
} \
|
||||||
if (i < eld->which##_count) { \
|
if (i < eld->which##_count) { \
|
||||||
memmove(eld->which + i, eld->which + i + 1, sizeof(eld->which[0]) * (eld->which##_count - i)); \
|
memmove(eld->which + i, eld->which + i + 1, sizeof(eld->which[0]) * (eld->which##_count - i)); \
|
||||||
} \
|
} \
|
||||||
@@ -102,7 +107,7 @@ update_timers(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
id_type
|
id_type
|
||||||
addTimer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data) {
|
addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free) {
|
||||||
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -111,11 +116,13 @@ addTimer(EventLoopData *eld, const char *name, double interval, int enabled, tim
|
|||||||
t->interval = interval;
|
t->interval = interval;
|
||||||
t->name = name;
|
t->name = name;
|
||||||
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
||||||
|
t->repeats = repeats;
|
||||||
t->callback = cb;
|
t->callback = cb;
|
||||||
t->callback_data = cb_data;
|
t->callback_data = cb_data;
|
||||||
|
t->free = free;
|
||||||
t->id = ++timer_counter;
|
t->id = ++timer_counter;
|
||||||
update_timers(eld);
|
update_timers(eld);
|
||||||
return t->id;
|
return timer_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -123,6 +130,14 @@ removeTimer(EventLoopData *eld, id_type timer_id) {
|
|||||||
removeX(timers, timer_id, update_timers);
|
removeX(timers, timer_id, update_timers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
removeAllTimers(EventLoopData *eld) {
|
||||||
|
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||||
|
if (eld->timers[i].free && eld->timers[i].callback_data) eld->timers[i].free(eld->timers[i].id, eld->timers[i].callback_data);
|
||||||
|
}
|
||||||
|
eld->timers_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
||||||
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||||
@@ -182,7 +197,7 @@ dispatchEvents(EventLoopData *eld) {
|
|||||||
unsigned
|
unsigned
|
||||||
dispatchTimers(EventLoopData *eld) {
|
dispatchTimers(EventLoopData *eld) {
|
||||||
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return 0;
|
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return 0;
|
||||||
static struct { timer_callback_func func; id_type id; void* data; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
|
static struct { timer_callback_func func; id_type id; void* data; bool repeats; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
|
||||||
unsigned num_dispatches = 0;
|
unsigned num_dispatches = 0;
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at <= now; i++) {
|
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at <= now; i++) {
|
||||||
@@ -190,11 +205,15 @@ dispatchTimers(EventLoopData *eld) {
|
|||||||
dispatches[num_dispatches].func = eld->timers[i].callback;
|
dispatches[num_dispatches].func = eld->timers[i].callback;
|
||||||
dispatches[num_dispatches].id = eld->timers[i].id;
|
dispatches[num_dispatches].id = eld->timers[i].id;
|
||||||
dispatches[num_dispatches].data = eld->timers[i].callback_data;
|
dispatches[num_dispatches].data = eld->timers[i].callback_data;
|
||||||
|
dispatches[num_dispatches].repeats = eld->timers[i].repeats;
|
||||||
num_dispatches++;
|
num_dispatches++;
|
||||||
}
|
}
|
||||||
// we dispatch separately so that the callbacks can modify timers
|
// we dispatch separately so that the callbacks can modify timers
|
||||||
for (unsigned i = 0; i < num_dispatches; i++) {
|
for (unsigned i = 0; i < num_dispatches; i++) {
|
||||||
dispatches[i].func(dispatches[i].id, dispatches[i].data);
|
dispatches[i].func(dispatches[i].id, dispatches[i].data);
|
||||||
|
if (!dispatches[i].repeats) {
|
||||||
|
removeTimer(eld, dispatches[i].id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (num_dispatches) update_timers(eld);
|
if (num_dispatches) update_timers(eld);
|
||||||
return num_dispatches;
|
return num_dispatches;
|
||||||
|
|||||||
8
glfw/backend_utils.h
vendored
8
glfw/backend_utils.h
vendored
@@ -27,15 +27,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef unsigned long long id_type;
|
typedef unsigned long long id_type;
|
||||||
typedef void(*watch_callback_func)(int, int, void*);
|
typedef void(*watch_callback_func)(int, int, void*);
|
||||||
typedef void(*timer_callback_func)(id_type, void*);
|
typedef void(*timer_callback_func)(id_type, void*);
|
||||||
|
typedef void (* GLFWuserdatafreefun)(id_type, void*);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd, events, enabled, ready;
|
int fd, events, enabled, ready;
|
||||||
watch_callback_func callback;
|
watch_callback_func callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
|
GLFWuserdatafreefun free;
|
||||||
id_type id;
|
id_type id;
|
||||||
const char *name;
|
const char *name;
|
||||||
} Watch;
|
} Watch;
|
||||||
@@ -45,7 +48,9 @@ typedef struct {
|
|||||||
double interval, trigger_at;
|
double interval, trigger_at;
|
||||||
timer_callback_func callback;
|
timer_callback_func callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
|
GLFWuserdatafreefun free;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
bool repeats;
|
||||||
} Timer;
|
} Timer;
|
||||||
|
|
||||||
|
|
||||||
@@ -61,8 +66,9 @@ typedef struct {
|
|||||||
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
||||||
void removeWatch(EventLoopData *eld, id_type watch_id);
|
void removeWatch(EventLoopData *eld, id_type watch_id);
|
||||||
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
||||||
id_type addTimer(EventLoopData *eld, const char *name, double interval, int enabled, timer_callback_func cb, void *cb_data);
|
id_type addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free);
|
||||||
void removeTimer(EventLoopData *eld, id_type timer_id);
|
void removeTimer(EventLoopData *eld, id_type timer_id);
|
||||||
|
void removeAllTimers(EventLoopData *eld);
|
||||||
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
|
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
|
||||||
void changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval);
|
void changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval);
|
||||||
double prepareForPoll(EventLoopData *eld, double timeout);
|
double prepareForPoll(EventLoopData *eld, double timeout);
|
||||||
|
|||||||
@@ -26,11 +26,6 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
|
||||||
#define NSEventMaskKeyUp NSKeyUpMask
|
|
||||||
#define NSEventMaskKeyDown NSKeyDownMask
|
|
||||||
#define NSEventModifierFlagCommand NSCommandKeyMask
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
@@ -202,7 +197,7 @@ static void createKeyTables(void)
|
|||||||
|
|
||||||
// Retrieve Unicode data for the current keyboard layout
|
// Retrieve Unicode data for the current keyboard layout
|
||||||
//
|
//
|
||||||
static GLFWbool updateUnicodeDataNS(void)
|
static bool updateUnicodeDataNS(void)
|
||||||
{
|
{
|
||||||
if (_glfw.ns.inputSource)
|
if (_glfw.ns.inputSource)
|
||||||
{
|
{
|
||||||
@@ -219,7 +214,7 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Cocoa: Failed to retrieve keyboard layout input source");
|
"Cocoa: Failed to retrieve keyboard layout input source");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.ns.unicodeData =
|
_glfw.ns.unicodeData =
|
||||||
@@ -229,15 +224,15 @@ static GLFWbool updateUnicodeDataNS(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Cocoa: Failed to retrieve keyboard layout Unicode data");
|
"Cocoa: Failed to retrieve keyboard layout Unicode data");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load HIToolbox.framework and the TIS symbols we need from it
|
// Load HIToolbox.framework and the TIS symbols we need from it
|
||||||
//
|
//
|
||||||
static GLFWbool initializeTIS(void)
|
static bool initializeTIS(void)
|
||||||
{
|
{
|
||||||
// This works only because Cocoa has already loaded it properly
|
// This works only because Cocoa has already loaded it properly
|
||||||
_glfw.ns.tis.bundle =
|
_glfw.ns.tis.bundle =
|
||||||
@@ -246,7 +241,7 @@ static GLFWbool initializeTIS(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Cocoa: Failed to load HIToolbox.framework");
|
"Cocoa: Failed to load HIToolbox.framework");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||||
@@ -269,7 +264,7 @@ static GLFWbool initializeTIS(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Cocoa: Failed to load TIS API symbols");
|
"Cocoa: Failed to load TIS API symbols");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
||||||
@@ -294,33 +289,61 @@ static GLFWbool initializeTIS(void)
|
|||||||
|
|
||||||
@end // GLFWHelper
|
@end // GLFWHelper
|
||||||
|
|
||||||
|
@interface GLFWApplication : NSApplication
|
||||||
|
- (void)tick_callback;
|
||||||
|
- (void)render_frame_received:(id)displayIDAsID;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GLFWApplication
|
||||||
|
- (void)tick_callback
|
||||||
|
{
|
||||||
|
_glfwDispatchTickCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)render_frame_received:(id)displayIDAsID
|
||||||
|
{
|
||||||
|
CGDirectDisplayID displayID = [(NSNumber*)displayIDAsID unsignedIntValue];
|
||||||
|
_glfwDispatchRenderFrame(displayID);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
is_ctrl_tab(NSEvent *event) {
|
is_ctrl_tab(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
||||||
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
if (
|
||||||
return event.keyCode == kVK_Tab && (modifierFlags == NSEventModifierFlagControl || modifierFlags == (
|
(modifierFlags == NSEventModifierFlagControl &&
|
||||||
NSEventModifierFlagControl | NSEventModifierFlagShift));
|
[event.charactersIgnoringModifiers isEqualToString:@"\t"]) ||
|
||||||
|
(modifierFlags == (NSEventModifierFlagControl | NSEventModifierFlagShift) &&
|
||||||
|
[event.charactersIgnoringModifiers isEqualToString:@"\x19"])
|
||||||
|
) return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_cmd_period(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
||||||
|
if (modifierFlags != NSEventModifierFlagCommand) return false;
|
||||||
|
if ([event.charactersIgnoringModifiers isEqualToString:@"."]) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
@autoreleasepool {
|
||||||
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
||||||
|
|
||||||
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
||||||
toTarget:_glfw.ns.helper
|
toTarget:_glfw.ns.helper
|
||||||
withObject:nil];
|
withObject:nil];
|
||||||
|
|
||||||
[NSApplication sharedApplication];
|
[GLFWApplication sharedApplication];
|
||||||
|
|
||||||
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
{
|
{
|
||||||
if (is_ctrl_tab(event)) {
|
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||||
|
if (is_ctrl_tab(event, modifierFlags) || is_cmd_period(event, modifierFlags)) {
|
||||||
// Cocoa swallows Ctrl+Tab to cycle between views
|
// Cocoa swallows Ctrl+Tab to cycle between views
|
||||||
[[NSApp keyWindow].contentView keyDown:event];
|
[[NSApp keyWindow].contentView keyDown:event];
|
||||||
}
|
}
|
||||||
@@ -330,13 +353,14 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
NSEvent* (^keyup_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
NSEvent* (^keyup_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
{
|
{
|
||||||
if ([event modifierFlags] & NSEventModifierFlagCommand) {
|
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||||
|
if (modifierFlags & NSEventModifierFlagCommand) {
|
||||||
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
|
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
|
||||||
// This works around an AppKit bug, where key up events while holding
|
// This works around an AppKit bug, where key up events while holding
|
||||||
// down the command key don't get sent to the key window.
|
// down the command key don't get sent to the key window.
|
||||||
[[NSApp keyWindow] sendEvent:event];
|
[[NSApp keyWindow] sendEvent:event];
|
||||||
}
|
}
|
||||||
if (is_ctrl_tab(event)) {
|
if (is_ctrl_tab(event, modifierFlags) || is_cmd_period(event, modifierFlags)) {
|
||||||
// Cocoa swallows Ctrl+Tab to cycle between views
|
// Cocoa swallows Ctrl+Tab to cycle between views
|
||||||
[[NSApp keyWindow].contentView keyUp:event];
|
[[NSApp keyWindow].contentView keyUp:event];
|
||||||
}
|
}
|
||||||
@@ -363,22 +387,32 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||||
if (!_glfw.ns.eventSource)
|
if (!_glfw.ns.eventSource)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
|
CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
|
||||||
|
|
||||||
if (!initializeTIS())
|
if (!initializeTIS())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
|
_glfw.ns.displayLinks.lock = [NSLock new];
|
||||||
_glfwInitTimerNS();
|
_glfwInitTimerNS();
|
||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
_glfwPollMonitorsNS();
|
_glfwPollMonitorsNS();
|
||||||
return GLFW_TRUE;
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
|
@autoreleasepool {
|
||||||
|
|
||||||
|
if (_glfw.ns.displayLinks.lock) {
|
||||||
|
_glfwClearDisplayLinks();
|
||||||
|
[_glfw.ns.displayLinks.lock release];
|
||||||
|
_glfw.ns.displayLinks.lock = nil;
|
||||||
|
}
|
||||||
|
|
||||||
if (_glfw.ns.inputSource)
|
if (_glfw.ns.inputSource)
|
||||||
{
|
{
|
||||||
CFRelease(_glfw.ns.inputSource);
|
CFRelease(_glfw.ns.inputSource);
|
||||||
@@ -419,16 +453,119 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
_glfwTerminateJoysticksNS();
|
_glfwTerminateJoysticksNS();
|
||||||
|
}
|
||||||
[_glfw.ns.autoreleasePool release];
|
|
||||||
_glfw.ns.autoreleasePool = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
#if defined(_GLFW_BUILD_DLL)
|
||||||
" dynamic"
|
" dynamic"
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLFWtickcallback tick_callback = NULL;
|
||||||
|
static void* tick_callback_data = NULL;
|
||||||
|
static bool tick_callback_requested = false;
|
||||||
|
|
||||||
|
|
||||||
|
void _glfwDispatchTickCallback() {
|
||||||
|
if (tick_callback) {
|
||||||
|
tick_callback_requested = false;
|
||||||
|
tick_callback(tick_callback_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRequestTickCallback() {
|
||||||
|
if (!tick_callback_requested) {
|
||||||
|
tick_callback_requested = true;
|
||||||
|
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
|
tick_callback = NULL;
|
||||||
|
[NSApp stop:nil];
|
||||||
|
_glfwPlatformPostEmptyEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
|
||||||
|
tick_callback = callback;
|
||||||
|
tick_callback_data = data;
|
||||||
|
[NSApp run];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NSTimer *os_timer;
|
||||||
|
unsigned long long id;
|
||||||
|
bool repeats;
|
||||||
|
double interval;
|
||||||
|
GLFWuserdatafun callback;
|
||||||
|
void *callback_data;
|
||||||
|
GLFWuserdatafun free_callback_data;
|
||||||
|
} Timer;
|
||||||
|
|
||||||
|
static Timer timers[128] = {{0}};
|
||||||
|
static size_t num_timers = 0;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
remove_timer_at(size_t idx) {
|
||||||
|
if (idx < num_timers) {
|
||||||
|
Timer *t = timers + idx;
|
||||||
|
if (t->os_timer) { [t->os_timer invalidate]; t->os_timer = NULL; }
|
||||||
|
if (t->callback_data && t->free_callback_data) { t->free_callback_data(t->id, t->callback_data); t->callback_data = NULL; }
|
||||||
|
remove_i_from_array(timers, idx, num_timers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void schedule_timer(Timer *t) {
|
||||||
|
t->os_timer = [NSTimer scheduledTimerWithTimeInterval:t->interval repeats:(t->repeats ? YES: NO) block:^(NSTimer *os_timer) {
|
||||||
|
for (size_t i = 0; i < num_timers; i++) {
|
||||||
|
if (timers[i].os_timer == os_timer) {
|
||||||
|
timers[i].callback(timers[i].id, timers[i].callback_data);
|
||||||
|
if (!timers[i].repeats) remove_timer_at(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) {
|
||||||
|
static unsigned long long timer_counter = 0;
|
||||||
|
if (num_timers >= sizeof(timers)/sizeof(timers[0]) - 1) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Timer *t = timers + num_timers++;
|
||||||
|
t->id = ++timer_counter;
|
||||||
|
t->repeats = repeats;
|
||||||
|
t->interval = interval;
|
||||||
|
t->callback = callback;
|
||||||
|
t->callback_data = callback_data;
|
||||||
|
t->free_callback_data = free_callback;
|
||||||
|
schedule_timer(t);
|
||||||
|
return timer_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
|
||||||
|
for (size_t i = 0; i < num_timers; i++) {
|
||||||
|
if (timers[i].id == timer_id) {
|
||||||
|
remove_timer_at(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
||||||
|
for (size_t i = 0; i < num_timers; i++) {
|
||||||
|
if (timers[i].id == timer_id) {
|
||||||
|
Timer *t = timers + i;
|
||||||
|
if (t->os_timer) { [t->os_timer invalidate]; t->os_timer = NULL; }
|
||||||
|
t->interval = interval;
|
||||||
|
if (enabled) schedule_timer(t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -220,9 +220,18 @@ static void matchCallback(void* context,
|
|||||||
case kHIDUsage_GD_Hatswitch:
|
case kHIDUsage_GD_Hatswitch:
|
||||||
target = hats;
|
target = hats;
|
||||||
break;
|
break;
|
||||||
|
case kHIDUsage_GD_DPadUp:
|
||||||
|
case kHIDUsage_GD_DPadRight:
|
||||||
|
case kHIDUsage_GD_DPadDown:
|
||||||
|
case kHIDUsage_GD_DPadLeft:
|
||||||
|
case kHIDUsage_GD_SystemMainMenu:
|
||||||
|
case kHIDUsage_GD_Select:
|
||||||
|
case kHIDUsage_GD_Start:
|
||||||
|
target = buttons;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (page == kHIDPage_Button)
|
else if (page == kHIDPage_Button || page == kHIDPage_Consumer)
|
||||||
target = buttons;
|
target = buttons;
|
||||||
|
|
||||||
if (target)
|
if (target)
|
||||||
@@ -397,12 +406,12 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|||||||
if (raw > axis->maximum)
|
if (raw > axis->maximum)
|
||||||
axis->maximum = raw;
|
axis->maximum = raw;
|
||||||
|
|
||||||
const long delta = axis->maximum - axis->minimum;
|
const long size = axis->maximum - axis->minimum;
|
||||||
if (delta == 0)
|
if (size == 0)
|
||||||
_glfwInputJoystickAxis(js, (int) i, 0.f);
|
_glfwInputJoystickAxis(js, (int) i, 0.f);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const float value = (2.f * (raw - axis->minimum) / delta) - 1.f;
|
const float value = (2.f * (raw - axis->minimum) / size) - 1.f;
|
||||||
_glfwInputJoystickAxis(js, (int) i, value);
|
_glfwInputJoystickAxis(js, (int) i, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -417,7 +426,8 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|||||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||||
const char value = getElementValue(js, button) - button->minimum;
|
const char value = getElementValue(js, button) - button->minimum;
|
||||||
_glfwInputJoystickButton(js, (int) i, value);
|
const int state = (value > 0) ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
_glfwInputJoystickButton(js, (int) i, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
for (i = 0; i < CFArrayGetCount(js->ns.hats); i++)
|
||||||
@@ -454,9 +464,8 @@ void _glfwPlatformUpdateGamepadGUID(char* guid)
|
|||||||
(strncmp(guid + 20, "000000000000", 12) == 0))
|
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||||
{
|
{
|
||||||
char original[33];
|
char original[33];
|
||||||
strcpy(original, guid);
|
strncpy(original, guid, sizeof(original) - 1);
|
||||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||||
original, original + 16);
|
original, original + 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||||
#include <CoreVideo/CVBase.h>
|
#include <CoreVideo/CVBase.h>
|
||||||
@@ -115,16 +116,16 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
|||||||
|
|
||||||
// Check whether the display mode should be included in enumeration
|
// Check whether the display mode should be included in enumeration
|
||||||
//
|
//
|
||||||
static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
static bool modeIsGood(CGDisplayModeRef mode)
|
||||||
{
|
{
|
||||||
uint32_t flags = CGDisplayModeGetIOFlags(mode);
|
uint32_t flags = CGDisplayModeGetIOFlags(mode);
|
||||||
|
|
||||||
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
|
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (flags & kDisplayModeInterlacedFlag)
|
if (flags & kDisplayModeInterlacedFlag)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (flags & kDisplayModeStretchedFlag)
|
if (flags & kDisplayModeStretchedFlag)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
@@ -132,12 +133,12 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
|||||||
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||||
{
|
{
|
||||||
CFRelease(format);
|
CFRelease(format);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(format);
|
CFRelease(format);
|
||||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert Core Graphics display mode to GLFW video mode
|
// Convert Core Graphics display mode to GLFW video mode
|
||||||
@@ -148,7 +149,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
|||||||
GLFWvidmode result;
|
GLFWvidmode result;
|
||||||
result.width = (int) CGDisplayModeGetWidth(mode);
|
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||||
result.height = (int) CGDisplayModeGetHeight(mode);
|
result.height = (int) CGDisplayModeGetHeight(mode);
|
||||||
result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode);
|
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
||||||
|
|
||||||
if (result.refreshRate == 0)
|
if (result.refreshRate == 0)
|
||||||
{
|
{
|
||||||
@@ -212,11 +213,91 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finds and caches the NSScreen corresponding to the specified monitor
|
||||||
|
//
|
||||||
|
bool refreshMonitorScreen(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
if (monitor->ns.screen)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (NSScreen* screen in [NSScreen screens])
|
||||||
|
{
|
||||||
|
NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"];
|
||||||
|
|
||||||
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
|
// display replacement on machines with automatic graphics
|
||||||
|
// switching
|
||||||
|
if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue]))
|
||||||
|
{
|
||||||
|
monitor->ns.screen = screen;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void _glfwClearDisplayLinks() {
|
||||||
|
[_glfw.ns.displayLinks.lock lock];
|
||||||
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].displayLinkStarted) {
|
||||||
|
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
|
_glfw.ns.displayLinks.entries[i].displayLinkStarted = false;
|
||||||
|
}
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].displayLink) {
|
||||||
|
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
|
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_glfw.ns.displayLinks.count = 0;
|
||||||
|
[_glfw.ns.displayLinks.lock unlock];
|
||||||
|
}
|
||||||
|
|
||||||
|
static CVReturn displayLinkCallback(
|
||||||
|
CVDisplayLinkRef displayLink,
|
||||||
|
const CVTimeStamp* now, const CVTimeStamp* outputTime,
|
||||||
|
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* userInfo)
|
||||||
|
{
|
||||||
|
CGDirectDisplayID displayID = (CGDirectDisplayID)userInfo;
|
||||||
|
[_glfw.ns.displayLinks.lock lock];
|
||||||
|
bool notify = false;
|
||||||
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) {
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].renderFrameRequested) {
|
||||||
|
notify = true;
|
||||||
|
_glfw.ns.displayLinks.entries[i].renderFrameRequested = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[_glfw.ns.displayLinks.lock unlock];
|
||||||
|
if (notify) {
|
||||||
|
NSNumber *arg = [NSNumber numberWithUnsignedInt:displayID];
|
||||||
|
[NSApp performSelectorOnMainThread:@selector(render_frame_received:) withObject:arg waitUntilDone:NO];
|
||||||
|
[arg release];
|
||||||
|
}
|
||||||
|
return kCVReturnSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void createDisplayLink(CGDirectDisplayID displayID) {
|
||||||
|
[_glfw.ns.displayLinks.lock lock];
|
||||||
|
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
|
||||||
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
|
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
||||||
|
}
|
||||||
|
_GLFWDisplayLinkNS *entry = &_glfw.ns.displayLinks.entries[_glfw.ns.displayLinks.count++];
|
||||||
|
memset(entry, 0, sizeof(_GLFWDisplayLinkNS));
|
||||||
|
entry->displayID = displayID;
|
||||||
|
CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink);
|
||||||
|
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID);
|
||||||
|
[_glfw.ns.displayLinks.lock unlock];
|
||||||
|
}
|
||||||
|
|
||||||
// Poll for changes in the set of connected monitors
|
// Poll for changes in the set of connected monitors
|
||||||
//
|
//
|
||||||
void _glfwPollMonitorsNS(void)
|
void _glfwPollMonitorsNS(void)
|
||||||
@@ -228,6 +309,7 @@ void _glfwPollMonitorsNS(void)
|
|||||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
|
_glfwClearDisplayLinks();
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
_glfw.monitors[i]->ns.screen = nil;
|
_glfw.monitors[i]->ns.screen = nil;
|
||||||
@@ -269,6 +351,7 @@ void _glfwPollMonitorsNS(void)
|
|||||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||||
monitor->ns.displayID = displays[i];
|
monitor->ns.displayID = displays[i];
|
||||||
monitor->ns.unitNumber = unitNumber;
|
monitor->ns.unitNumber = unitNumber;
|
||||||
|
createDisplayLink(monitor->ns.displayID);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
|
|
||||||
@@ -283,6 +366,7 @@ void _glfwPollMonitorsNS(void)
|
|||||||
|
|
||||||
free(disconnected);
|
free(disconnected);
|
||||||
free(displays);
|
free(displays);
|
||||||
|
_glfwRestartDisplayLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the current video mode
|
// Change the current video mode
|
||||||
@@ -372,35 +456,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
float* xscale, float* yscale)
|
float* xscale, float* yscale)
|
||||||
{
|
{
|
||||||
if (!monitor->ns.screen)
|
if (!refreshMonitorScreen(monitor))
|
||||||
{
|
return;
|
||||||
NSUInteger i;
|
|
||||||
NSArray* screens = [NSScreen screens];
|
|
||||||
|
|
||||||
for (i = 0; i < [screens count]; i++)
|
|
||||||
{
|
|
||||||
NSScreen* screen = [screens objectAtIndex:i];
|
|
||||||
NSNumber* displayID =
|
|
||||||
[[screen deviceDescription] objectForKey:@"NSScreenNumber"];
|
|
||||||
|
|
||||||
// HACK: Compare unit numbers instead of display IDs to work around
|
|
||||||
// display replacement on machines with automatic graphics
|
|
||||||
// switching
|
|
||||||
if (monitor->ns.unitNumber ==
|
|
||||||
CGDisplayUnitNumber([displayID unsignedIntValue]))
|
|
||||||
{
|
|
||||||
monitor->ns.screen = screen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == [screens count])
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Cocoa: Failed to find a screen for monitor");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const NSRect points = [monitor->ns.screen frame];
|
const NSRect points = [monitor->ns.screen frame];
|
||||||
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
||||||
@@ -411,6 +468,24 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = (float) (pixels.size.height / points.size.height);
|
*yscale = (float) (pixels.size.height / points.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||||
|
{
|
||||||
|
if (!refreshMonitorScreen(monitor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const NSRect frameRect = [monitor->ns.screen visibleFrame];
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = frameRect.origin.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
|
||||||
|
if (width)
|
||||||
|
*width = frameRect.size.width;
|
||||||
|
if (height)
|
||||||
|
*height = frameRect.size.height;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
CFArrayRef modes;
|
||||||
@@ -467,7 +542,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
|||||||
CVDisplayLinkRelease(link);
|
CVDisplayLinkRelease(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
||||||
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
||||||
@@ -489,7 +564,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(values);
|
free(values);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
|||||||
60
glfw/cocoa_platform.h
vendored
60
glfw/cocoa_platform.h
vendored
@@ -30,14 +30,43 @@
|
|||||||
#include <Carbon/Carbon.h>
|
#include <Carbon/Carbon.h>
|
||||||
#if defined(__OBJC__)
|
#if defined(__OBJC__)
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <CoreVideo/CoreVideo.h>
|
||||||
#else
|
#else
|
||||||
typedef void* id;
|
typedef void* id;
|
||||||
|
typedef void* CVDisplayLinkRef;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
|
#define NSEventMaskKeyUp NSKeyUpMask
|
||||||
|
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
|
||||||
|
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||||
|
#define NSEventModifierFlagControl NSControlKeyMask
|
||||||
|
#define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
|
||||||
|
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||||
|
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||||
|
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||||
|
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
|
||||||
|
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
||||||
|
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
||||||
|
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||||
|
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 101400)
|
||||||
|
#define NSPasteboardTypeFileURL NSFilenamesPboardType
|
||||||
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
|
#define NSPasteboardTypeString NSStringPboardType
|
||||||
|
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,int);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
||||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
|
|
||||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||||
{
|
{
|
||||||
@@ -87,7 +116,8 @@ typedef struct _GLFWwindowNS
|
|||||||
id view;
|
id view;
|
||||||
id layer;
|
id layer;
|
||||||
|
|
||||||
GLFWbool maximized;
|
bool maximized;
|
||||||
|
bool retina;
|
||||||
|
|
||||||
// Cached window properties to filter out duplicate events
|
// Cached window properties to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -105,16 +135,26 @@ typedef struct _GLFWwindowNS
|
|||||||
GLFWcocoatogglefullscreenfun toggleFullscreenCallback;
|
GLFWcocoatogglefullscreenfun toggleFullscreenCallback;
|
||||||
// Dead key state
|
// Dead key state
|
||||||
UInt32 deadKeyState;
|
UInt32 deadKeyState;
|
||||||
|
// Whether a render frame has been requested for this window
|
||||||
|
bool renderFrameRequested;
|
||||||
|
GLFWcocoarenderframefun renderFrameCallback;
|
||||||
} _GLFWwindowNS;
|
} _GLFWwindowNS;
|
||||||
|
|
||||||
|
typedef struct _GLFWDisplayLinkNS
|
||||||
|
{
|
||||||
|
CVDisplayLinkRef displayLink;
|
||||||
|
CGDirectDisplayID displayID;
|
||||||
|
bool displayLinkStarted;
|
||||||
|
bool renderFrameRequested;
|
||||||
|
} _GLFWDisplayLinkNS;
|
||||||
|
|
||||||
// Cocoa-specific global data
|
// Cocoa-specific global data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWlibraryNS
|
typedef struct _GLFWlibraryNS
|
||||||
{
|
{
|
||||||
CGEventSourceRef eventSource;
|
CGEventSourceRef eventSource;
|
||||||
id delegate;
|
id delegate;
|
||||||
id autoreleasePool;
|
bool cursorHidden;
|
||||||
GLFWbool cursorHidden;
|
|
||||||
TISInputSourceRef inputSource;
|
TISInputSourceRef inputSource;
|
||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
id unicodeData;
|
id unicodeData;
|
||||||
@@ -141,6 +181,12 @@ typedef struct _GLFWlibraryNS
|
|||||||
CFStringRef kPropertyUnicodeKeyLayoutData;
|
CFStringRef kPropertyUnicodeKeyLayoutData;
|
||||||
} tis;
|
} tis;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
_GLFWDisplayLinkNS entries[256];
|
||||||
|
size_t count;
|
||||||
|
id lock;
|
||||||
|
} displayLinks;
|
||||||
|
|
||||||
} _GLFWlibraryNS;
|
} _GLFWlibraryNS;
|
||||||
|
|
||||||
// Cocoa-specific per-monitor data
|
// Cocoa-specific per-monitor data
|
||||||
@@ -176,3 +222,9 @@ void _glfwInitTimerNS(void);
|
|||||||
void _glfwPollMonitorsNS(void);
|
void _glfwPollMonitorsNS(void);
|
||||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||||
|
float _glfwTransformYNS(float y);
|
||||||
|
void _glfwClearDisplayLinks(void);
|
||||||
|
void _glfwRestartDisplayLinks(void);
|
||||||
|
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
|
||||||
|
void _glfwDispatchTickCallback(void);
|
||||||
|
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
69
glfw/context.c
vendored
69
glfw/context.c
vendored
@@ -44,7 +44,7 @@
|
|||||||
// exists and whether all relevant options have supported and non-conflicting
|
// exists and whether all relevant options have supported and non-conflicting
|
||||||
// values
|
// values
|
||||||
//
|
//
|
||||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||||
{
|
{
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
{
|
{
|
||||||
@@ -52,7 +52,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
ctxconfig->share->context.client == GLFW_NO_API)
|
ctxconfig->share->context.client == GLFW_NO_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context creation API 0x%08X",
|
"Invalid context creation API 0x%08X",
|
||||||
ctxconfig->source);
|
ctxconfig->source);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API &&
|
if (ctxconfig->client != GLFW_NO_API &&
|
||||||
@@ -73,7 +73,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid client API 0x%08X",
|
"Invalid client API 0x%08X",
|
||||||
ctxconfig->client);
|
ctxconfig->client);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
@@ -92,7 +92,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
"Invalid OpenGL version %i.%i",
|
"Invalid OpenGL version %i.%i",
|
||||||
ctxconfig->major, ctxconfig->minor);
|
ctxconfig->major, ctxconfig->minor);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
if (ctxconfig->profile)
|
||||||
@@ -103,7 +103,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid OpenGL profile 0x%08X",
|
"Invalid OpenGL profile 0x%08X",
|
||||||
ctxconfig->profile);
|
ctxconfig->profile);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->major <= 2 ||
|
if (ctxconfig->major <= 2 ||
|
||||||
@@ -114,7 +114,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
"Context profiles are only defined for OpenGL version 3.2 and above");
|
"Context profiles are only defined for OpenGL version 3.2 and above");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
"Forward-compatibility is only defined for OpenGL version 3.0 and above");
|
"Forward-compatibility is only defined for OpenGL version 3.0 and above");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
else if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
@@ -140,7 +140,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
_glfwInputError(GLFW_INVALID_VALUE,
|
||||||
"Invalid OpenGL ES version %i.%i",
|
"Invalid OpenGL ES version %i.%i",
|
||||||
ctxconfig->major, ctxconfig->minor);
|
ctxconfig->major, ctxconfig->minor);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context robustness mode 0x%08X",
|
"Invalid context robustness mode 0x%08X",
|
||||||
ctxconfig->robustness);
|
ctxconfig->robustness);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,11 +164,11 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
|||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
"Invalid context release behavior 0x%08X",
|
"Invalid context release behavior 0x%08X",
|
||||||
ctxconfig->release);
|
ctxconfig->release);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chooses the framebuffer config that best matches the desired one
|
// Chooses the framebuffer config that best matches the desired one
|
||||||
@@ -341,7 +341,7 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
|||||||
|
|
||||||
// Retrieves the attributes of the current context
|
// Retrieves the attributes of the current context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig)
|
const _GLFWctxconfig* ctxconfig)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -358,7 +358,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
window->context.source = ctxconfig->source;
|
window->context.source = ctxconfig->source;
|
||||||
window->context.client = GLFW_OPENGL_API;
|
window->context.client = GLFW_OPENGL_API;
|
||||||
|
|
||||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
|
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
glfwMakeContextCurrent((GLFWwindow*) window);
|
glfwMakeContextCurrent((GLFWwindow*) window);
|
||||||
|
|
||||||
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
||||||
@@ -369,7 +369,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
version = (const char*) window->context.GetString(GL_VERSION);
|
version = (const char*) window->context.GetString(GL_VERSION);
|
||||||
@@ -387,7 +387,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; prefixes[i]; i++)
|
for (i = 0; prefixes[i]; i++)
|
||||||
@@ -419,7 +419,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->context.major < ctxconfig->major ||
|
if (window->context.major < ctxconfig->major ||
|
||||||
@@ -449,7 +449,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->context.major >= 3)
|
if (window->context.major >= 3)
|
||||||
@@ -465,7 +465,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Entry point retrieval is broken");
|
"Entry point retrieval is broken");
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,21 +478,21 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||||
window->context.forward = GLFW_TRUE;
|
window->context.forward = true;
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
|
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
|
||||||
window->context.debug = GLFW_TRUE;
|
window->context.debug = true;
|
||||||
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
|
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
|
||||||
ctxconfig->debug)
|
ctxconfig->debug)
|
||||||
{
|
{
|
||||||
// HACK: This is a workaround for older drivers (pre KHR_debug)
|
// HACK: This is a workaround for older drivers (pre KHR_debug)
|
||||||
// not setting the debug bit in the context flags for
|
// not setting the debug bit in the context flags for
|
||||||
// debug contexts
|
// debug contexts
|
||||||
window->context.debug = GLFW_TRUE;
|
window->context.debug = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
|
if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
|
||||||
window->context.noerror = GLFW_TRUE;
|
window->context.noerror = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
// Read back OpenGL context profile (OpenGL 3.2 and above)
|
||||||
@@ -572,12 +572,12 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Searches an extension string for the specified extension
|
// Searches an extension string for the specified extension
|
||||||
//
|
//
|
||||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
|
bool _glfwStringInExtensionString(const char* string, const char* extensions)
|
||||||
{
|
{
|
||||||
const char* start = extensions;
|
const char* start = extensions;
|
||||||
|
|
||||||
@@ -588,7 +588,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
|||||||
|
|
||||||
where = strstr(start, string);
|
where = strstr(start, string);
|
||||||
if (!where)
|
if (!where)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
terminator = where + strlen(string);
|
terminator = where + strlen(string);
|
||||||
if (where == start || *(where - 1) == ' ')
|
if (where == start || *(where - 1) == ' ')
|
||||||
@@ -600,7 +600,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
|||||||
start = terminator;
|
start = terminator;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -677,20 +677,20 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
assert(extension != NULL);
|
assert(extension != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||||
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*extension == '\0')
|
if (*extension == '\0')
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->context.major >= 3)
|
if (window->context.major >= 3)
|
||||||
@@ -710,11 +710,11 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Extension string retrieval is broken");
|
"Extension string retrieval is broken");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(en, extension) == 0)
|
if (strcmp(en, extension) == 0)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -727,11 +727,11 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Extension string retrieval is broken");
|
"Extension string retrieval is broken");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if extension is in the platform-specific string
|
// Check if extension is in the platform-specific string
|
||||||
@@ -755,4 +755,3 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
|
|||||||
|
|
||||||
return window->context.getProcAddress(procname);
|
return window->context.getProcAddress(procname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
120
glfw/dbus_glfw.c
vendored
120
glfw/dbus_glfw.c
vendored
@@ -43,12 +43,13 @@ report_error(DBusError *err, const char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _GLFWDBUSData *dbus_data = NULL;
|
static _GLFWDBUSData *dbus_data = NULL;
|
||||||
|
static DBusConnection *session_bus = NULL;
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) {
|
glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) {
|
||||||
dbus->eld = eld;
|
dbus->eld = eld;
|
||||||
dbus_data = dbus;
|
dbus_data = dbus;
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -108,7 +109,7 @@ add_dbus_timeout(DBusTimeout *timeout, void *data) {
|
|||||||
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
|
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
|
||||||
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
|
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
|
||||||
if (interval < 0) return FALSE;
|
if (interval < 0) return FALSE;
|
||||||
id_type timer_id = addTimer(dbus_data->eld, data, interval, enabled, on_dbus_timer_ready, timeout);
|
id_type timer_id = addTimer(dbus_data->eld, data, interval, enabled, true, on_dbus_timer_ready, timeout, NULL);
|
||||||
if (!timer_id) return FALSE;
|
if (!timer_id) return FALSE;
|
||||||
id_type *idp = malloc(sizeof(id_type));
|
id_type *idp = malloc(sizeof(id_type));
|
||||||
if (!idp) {
|
if (!idp) {
|
||||||
@@ -135,7 +136,7 @@ toggle_dbus_timeout(DBusTimeout *timeout, void *data) {
|
|||||||
|
|
||||||
|
|
||||||
DBusConnection*
|
DBusConnection*
|
||||||
glfw_dbus_connect_to(const char *path, const char* err_msg, const char *name, GLFWbool register_on_bus) {
|
glfw_dbus_connect_to(const char *path, const char* err_msg, const char *name, bool register_on_bus) {
|
||||||
DBusError err;
|
DBusError err;
|
||||||
dbus_error_init(&err);
|
dbus_error_init(&err);
|
||||||
DBusConnection *ans = dbus_connection_open_private(path, &err);
|
DBusConnection *ans = dbus_connection_open_private(path, &err);
|
||||||
@@ -171,12 +172,21 @@ glfw_dbus_dispatch(DBusConnection *conn) {
|
|||||||
while(dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS);
|
while(dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glfw_dbus_session_bus_dispatch() {
|
||||||
|
if (session_bus) glfw_dbus_dispatch(session_bus);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_dbus_terminate(_GLFWDBUSData *dbus) {
|
glfw_dbus_terminate(_GLFWDBUSData *dbus) {
|
||||||
if (dbus_data) {
|
if (dbus_data) {
|
||||||
dbus_data->eld = NULL;
|
dbus_data->eld = NULL;
|
||||||
dbus_data = NULL;
|
dbus_data = NULL;
|
||||||
}
|
}
|
||||||
|
if (session_bus) {
|
||||||
|
dbus_connection_unref(session_bus);
|
||||||
|
session_bus = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -185,14 +195,14 @@ glfw_dbus_close_connection(DBusConnection *conn) {
|
|||||||
dbus_connection_unref(conn);
|
dbus_connection_unref(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...) {
|
glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...) {
|
||||||
DBusError err;
|
DBusError err;
|
||||||
dbus_error_init(&err);
|
dbus_error_init(&err);
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, failmsg);
|
va_start(ap, failmsg);
|
||||||
int firstarg = va_arg(ap, int);
|
int firstarg = va_arg(ap, int);
|
||||||
GLFWbool ret = dbus_message_get_args_valist(msg, &err, firstarg, ap) ? GLFW_TRUE : GLFW_FALSE;
|
bool ret = dbus_message_get_args_valist(msg, &err, firstarg, ap) ? true : false;
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (!ret) report_error(&err, failmsg);
|
if (!ret) report_error(&err, failmsg);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -223,34 +233,43 @@ method_reply_received(DBusPendingCall *pending, void *user_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool
|
bool
|
||||||
|
call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data) {
|
||||||
|
bool retval = false;
|
||||||
|
#define REPORT(errs) _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: node=%s path=%s interface=%s method=%s, with error: %s", dbus_message_get_destination(msg), dbus_message_get_path(msg), dbus_message_get_interface(msg), dbus_message_get_member(msg), errs)
|
||||||
|
if (callback) {
|
||||||
|
DBusPendingCall *pending = NULL;
|
||||||
|
if (dbus_connection_send_with_reply(conn, msg, &pending, timeout)) {
|
||||||
|
MethodResponse *res = malloc(sizeof(MethodResponse));
|
||||||
|
if (!res) return false;
|
||||||
|
res->callback = callback;
|
||||||
|
res->user_data = user_data;
|
||||||
|
dbus_pending_call_set_notify(pending, method_reply_received, res, free);
|
||||||
|
retval = true;
|
||||||
|
} else {
|
||||||
|
REPORT("out of memory");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dbus_connection_send(conn, msg, NULL)) {
|
||||||
|
retval = true;
|
||||||
|
} else {
|
||||||
|
REPORT("out of memory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
#undef REPORT
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, va_list ap) {
|
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void *user_data, va_list ap) {
|
||||||
if (!conn) return GLFW_FALSE;
|
if (!conn) return false;
|
||||||
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
||||||
if (!msg) return GLFW_FALSE;
|
if (!msg) return false;
|
||||||
GLFWbool retval = GLFW_FALSE;
|
bool retval = false;
|
||||||
MethodResponse *res = malloc(sizeof(MethodResponse));
|
|
||||||
if (!res) { dbus_message_unref(msg); return GLFW_FALSE; }
|
|
||||||
res->callback = callback;
|
|
||||||
res->user_data = user_data;
|
|
||||||
|
|
||||||
int firstarg = va_arg(ap, int);
|
int firstarg = va_arg(ap, int);
|
||||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
|
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
|
||||||
if (callback) {
|
retval = call_method_with_msg(conn, msg, timeout, callback, user_data);
|
||||||
DBusPendingCall *pending = NULL;
|
|
||||||
if (dbus_connection_send_with_reply(conn, msg, &pending, timeout)) {
|
|
||||||
dbus_pending_call_set_notify(pending, method_reply_received, res, free);
|
|
||||||
retval = GLFW_TRUE;
|
|
||||||
} else {
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s out of memory", method, node, interface);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (dbus_connection_send(conn, msg, NULL)) {
|
|
||||||
retval = GLFW_TRUE;
|
|
||||||
} else {
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s out of memory", method, node, interface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s could not add arguments", method, node, interface);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s could not add arguments", method, node, interface);
|
||||||
}
|
}
|
||||||
@@ -259,9 +278,9 @@ call_method(DBusConnection *conn, const char *node, const char *path, const char
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void* user_data, ...) {
|
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout, dbus_pending_callback callback, void* user_data, ...) {
|
||||||
GLFWbool retval;
|
bool retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, user_data);
|
va_start(ap, user_data);
|
||||||
retval = call_method(conn, node, path, interface, method, timeout, callback, user_data, ap);
|
retval = call_method(conn, node, path, interface, method, timeout, callback, user_data, ap);
|
||||||
@@ -269,9 +288,9 @@ glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const c
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) {
|
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) {
|
||||||
GLFWbool retval;
|
bool retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, method);
|
va_start(ap, method);
|
||||||
retval = call_method(conn, node, path, interface, method, DBUS_TIMEOUT_USE_DEFAULT, NULL, NULL, ap);
|
retval = call_method(conn, node, path, interface, method, DBUS_TIMEOUT_USE_DEFAULT, NULL, NULL, ap);
|
||||||
@@ -293,3 +312,38 @@ glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...) {
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
glfw_dbus_connect_to_session_bus(void) {
|
||||||
|
DBusError error;
|
||||||
|
dbus_error_init(&error);
|
||||||
|
if (session_bus) {
|
||||||
|
dbus_connection_unref(session_bus);
|
||||||
|
}
|
||||||
|
session_bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||||
|
if (dbus_error_is_set(&error)) {
|
||||||
|
report_error(&error, "Failed to connect to DBUS session bus");
|
||||||
|
session_bus = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static const char *name = "session-bus";
|
||||||
|
if (!dbus_connection_set_watch_functions(session_bus, add_dbus_watch, remove_dbus_watch, toggle_dbus_watch, (void*)name, NULL)) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set DBUS watches on connection to: %s", name);
|
||||||
|
dbus_connection_close(session_bus);
|
||||||
|
dbus_connection_unref(session_bus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dbus_connection_set_timeout_functions(session_bus, add_dbus_timeout, remove_dbus_timeout, toggle_dbus_timeout, (void*)name, NULL)) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set DBUS timeout functions on connection to: %s", name);
|
||||||
|
dbus_connection_close(session_bus);
|
||||||
|
dbus_connection_unref(session_bus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DBusConnection *
|
||||||
|
glfw_dbus_session_bus() {
|
||||||
|
if (!session_bus) glfw_dbus_connect_to_session_bus();
|
||||||
|
return session_bus;
|
||||||
|
}
|
||||||
|
|||||||
14
glfw/dbus_glfw.h
vendored
14
glfw/dbus_glfw.h
vendored
@@ -37,14 +37,18 @@ typedef struct {
|
|||||||
} _GLFWDBUSData;
|
} _GLFWDBUSData;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld);
|
bool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld);
|
||||||
void glfw_dbus_terminate(_GLFWDBUSData *dbus);
|
void glfw_dbus_terminate(_GLFWDBUSData *dbus);
|
||||||
DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg, const char* name, GLFWbool register_on_bus);
|
DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg, const char* name, bool register_on_bus);
|
||||||
void glfw_dbus_close_connection(DBusConnection *conn);
|
void glfw_dbus_close_connection(DBusConnection *conn);
|
||||||
GLFWbool
|
bool
|
||||||
|
call_method_with_msg(DBusConnection *conn, DBusMessage *msg, int timeout, dbus_pending_callback callback, void *user_data);
|
||||||
|
bool
|
||||||
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
||||||
GLFWbool
|
bool
|
||||||
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout_ms, dbus_pending_callback callback, void *user_data, ...);
|
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, int timeout_ms, dbus_pending_callback callback, void *user_data, ...);
|
||||||
void glfw_dbus_dispatch(DBusConnection *);
|
void glfw_dbus_dispatch(DBusConnection *);
|
||||||
GLFWbool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...);
|
void glfw_dbus_session_bus_dispatch(void);
|
||||||
|
bool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...);
|
||||||
int glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...);
|
int glfw_dbus_match_signal(DBusMessage *msg, const char *interface, ...);
|
||||||
|
DBusConnection* glfw_dbus_session_bus(void);
|
||||||
|
|||||||
62
glfw/egl_context.c
vendored
62
glfw/egl_context.c
vendored
@@ -85,7 +85,7 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib)
|
|||||||
|
|
||||||
// Return the EGLConfig most closely matching the specified hints
|
// Return the EGLConfig most closely matching the specified hints
|
||||||
//
|
//
|
||||||
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* desired,
|
const _GLFWfbconfig* desired,
|
||||||
EGLConfig* result)
|
EGLConfig* result)
|
||||||
{
|
{
|
||||||
@@ -98,7 +98,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
if (!nativeCount)
|
if (!nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
||||||
@@ -170,7 +170,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||||
|
|
||||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
||||||
u->doublebuffer = GLFW_TRUE;
|
u->doublebuffer = true;
|
||||||
|
|
||||||
u->handle = (uintptr_t) n;
|
u->handle = (uintptr_t) n;
|
||||||
usableCount++;
|
usableCount++;
|
||||||
@@ -241,10 +241,10 @@ static int extensionSupportedEGL(const char* extension)
|
|||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||||
@@ -297,7 +297,7 @@ static void destroyContextEGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Initialize EGL
|
// Initialize EGL
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitEGL(void)
|
bool _glfwInitEGL(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
@@ -318,7 +318,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (_glfw.egl.handle)
|
if (_glfw.egl.handle)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
for (i = 0; sonames[i]; i++)
|
||||||
{
|
{
|
||||||
@@ -330,7 +330,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
if (!_glfw.egl.handle)
|
if (!_glfw.egl.handle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||||
@@ -389,7 +389,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
"EGL: Failed to load required entry points");
|
"EGL: Failed to load required entry points");
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||||
@@ -400,7 +400,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
||||||
@@ -410,7 +410,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
|
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.egl.KHR_create_context =
|
_glfw.egl.KHR_create_context =
|
||||||
@@ -424,7 +424,7 @@ GLFWbool _glfwInitEGL(void)
|
|||||||
_glfw.egl.KHR_context_flush_control =
|
_glfw.egl.KHR_context_flush_control =
|
||||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate EGL
|
// Terminate EGL
|
||||||
@@ -453,7 +453,7 @@ void _glfwTerminateEGL(void)
|
|||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
bool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
@@ -465,7 +465,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
if (!_glfw.egl.display)
|
if (!_glfw.egl.display)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
@@ -475,7 +475,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
@@ -485,7 +485,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to bind OpenGL ES: %s",
|
"EGL: Failed to bind OpenGL ES: %s",
|
||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -495,7 +495,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to bind OpenGL: %s",
|
"EGL: Failed to bind OpenGL: %s",
|
||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
if (ctxconfig->noerror)
|
if (ctxconfig->noerror)
|
||||||
{
|
{
|
||||||
if (_glfw.egl.KHR_create_context_no_error)
|
if (_glfw.egl.KHR_create_context_no_error)
|
||||||
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
|
setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
||||||
@@ -581,7 +581,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"EGL: Failed to create context: %s",
|
"EGL: Failed to create context: %s",
|
||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up attributes for surface creation
|
// Set up attributes for surface creation
|
||||||
@@ -607,11 +607,20 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"EGL: Failed to create window surface: %s",
|
"EGL: Failed to create window surface: %s",
|
||||||
getEGLErrorString(eglGetError()));
|
getEGLErrorString(eglGetError()));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.egl.config = config;
|
window->context.egl.config = config;
|
||||||
|
|
||||||
|
EGLint a = EGL_MIN_SWAP_INTERVAL;
|
||||||
|
if (!eglGetConfigAttrib(_glfw.egl.display, config, a, &a)) {
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: could not check for non-blocking buffer swap with error: %s", getEGLErrorString(eglGetError()));
|
||||||
|
} else {
|
||||||
|
if (a > 0) {
|
||||||
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: non-blocking swap buffers not available, minimum swap interval is: %d", a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load the appropriate client library
|
// Load the appropriate client library
|
||||||
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
||||||
{
|
{
|
||||||
@@ -686,7 +695,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"EGL: Failed to load client library");
|
"EGL: Failed to load client library");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,7 +706,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressEGL;
|
window->context.getProcAddress = getProcAddressEGL;
|
||||||
window->context.destroy = destroyContextEGL;
|
window->context.destroy = destroyContextEGL;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setAttrib
|
#undef setAttrib
|
||||||
@@ -705,7 +714,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
// Returns the Visual and depth of the chosen EGLConfig
|
// Returns the Visual and depth of the chosen EGLConfig
|
||||||
//
|
//
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
@@ -720,7 +729,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"EGL: Failed to find a suitable EGLConfig");
|
"EGL: Failed to find a suitable EGLConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
eglGetConfigAttrib(_glfw.egl.display, native,
|
eglGetConfigAttrib(_glfw.egl.display, native,
|
||||||
@@ -734,14 +743,14 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"EGL: Failed to retrieve Visual for EGLConfig");
|
"EGL: Failed to retrieve Visual for EGLConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*visual = result->visual;
|
*visual = result->visual;
|
||||||
*depth = result->depth;
|
*depth = result->depth;
|
||||||
|
|
||||||
XFree(result);
|
XFree(result);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
|
|
||||||
@@ -783,4 +792,3 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
|
|||||||
|
|
||||||
return window->context.egl.surface;
|
return window->context.egl.surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
glfw/egl_context.h
vendored
36
glfw/egl_context.h
vendored
@@ -47,26 +47,26 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
|||||||
#error "No supported EGL platform selected"
|
#error "No supported EGL platform selected"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define EGL_SUCCESS 0x3000
|
#define EGL_SUCCESS 0x3000
|
||||||
#define EGL_NOT_INITIALIZED 0x3001
|
#define EGL_NOT_INITIALIZED 0x3001
|
||||||
#define EGL_BAD_ACCESS 0x3002
|
#define EGL_BAD_ACCESS 0x3002
|
||||||
#define EGL_BAD_ALLOC 0x3003
|
#define EGL_BAD_ALLOC 0x3003
|
||||||
#define EGL_BAD_ATTRIBUTE 0x3004
|
#define EGL_BAD_ATTRIBUTE 0x3004
|
||||||
#define EGL_BAD_CONFIG 0x3005
|
#define EGL_BAD_CONFIG 0x3005
|
||||||
#define EGL_BAD_CONTEXT 0x3006
|
#define EGL_BAD_CONTEXT 0x3006
|
||||||
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||||
#define EGL_BAD_DISPLAY 0x3008
|
#define EGL_BAD_DISPLAY 0x3008
|
||||||
#define EGL_BAD_MATCH 0x3009
|
#define EGL_BAD_MATCH 0x3009
|
||||||
#define EGL_BAD_NATIVE_PIXMAP 0x300a
|
#define EGL_BAD_NATIVE_PIXMAP 0x300a
|
||||||
#define EGL_BAD_NATIVE_WINDOW 0x300b
|
#define EGL_BAD_NATIVE_WINDOW 0x300b
|
||||||
#define EGL_BAD_PARAMETER 0x300c
|
#define EGL_BAD_PARAMETER 0x300c
|
||||||
#define EGL_BAD_SURFACE 0x300d
|
#define EGL_BAD_SURFACE 0x300d
|
||||||
#define EGL_CONTEXT_LOST 0x300e
|
#define EGL_CONTEXT_LOST 0x300e
|
||||||
#define EGL_COLOR_BUFFER_TYPE 0x303f
|
#define EGL_COLOR_BUFFER_TYPE 0x303f
|
||||||
#define EGL_RGB_BUFFER 0x308e
|
#define EGL_RGB_BUFFER 0x308e
|
||||||
#define EGL_SURFACE_TYPE 0x3033
|
#define EGL_SURFACE_TYPE 0x3033
|
||||||
#define EGL_WINDOW_BIT 0x0004
|
#define EGL_WINDOW_BIT 0x0004
|
||||||
#define EGL_RENDERABLE_TYPE 0x3040
|
#define EGL_RENDERABLE_TYPE 0x3040
|
||||||
#define EGL_OPENGL_ES_BIT 0x0001
|
#define EGL_OPENGL_ES_BIT 0x0001
|
||||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||||
#define EGL_OPENGL_BIT 0x0008
|
#define EGL_OPENGL_BIT 0x0008
|
||||||
@@ -76,7 +76,7 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
|||||||
#define EGL_RED_SIZE 0x3024
|
#define EGL_RED_SIZE 0x3024
|
||||||
#define EGL_DEPTH_SIZE 0x3025
|
#define EGL_DEPTH_SIZE 0x3025
|
||||||
#define EGL_STENCIL_SIZE 0x3026
|
#define EGL_STENCIL_SIZE 0x3026
|
||||||
#define EGL_SAMPLES 0x3031
|
#define EGL_SAMPLES 0x3031
|
||||||
#define EGL_OPENGL_ES_API 0x30a0
|
#define EGL_OPENGL_ES_API 0x30a0
|
||||||
#define EGL_OPENGL_API 0x30a2
|
#define EGL_OPENGL_API 0x30a2
|
||||||
#define EGL_NONE 0x3038
|
#define EGL_NONE 0x3038
|
||||||
@@ -87,6 +87,8 @@ typedef struct wl_egl_window* EGLNativeWindowType;
|
|||||||
#define EGL_NO_DISPLAY ((EGLDisplay) 0)
|
#define EGL_NO_DISPLAY ((EGLDisplay) 0)
|
||||||
#define EGL_NO_CONTEXT ((EGLContext) 0)
|
#define EGL_NO_CONTEXT ((EGLContext) 0)
|
||||||
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
|
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0)
|
||||||
|
#define EGL_MIN_SWAP_INTERVAL 0x303B
|
||||||
|
#define EGL_MAX_SWAP_INTERVAL 0x303C
|
||||||
|
|
||||||
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||||
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||||
@@ -171,13 +173,13 @@ typedef struct _GLFWlibraryEGL
|
|||||||
{
|
{
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
GLFWbool prefix;
|
bool prefix;
|
||||||
|
|
||||||
GLFWbool KHR_create_context;
|
bool KHR_create_context;
|
||||||
GLFWbool KHR_create_context_no_error;
|
bool KHR_create_context_no_error;
|
||||||
GLFWbool KHR_gl_colorspace;
|
bool KHR_gl_colorspace;
|
||||||
GLFWbool KHR_get_all_proc_addresses;
|
bool KHR_get_all_proc_addresses;
|
||||||
GLFWbool KHR_context_flush_control;
|
bool KHR_context_flush_control;
|
||||||
|
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
@@ -201,13 +203,13 @@ typedef struct _GLFWlibraryEGL
|
|||||||
} _GLFWlibraryEGL;
|
} _GLFWlibraryEGL;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitEGL(void);
|
bool _glfwInitEGL(void);
|
||||||
void _glfwTerminateEGL(void);
|
void _glfwTerminateEGL(void);
|
||||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
bool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth);
|
Visual** visual, int* depth);
|
||||||
|
|||||||
49
glfw/glfw.py
49
glfw/glfw.py
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
@@ -102,40 +102,6 @@ def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir):
|
|||||||
desc='Generating {} ...'.format(emphasis(os.path.basename(dest))))
|
desc='Generating {} ...'.format(emphasis(os.path.basename(dest))))
|
||||||
|
|
||||||
|
|
||||||
def collect_source_information():
|
|
||||||
raw = open('src/CMakeLists.txt').read()
|
|
||||||
mraw = open('CMakeLists.txt').read()
|
|
||||||
|
|
||||||
def extract_sources(group, start_pos=0):
|
|
||||||
for which in 'HEADERS SOURCES'.split():
|
|
||||||
yield which.lower(), list(filter(
|
|
||||||
lambda x: x[0] not in '"$',
|
|
||||||
re.search(
|
|
||||||
r'{0}_{1}\s+([^)]+?)[)]'.format(group, which),
|
|
||||||
raw[start_pos:]
|
|
||||||
).group(1).strip().split()
|
|
||||||
))
|
|
||||||
|
|
||||||
wayland_protocols = re.search(r'WaylandProtocols\s+(\S+)\s+', mraw).group(1)
|
|
||||||
wayland_protocols = list(map(int, wayland_protocols.split('.')))
|
|
||||||
ans = {
|
|
||||||
'common': dict(extract_sources('common')),
|
|
||||||
'wayland_protocols': wayland_protocols,
|
|
||||||
}
|
|
||||||
for group in 'cocoa win32 x11 wayland osmesa'.split():
|
|
||||||
m = re.search('_GLFW_' + group.upper(), raw)
|
|
||||||
ans[group] = dict(extract_sources('glfw', m.start()))
|
|
||||||
if group in ('x11', 'wayland'):
|
|
||||||
for joystick in ('linux', 'null'):
|
|
||||||
ans[group]['headers'].append('{}_joystick.h'.format(joystick))
|
|
||||||
ans[group]['sources'].append('{}_joystick.c'.format(joystick))
|
|
||||||
if group == 'wayland':
|
|
||||||
ans[group]['protocols'] = p = []
|
|
||||||
for m in re.finditer(r'WAYLAND_PROTOCOLS_PKGDATADIR\}/(.+?)"?$', raw, flags=re.M):
|
|
||||||
p.append(m.group(1))
|
|
||||||
return ans
|
|
||||||
|
|
||||||
|
|
||||||
class Arg:
|
class Arg:
|
||||||
|
|
||||||
def __init__(self, decl):
|
def __init__(self, decl):
|
||||||
@@ -168,6 +134,8 @@ class Function:
|
|||||||
if a == 'void':
|
if a == 'void':
|
||||||
continue
|
continue
|
||||||
self.args.append(Arg(a))
|
self.args.append(Arg(a))
|
||||||
|
if not self.args:
|
||||||
|
self.args = [Arg('void v')]
|
||||||
|
|
||||||
def declaration(self):
|
def declaration(self):
|
||||||
return 'typedef {restype} (*{name}_func)({args});\n{name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
return 'typedef {restype} (*{name}_func)({args});\n{name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
||||||
@@ -206,12 +174,16 @@ def generate_wrappers(glfw_header):
|
|||||||
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
||||||
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
||||||
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
||||||
|
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
|
||||||
void* glfwGetX11Display(void)
|
void* glfwGetX11Display(void)
|
||||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||||
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
||||||
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
||||||
int glfwGetXKBScancode(const char* key_name, int case_sensitive)
|
int glfwGetXKBScancode(const char* key_name, int case_sensitive)
|
||||||
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
||||||
|
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
||||||
|
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||||
|
void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler)
|
||||||
'''.splitlines():
|
'''.splitlines():
|
||||||
if line:
|
if line:
|
||||||
functions.append(Function(line.strip(), check_fail=False))
|
functions.append(Function(line.strip(), check_fail=False))
|
||||||
@@ -227,10 +199,13 @@ def generate_wrappers(glfw_header):
|
|||||||
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
||||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
|
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
|
||||||
|
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
|
||||||
|
typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*);
|
||||||
{}
|
{}
|
||||||
|
|
||||||
const char* load_glfw(const char* path);
|
const char* load_glfw(const char* path);
|
||||||
@@ -260,7 +235,7 @@ load_glfw(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
unload_glfw() {
|
unload_glfw(void) {
|
||||||
if (handle) { dlclose(handle); handle = NULL; }
|
if (handle) { dlclose(handle); handle = NULL; }
|
||||||
}
|
}
|
||||||
'''.replace('LOAD', '\n\n '.join(f.load() for f in functions))
|
'''.replace('LOAD', '\n\n '.join(f.load() for f in functions))
|
||||||
|
|||||||
464
glfw/glfw3.h
vendored
464
glfw/glfw3.h
vendored
@@ -133,6 +133,8 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* Include the chosen OpenGL or OpenGL ES headers.
|
/* Include the chosen OpenGL or OpenGL ES headers.
|
||||||
*/
|
*/
|
||||||
#if defined(GLFW_INCLUDE_ES1)
|
#if defined(GLFW_INCLUDE_ES1)
|
||||||
@@ -269,24 +271,6 @@ extern "C" {
|
|||||||
#define GLFW_VERSION_REVISION 0
|
#define GLFW_VERSION_REVISION 0
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
/*! @name Boolean values
|
|
||||||
* @{ */
|
|
||||||
/*! @brief One.
|
|
||||||
*
|
|
||||||
* One. Seriously. You don't _need_ to use this symbol in your code. It's
|
|
||||||
* semantic sugar for the number 1. You can also use `1` or `true` or `_True`
|
|
||||||
* or `GL_TRUE` or whatever you want.
|
|
||||||
*/
|
|
||||||
#define GLFW_TRUE 1
|
|
||||||
/*! @brief Zero.
|
|
||||||
*
|
|
||||||
* Zero. Seriously. You don't _need_ to use this symbol in your code. It's
|
|
||||||
* semantic sugar for the number 0. You can also use `0` or `false` or
|
|
||||||
* `_False` or `GL_FALSE` or whatever you want.
|
|
||||||
*/
|
|
||||||
#define GLFW_FALSE 0
|
|
||||||
/*! @} */
|
|
||||||
|
|
||||||
/*! @name Key and button actions
|
/*! @name Key and button actions
|
||||||
* @{ */
|
* @{ */
|
||||||
/*! @brief The key or mouse button was released.
|
/*! @brief The key or mouse button was released.
|
||||||
@@ -408,6 +392,7 @@ extern "C" {
|
|||||||
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
|
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
|
||||||
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
|
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
|
||||||
#define GLFW_KEY_PLUS 163
|
#define GLFW_KEY_PLUS 163
|
||||||
|
#define GLFW_KEY_UNDERSCORE 164
|
||||||
|
|
||||||
/* Function keys */
|
/* Function keys */
|
||||||
#define GLFW_KEY_ESCAPE 256
|
#define GLFW_KEY_ESCAPE 256
|
||||||
@@ -826,7 +811,11 @@ extern "C" {
|
|||||||
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
||||||
*/
|
*/
|
||||||
#define GLFW_FOCUS_ON_SHOW 0x0002000C
|
#define GLFW_FOCUS_ON_SHOW 0x0002000C
|
||||||
|
/*! @brief Occlusion window attribute
|
||||||
|
*
|
||||||
|
* Occlusion [window attribute](@ref GLFW_OCCLUDED_attrib).
|
||||||
|
*/
|
||||||
|
#define GLFW_OCCLUDED 0x0002000D
|
||||||
/*! @brief Framebuffer bit depth hint.
|
/*! @brief Framebuffer bit depth hint.
|
||||||
*
|
*
|
||||||
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
||||||
@@ -1026,36 +1015,19 @@ extern "C" {
|
|||||||
* @ingroup input
|
* @ingroup input
|
||||||
* @{ */
|
* @{ */
|
||||||
|
|
||||||
/*! @brief The regular arrow cursor shape.
|
typedef enum {
|
||||||
*
|
GLFW_ARROW_CURSOR,
|
||||||
* The regular arrow cursor.
|
GLFW_IBEAM_CURSOR,
|
||||||
*/
|
GLFW_CROSSHAIR_CURSOR,
|
||||||
#define GLFW_ARROW_CURSOR 0x00036001
|
GLFW_HAND_CURSOR,
|
||||||
/*! @brief The text input I-beam cursor shape.
|
GLFW_HRESIZE_CURSOR,
|
||||||
*
|
GLFW_VRESIZE_CURSOR,
|
||||||
* The text input I-beam cursor shape.
|
GLFW_NW_RESIZE_CURSOR,
|
||||||
*/
|
GLFW_NE_RESIZE_CURSOR,
|
||||||
#define GLFW_IBEAM_CURSOR 0x00036002
|
GLFW_SW_RESIZE_CURSOR,
|
||||||
/*! @brief The crosshair shape.
|
GLFW_SE_RESIZE_CURSOR,
|
||||||
*
|
GLFW_INVALID_CURSOR
|
||||||
* The crosshair shape.
|
} GLFWCursorShape;
|
||||||
*/
|
|
||||||
#define GLFW_CROSSHAIR_CURSOR 0x00036003
|
|
||||||
/*! @brief The hand shape.
|
|
||||||
*
|
|
||||||
* The hand shape.
|
|
||||||
*/
|
|
||||||
#define GLFW_HAND_CURSOR 0x00036004
|
|
||||||
/*! @brief The horizontal resize arrow shape.
|
|
||||||
*
|
|
||||||
* The horizontal resize arrow shape.
|
|
||||||
*/
|
|
||||||
#define GLFW_HRESIZE_CURSOR 0x00036005
|
|
||||||
/*! @brief The vertical resize arrow shape.
|
|
||||||
*
|
|
||||||
* The vertical resize arrow shape.
|
|
||||||
*/
|
|
||||||
#define GLFW_VRESIZE_CURSOR 0x00036006
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
#define GLFW_CONNECTED 0x00040001
|
#define GLFW_CONNECTED 0x00040001
|
||||||
@@ -1164,9 +1136,9 @@ typedef void (* GLFWerrorfun)(int,const char*);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window that was moved.
|
* @param[in] window The window that was moved.
|
||||||
* @param[in] xpos The new x-coordinate, in screen coordinates, of the
|
* @param[in] xpos The new x-coordinate, in screen coordinates, of the
|
||||||
* upper-left corner of the client area of the window.
|
* upper-left corner of the content area of the window.
|
||||||
* @param[in] ypos The new y-coordinate, in screen coordinates, of the
|
* @param[in] ypos The new y-coordinate, in screen coordinates, of the
|
||||||
* upper-left corner of the client area of the window.
|
* upper-left corner of the content area of the window.
|
||||||
*
|
*
|
||||||
* @sa @ref window_pos
|
* @sa @ref window_pos
|
||||||
* @sa @ref glfwSetWindowPosCallback
|
* @sa @ref glfwSetWindowPosCallback
|
||||||
@@ -1232,8 +1204,8 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
|
|||||||
* This is the function signature for window focus callback functions.
|
* This is the function signature for window focus callback functions.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that gained or lost input focus.
|
* @param[in] window The window that gained or lost input focus.
|
||||||
* @param[in] focused `GLFW_TRUE` if the window was given input focus, or
|
* @param[in] focused `true` if the window was given input focus, or
|
||||||
* `GLFW_FALSE` if it lost it.
|
* `false` if it lost it.
|
||||||
*
|
*
|
||||||
* @sa @ref window_focus
|
* @sa @ref window_focus
|
||||||
* @sa @ref glfwSetWindowFocusCallback
|
* @sa @ref glfwSetWindowFocusCallback
|
||||||
@@ -1244,14 +1216,32 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
|
typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
|
||||||
|
|
||||||
|
/*! @brief The function signature for window occlusion callbacks.
|
||||||
|
*
|
||||||
|
* This is the function signature for window occlusion callback functions.
|
||||||
|
*
|
||||||
|
* @param[in] window The window whose occlusion state changed.
|
||||||
|
* @param[in] occluded `true` if the window was occluded, or `false`
|
||||||
|
* if the window is no longer occluded.
|
||||||
|
*
|
||||||
|
* @sa @ref window_occlusion
|
||||||
|
* @sa @ref glfwSetWindowOcclusionCallback
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup window
|
||||||
|
*/
|
||||||
|
typedef void (* GLFWwindowocclusionfun)(GLFWwindow*, bool);
|
||||||
|
|
||||||
|
|
||||||
/*! @brief The function signature for window iconify/restore callbacks.
|
/*! @brief The function signature for window iconify/restore callbacks.
|
||||||
*
|
*
|
||||||
* This is the function signature for window iconify/restore callback
|
* This is the function signature for window iconify/restore callback
|
||||||
* functions.
|
* functions.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that was iconified or restored.
|
* @param[in] window The window that was iconified or restored.
|
||||||
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
|
* @param[in] iconified `true` if the window was iconified, or
|
||||||
* `GLFW_FALSE` if it was restored.
|
* `false` if it was restored.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
* @sa @ref glfwSetWindowIconifyCallback
|
* @sa @ref glfwSetWindowIconifyCallback
|
||||||
@@ -1268,8 +1258,8 @@ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
|
|||||||
* functions.
|
* functions.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that was maximized or restored.
|
* @param[in] window The window that was maximized or restored.
|
||||||
* @param[in] iconified `GLFW_TRUE` if the window was maximized, or
|
* @param[in] iconified `true` if the window was maximized, or
|
||||||
* `GLFW_FALSE` if it was restored.
|
* `false` if it was restored.
|
||||||
*
|
*
|
||||||
* @sa @ref window_maximize
|
* @sa @ref window_maximize
|
||||||
* @sa glfwSetWindowMaximizeCallback
|
* @sa glfwSetWindowMaximizeCallback
|
||||||
@@ -1343,9 +1333,9 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window that received the event.
|
* @param[in] window The window that received the event.
|
||||||
* @param[in] xpos The new cursor x-coordinate, relative to the left edge of
|
* @param[in] xpos The new cursor x-coordinate, relative to the left edge of
|
||||||
* the client area.
|
* the content area.
|
||||||
* @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
|
* @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
|
||||||
* client area.
|
* content area.
|
||||||
*
|
*
|
||||||
* @sa @ref cursor_pos
|
* @sa @ref cursor_pos
|
||||||
* @sa @ref glfwSetCursorPosCallback
|
* @sa @ref glfwSetCursorPosCallback
|
||||||
@@ -1361,8 +1351,8 @@ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
|
|||||||
* This is the function signature for cursor enter/leave callback functions.
|
* This is the function signature for cursor enter/leave callback functions.
|
||||||
*
|
*
|
||||||
* @param[in] window The window that received the event.
|
* @param[in] window The window that received the event.
|
||||||
* @param[in] entered `GLFW_TRUE` if the cursor entered the window's client
|
* @param[in] entered `true` if the cursor entered the window's client
|
||||||
* area, or `GLFW_FALSE` if it left it.
|
* area, or `false` if it left it.
|
||||||
*
|
*
|
||||||
* @sa @ref cursor_enter
|
* @sa @ref cursor_enter
|
||||||
* @sa @ref glfwSetCursorEnterCallback
|
* @sa @ref glfwSetCursorEnterCallback
|
||||||
@@ -1450,6 +1440,8 @@ typedef void (* GLFWkeyboardfun)(GLFWwindow*, int, int, int, int, const char*, i
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
|
typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
|
||||||
|
|
||||||
|
typedef void (* GLFWliveresizefun)(GLFWwindow*, bool);
|
||||||
|
|
||||||
/*! @brief The function signature for monitor configuration callbacks.
|
/*! @brief The function signature for monitor configuration callbacks.
|
||||||
*
|
*
|
||||||
* This is the function signature for monitor configuration callback functions.
|
* This is the function signature for monitor configuration callback functions.
|
||||||
@@ -1485,6 +1477,9 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
|
|||||||
*/
|
*/
|
||||||
typedef void (* GLFWjoystickfun)(int,int);
|
typedef void (* GLFWjoystickfun)(int,int);
|
||||||
|
|
||||||
|
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
||||||
|
typedef void (* GLFWtickcallback)(void*);
|
||||||
|
|
||||||
/*! @brief Video mode type.
|
/*! @brief Video mode type.
|
||||||
*
|
*
|
||||||
* This describes a single video mode.
|
* This describes a single video mode.
|
||||||
@@ -1609,9 +1604,9 @@ typedef struct GLFWgamepadstate
|
|||||||
* succeeds, you should call @ref glfwTerminate before the application exits.
|
* succeeds, you should call @ref glfwTerminate before the application exits.
|
||||||
*
|
*
|
||||||
* Additional calls to this function after successful initialization but before
|
* Additional calls to this function after successful initialization but before
|
||||||
* termination will return `GLFW_TRUE` immediately.
|
* termination will return `true` immediately.
|
||||||
*
|
*
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
* @return `true` if successful, or `false` if an
|
||||||
* [error](@ref error_handling) occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||||
@@ -1631,6 +1626,12 @@ typedef struct GLFWgamepadstate
|
|||||||
* @ingroup init
|
* @ingroup init
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwInit(void);
|
GLFWAPI int glfwInit(void);
|
||||||
|
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data);
|
||||||
|
GLFWAPI void glfwStopMainLoop(void);
|
||||||
|
GLFWAPI void glfwRequestTickCallback(void);
|
||||||
|
GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback);
|
||||||
|
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
||||||
|
GLFWAPI void glfwRemoveTimer(unsigned long long);
|
||||||
|
|
||||||
/*! @brief Terminates the GLFW library.
|
/*! @brief Terminates the GLFW library.
|
||||||
*
|
*
|
||||||
@@ -1902,6 +1903,35 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
|
GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||||
|
|
||||||
|
/*! @brief Returns the work area of the monitor.
|
||||||
|
*
|
||||||
|
* This function returns the position, in screen coordinates, of the upper-left
|
||||||
|
* corner of the specified monitor alongwith the work area size in screen co-ordinates.
|
||||||
|
* The work area is defined as the area of the monitor not occluded by the operating
|
||||||
|
* system chrome (task bar, global menubar, etc.).
|
||||||
|
*
|
||||||
|
* Any or all of the position and size arguments may be `NULL`. If an error occurs, all
|
||||||
|
* non-`NULL` position and size arguments will be set to zero.
|
||||||
|
*
|
||||||
|
* @param[in] monitor The monitor to query.
|
||||||
|
* @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.
|
||||||
|
* @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.
|
||||||
|
* @param[out] width Where to store the monitor width, or `NULL`.
|
||||||
|
* @param[out] height Where to store the monitor height, or `NULL`.
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
|
* GLFW_PLATFORM_ERROR.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref monitor_workarea
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup monitor
|
||||||
|
*/
|
||||||
|
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
|
||||||
|
|
||||||
/*! @brief Returns the physical size of the monitor.
|
/*! @brief Returns the physical size of the monitor.
|
||||||
*
|
*
|
||||||
* This function returns the size, in millimetres, of the display area of the
|
* This function returns the size, in millimetres, of the display area of the
|
||||||
@@ -2424,7 +2454,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
* @remark @macos On OS X 10.10 and later the window frame will not be rendered
|
||||||
* at full resolution on Retina displays unless the
|
* at full resolution on Retina displays unless the
|
||||||
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
|
* [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
|
||||||
* hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the
|
* hint is `true` and the `NSHighResolutionCapable` key is enabled in the
|
||||||
* application bundle's `Info.plist`. For more information, see
|
* application bundle's `Info.plist`. For more information, see
|
||||||
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
* [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)
|
||||||
* in the Mac Developer Library. The GLFW test and example programs use
|
* in the Mac Developer Library. The GLFW test and example programs use
|
||||||
@@ -2450,11 +2480,13 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
* GLFW_X11_CLASS_NAME and @ref GLFW_X11_INSTANCE_NAME window hints to override
|
* GLFW_X11_CLASS_NAME and @ref GLFW_X11_INSTANCE_NAME window hints to override
|
||||||
* this.
|
* this.
|
||||||
*
|
*
|
||||||
* @remark @wayland The window frame is currently very simple, only allowing
|
* @remark @wayland Compositors should implement the xdg-decoration protocol
|
||||||
* window resize or move. A compositor can still emit close, maximize or
|
* for GLFW to decorate the window properly. If this protocol isn't
|
||||||
* fullscreen events, using for example a keybind mechanism. Additionally,
|
* supported, or if the compositor prefers client-side decorations, a very
|
||||||
* the wp_viewporter protocol is required for this feature, otherwise the
|
* simple fallback frame will be drawn using the wp_viewporter protocol. A
|
||||||
* window will not be decorated.
|
* compositor can still emit close, maximize or fullscreen events, using for
|
||||||
|
* instance a keybind mechanism. If neither of these protocols is supported,
|
||||||
|
* the window won't be decorated.
|
||||||
*
|
*
|
||||||
* @remark @wayland A full screen window will not attempt to change the mode,
|
* @remark @wayland A full screen window will not attempt to change the mode,
|
||||||
* no matter what the requested size or refresh rate.
|
* no matter what the requested size or refresh rate.
|
||||||
@@ -2472,6 +2504,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
|||||||
* @ingroup window
|
* @ingroup window
|
||||||
*/
|
*/
|
||||||
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
|
GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);
|
||||||
|
GLFWAPI bool glfwToggleFullscreen(GLFWwindow *window, unsigned int flags);
|
||||||
|
|
||||||
/*! @brief Destroys the specified window and its context.
|
/*! @brief Destroys the specified window and its context.
|
||||||
*
|
*
|
||||||
@@ -2616,19 +2649,19 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
|
GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);
|
||||||
|
|
||||||
/*! @brief Retrieves the position of the client area of the specified window.
|
/*! @brief Retrieves the position of the content area of the specified window.
|
||||||
*
|
*
|
||||||
* This function retrieves the position, in screen coordinates, of the
|
* This function retrieves the position, in screen coordinates, of the
|
||||||
* upper-left corner of the client area of the specified window.
|
* upper-left corner of the content area of the specified window.
|
||||||
*
|
*
|
||||||
* Any or all of the position arguments may be `NULL`. If an error occurs, all
|
* Any or all of the position arguments may be `NULL`. If an error occurs, all
|
||||||
* non-`NULL` position arguments will be set to zero.
|
* non-`NULL` position arguments will be set to zero.
|
||||||
*
|
*
|
||||||
* @param[in] window The window to query.
|
* @param[in] window The window to query.
|
||||||
* @param[out] xpos Where to store the x-coordinate of the upper-left corner of
|
* @param[out] xpos Where to store the x-coordinate of the upper-left corner of
|
||||||
* the client area, or `NULL`.
|
* the content area, or `NULL`.
|
||||||
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
|
* @param[out] ypos Where to store the y-coordinate of the upper-left corner of
|
||||||
* the client area, or `NULL`.
|
* the content area, or `NULL`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -2648,10 +2681,10 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
||||||
|
|
||||||
/*! @brief Sets the position of the client area of the specified window.
|
/*! @brief Sets the position of the content area of the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the position, in screen coordinates, of the upper-left
|
* This function sets the position, in screen coordinates, of the upper-left
|
||||||
* corner of the client area of the specified windowed mode window. If the
|
* corner of the content area of the specified windowed mode window. If the
|
||||||
* window is a full screen window, this function does nothing.
|
* window is a full screen window, this function does nothing.
|
||||||
*
|
*
|
||||||
* __Do not use this function__ to move an already visible window unless you
|
* __Do not use this function__ to move an already visible window unless you
|
||||||
@@ -2661,8 +2694,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
|||||||
* cannot and should not override these limits.
|
* cannot and should not override these limits.
|
||||||
*
|
*
|
||||||
* @param[in] window The window to query.
|
* @param[in] window The window to query.
|
||||||
* @param[in] xpos The x-coordinate of the upper-left corner of the client area.
|
* @param[in] xpos The x-coordinate of the upper-left corner of the content area.
|
||||||
* @param[in] ypos The y-coordinate of the upper-left corner of the client area.
|
* @param[in] ypos The y-coordinate of the upper-left corner of the content area.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -2683,9 +2716,9 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
|
GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
|
||||||
|
|
||||||
/*! @brief Retrieves the size of the client area of the specified window.
|
/*! @brief Retrieves the size of the content area of the specified window.
|
||||||
*
|
*
|
||||||
* This function retrieves the size, in screen coordinates, of the client area
|
* This function retrieves the size, in screen coordinates, of the content area
|
||||||
* of the specified window. If you wish to retrieve the size of the
|
* of the specified window. If you wish to retrieve the size of the
|
||||||
* framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
|
* framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
|
||||||
*
|
*
|
||||||
@@ -2694,9 +2727,9 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window whose size to retrieve.
|
* @param[in] window The window whose size to retrieve.
|
||||||
* @param[out] width Where to store the width, in screen coordinates, of the
|
* @param[out] width Where to store the width, in screen coordinates, of the
|
||||||
* client area, or `NULL`.
|
* content area, or `NULL`.
|
||||||
* @param[out] height Where to store the height, in screen coordinates, of the
|
* @param[out] height Where to store the height, in screen coordinates, of the
|
||||||
* client area, or `NULL`.
|
* content area, or `NULL`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -2715,7 +2748,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
|
|||||||
|
|
||||||
/*! @brief Sets the size limits of the specified window.
|
/*! @brief Sets the size limits of the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the size limits of the client area of the specified
|
* This function sets the size limits of the content area of the specified
|
||||||
* window. If the window is full screen, the size limits only take effect
|
* window. If the window is full screen, the size limits only take effect
|
||||||
* once it is made windowed. If the window is not resizable, this function
|
* once it is made windowed. If the window is not resizable, this function
|
||||||
* does nothing.
|
* does nothing.
|
||||||
@@ -2730,11 +2763,11 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
|
|||||||
* @param[in] minwidth The minimum width, in screen coordinates, of the client
|
* @param[in] minwidth The minimum width, in screen coordinates, of the client
|
||||||
* area, or `GLFW_DONT_CARE`.
|
* area, or `GLFW_DONT_CARE`.
|
||||||
* @param[in] minheight The minimum height, in screen coordinates, of the
|
* @param[in] minheight The minimum height, in screen coordinates, of the
|
||||||
* client area, or `GLFW_DONT_CARE`.
|
* content area, or `GLFW_DONT_CARE`.
|
||||||
* @param[in] maxwidth The maximum width, in screen coordinates, of the client
|
* @param[in] maxwidth The maximum width, in screen coordinates, of the client
|
||||||
* area, or `GLFW_DONT_CARE`.
|
* area, or `GLFW_DONT_CARE`.
|
||||||
* @param[in] maxheight The maximum height, in screen coordinates, of the
|
* @param[in] maxheight The maximum height, in screen coordinates, of the
|
||||||
* client area, or `GLFW_DONT_CARE`.
|
* content area, or `GLFW_DONT_CARE`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||||
@@ -2758,7 +2791,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
|
|||||||
|
|
||||||
/*! @brief Sets the aspect ratio of the specified window.
|
/*! @brief Sets the aspect ratio of the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the required aspect ratio of the client area of the
|
* This function sets the required aspect ratio of the content area of the
|
||||||
* specified window. If the window is full screen, the aspect ratio only takes
|
* specified window. If the window is full screen, the aspect ratio only takes
|
||||||
* effect once it is made windowed. If the window is not resizable, this
|
* effect once it is made windowed. If the window is not resizable, this
|
||||||
* function does nothing.
|
* function does nothing.
|
||||||
@@ -2799,9 +2832,9 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
|
GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
|
||||||
|
|
||||||
/*! @brief Sets the size of the client area of the specified window.
|
/*! @brief Sets the size of the content area of the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the size, in screen coordinates, of the client area of
|
* This function sets the size, in screen coordinates, of the content area of
|
||||||
* the specified window.
|
* the specified window.
|
||||||
*
|
*
|
||||||
* For full screen windows, this function updates the resolution of its desired
|
* For full screen windows, this function updates the resolution of its desired
|
||||||
@@ -2817,9 +2850,9 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window to resize.
|
* @param[in] window The window to resize.
|
||||||
* @param[in] width The desired width, in screen coordinates, of the window
|
* @param[in] width The desired width, in screen coordinates, of the window
|
||||||
* client area.
|
* content area.
|
||||||
* @param[in] height The desired height, in screen coordinates, of the window
|
* @param[in] height The desired height, in screen coordinates, of the window
|
||||||
* client area.
|
* content area.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -3033,9 +3066,8 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
* @remark @wayland There is no concept of iconification in wl_shell, this
|
* @remark @wayland Once a window is iconified it cannot be restored
|
||||||
* function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
|
* except by the compositor, this is a design decision of xdg-shell.
|
||||||
* protocol.
|
|
||||||
*
|
*
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
@@ -3223,7 +3255,7 @@ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
|
|||||||
* supported. Currently (macOS, Windows, X11 and Wayland).
|
* supported. Currently (macOS, Windows, X11 and Wayland).
|
||||||
*
|
*
|
||||||
* @param[in] window The window with which the bell is associated.
|
* @param[in] window The window with which the bell is associated.
|
||||||
* @return GLFW_TRUE if the bell succeeded otherwise GLFW_FALSE
|
* @return true if the bell succeeded otherwise false
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -3272,7 +3304,7 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
|||||||
* The window position is ignored when setting a monitor.
|
* The window position is ignored when setting a monitor.
|
||||||
*
|
*
|
||||||
* When the monitor is `NULL`, the position, width and height are used to
|
* When the monitor is `NULL`, the position, width and height are used to
|
||||||
* place the window client area. The refresh rate is ignored when no monitor
|
* place the window content area. The refresh rate is ignored when no monitor
|
||||||
* is specified.
|
* is specified.
|
||||||
*
|
*
|
||||||
* If you only wish to update the resolution of a full screen window or the
|
* If you only wish to update the resolution of a full screen window or the
|
||||||
@@ -3285,10 +3317,10 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
|||||||
* @param[in] window The window whose monitor, size or video mode to set.
|
* @param[in] window The window whose monitor, size or video mode to set.
|
||||||
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
|
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
|
||||||
* @param[in] xpos The desired x-coordinate of the upper-left corner of the
|
* @param[in] xpos The desired x-coordinate of the upper-left corner of the
|
||||||
* client area.
|
* content area.
|
||||||
* @param[in] ypos The desired y-coordinate of the upper-left corner of the
|
* @param[in] ypos The desired y-coordinate of the upper-left corner of the
|
||||||
* client area.
|
* content area.
|
||||||
* @param[in] width The desired with, in screen coordinates, of the client area
|
* @param[in] width The desired with, in screen coordinates, of the content area
|
||||||
* or video mode.
|
* or video mode.
|
||||||
* @param[in] height The desired height, in screen coordinates, of the client
|
* @param[in] height The desired height, in screen coordinates, of the client
|
||||||
* area or video mode.
|
* area or video mode.
|
||||||
@@ -3373,7 +3405,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
|
|||||||
*
|
*
|
||||||
* @param[in] window The window to set the attribute for.
|
* @param[in] window The window to set the attribute for.
|
||||||
* @param[in] attrib A supported window attribute.
|
* @param[in] attrib A supported window attribute.
|
||||||
* @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
|
* @param[in] value `true` or `false`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||||
@@ -3440,7 +3472,7 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
|
|||||||
*
|
*
|
||||||
* This function sets the position callback of the specified window, which is
|
* This function sets the position callback of the specified window, which is
|
||||||
* called when the window is moved. The callback is provided with the
|
* called when the window is moved. The callback is provided with the
|
||||||
* position, in screen coordinates, of the upper-left corner of the client area
|
* position, in screen coordinates, of the upper-left corner of the content area
|
||||||
* of the window.
|
* of the window.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose callback to set.
|
* @param[in] window The window whose callback to set.
|
||||||
@@ -3468,7 +3500,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
|
|||||||
*
|
*
|
||||||
* This function sets the size callback of the specified window, which is
|
* This function sets the size callback of the specified window, which is
|
||||||
* called when the window is resized. The callback is provided with the size,
|
* called when the window is resized. The callback is provided with the size,
|
||||||
* in screen coordinates, of the client area of the window.
|
* in screen coordinates, of the content area of the window.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose callback to set.
|
* @param[in] window The window whose callback to set.
|
||||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||||
@@ -3525,7 +3557,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
|
|||||||
/*! @brief Sets the refresh callback for the specified window.
|
/*! @brief Sets the refresh callback for the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the refresh callback of the specified window, which is
|
* This function sets the refresh callback of the specified window, which is
|
||||||
* called when the client area of the window needs to be redrawn, for example
|
* called when the content area of the window needs to be redrawn, for example
|
||||||
* if the window has been exposed after having been covered by another window.
|
* if the window has been exposed after having been covered by another window.
|
||||||
*
|
*
|
||||||
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
|
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
|
||||||
@@ -3579,6 +3611,31 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GL
|
|||||||
*/
|
*/
|
||||||
GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);
|
GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);
|
||||||
|
|
||||||
|
/*! @brief Sets the occlusion callback for the specified window.
|
||||||
|
*
|
||||||
|
* This function sets the occlusion callback of the specified window, which is
|
||||||
|
* called when the window becomes (fully) occluded by other windows or when (a
|
||||||
|
* part of) the window becomes visible again because an overlapping window is
|
||||||
|
* moved away.
|
||||||
|
*
|
||||||
|
* @param[in] window The window whose callback to set.
|
||||||
|
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||||
|
* callback.
|
||||||
|
* @return The previously set callback, or `NULL` if no callback was set or the
|
||||||
|
* library had not been [initialized](@ref intro_init).
|
||||||
|
*
|
||||||
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||||
|
*
|
||||||
|
* @thread_safety This function must only be called from the main thread.
|
||||||
|
*
|
||||||
|
* @sa @ref window_occlusion
|
||||||
|
*
|
||||||
|
* @since Added in version 3.3.
|
||||||
|
*
|
||||||
|
* @ingroup window
|
||||||
|
*/
|
||||||
|
GLFWAPI GLFWwindowocclusionfun glfwSetWindowOcclusionCallback(GLFWwindow* window, GLFWwindowocclusionfun cbfun);
|
||||||
|
|
||||||
/*! @brief Sets the iconify callback for the specified window.
|
/*! @brief Sets the iconify callback for the specified window.
|
||||||
*
|
*
|
||||||
* This function sets the iconification callback of the specified window, which
|
* This function sets the iconification callback of the specified window, which
|
||||||
@@ -3592,9 +3649,6 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
|
|||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||||
*
|
*
|
||||||
* @remark @wayland The wl_shell protocol has no concept of iconification,
|
|
||||||
* this callback will never be called when using this deprecated protocol.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
* @thread_safety This function must only be called from the main thread.
|
||||||
*
|
*
|
||||||
* @sa @ref window_iconify
|
* @sa @ref window_iconify
|
||||||
@@ -3675,152 +3729,11 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
|
|||||||
*/
|
*/
|
||||||
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
|
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun cbfun);
|
||||||
|
|
||||||
/*! @brief Processes all pending events.
|
|
||||||
*
|
|
||||||
* This function processes only those events that are already in the event
|
|
||||||
* queue and then returns immediately. Processing events will cause the window
|
|
||||||
* and input callbacks associated with those events to be called.
|
|
||||||
*
|
|
||||||
* On some platforms, a window move, resize or menu operation will cause event
|
|
||||||
* processing to block. This is due to how event processing is designed on
|
|
||||||
* those platforms. You can use the
|
|
||||||
* [window refresh callback](@ref window_refresh) to redraw the contents of
|
|
||||||
* your window when necessary during such operations.
|
|
||||||
*
|
|
||||||
* Do not assume that callbacks you set will _only_ be called in response to
|
|
||||||
* event processing functions like this one. While it is necessary to poll for
|
|
||||||
* events, 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.
|
|
||||||
*
|
|
||||||
* Event processing is not required for joystick input to work.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
|
||||||
* GLFW_PLATFORM_ERROR.
|
|
||||||
*
|
|
||||||
* @reentrancy This function must not be called from a callback.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
|
||||||
*
|
|
||||||
* @sa @ref events
|
|
||||||
* @sa @ref glfwWaitEvents
|
|
||||||
* @sa @ref glfwWaitEventsTimeout
|
|
||||||
*
|
|
||||||
* @since Added in version 1.0.
|
|
||||||
*
|
|
||||||
* @ingroup window
|
|
||||||
*/
|
|
||||||
GLFWAPI void glfwPollEvents(void);
|
|
||||||
|
|
||||||
/*! @brief Waits until events are queued and processes them.
|
|
||||||
*
|
|
||||||
* This function puts the calling thread to sleep until at least one event is
|
|
||||||
* available in the event queue. Once one or more events are available,
|
|
||||||
* it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue
|
|
||||||
* are processed and the function then returns immediately. Processing events
|
|
||||||
* will cause the window and input callbacks associated with those events to be
|
|
||||||
* called.
|
|
||||||
*
|
|
||||||
* Since not all events are associated with callbacks, this function may return
|
|
||||||
* without a callback having been called even if you are monitoring all
|
|
||||||
* callbacks.
|
|
||||||
*
|
|
||||||
* On some platforms, a window move, resize or menu operation will cause event
|
|
||||||
* processing to block. This is due to how event processing is designed on
|
|
||||||
* those platforms. You can use the
|
|
||||||
* [window refresh callback](@ref window_refresh) to redraw the contents of
|
|
||||||
* your window when necessary during such operations.
|
|
||||||
*
|
|
||||||
* Do not assume that callbacks you set will _only_ be called in response to
|
|
||||||
* event processing functions like this one. While it is necessary to poll for
|
|
||||||
* events, 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.
|
|
||||||
*
|
|
||||||
* If no windows exist, this function returns immediately. For synchronization
|
|
||||||
* of threads in applications that do not create windows, use your threading
|
|
||||||
* library of choice.
|
|
||||||
*
|
|
||||||
* Event processing is not required for joystick input to work.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
|
||||||
* GLFW_PLATFORM_ERROR.
|
|
||||||
*
|
|
||||||
* @reentrancy This function must not be called from a callback.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
|
||||||
*
|
|
||||||
* @sa @ref events
|
|
||||||
* @sa @ref glfwPollEvents
|
|
||||||
* @sa @ref glfwWaitEventsTimeout
|
|
||||||
*
|
|
||||||
* @since Added in version 2.5.
|
|
||||||
*
|
|
||||||
* @ingroup window
|
|
||||||
*/
|
|
||||||
GLFWAPI void glfwWaitEvents(void);
|
|
||||||
|
|
||||||
/*! @brief Waits with timeout until events are queued and processes them.
|
|
||||||
*
|
|
||||||
* This function puts the calling thread to sleep until at least one event is
|
|
||||||
* available in the event queue, or until the specified timeout is reached. If
|
|
||||||
* one or more events are available, it behaves exactly like @ref
|
|
||||||
* glfwPollEvents, i.e. the events in the queue are processed and the function
|
|
||||||
* then returns immediately. Processing events will cause the window and input
|
|
||||||
* callbacks associated with those events to be called.
|
|
||||||
*
|
|
||||||
* The timeout value must be a positive finite number.
|
|
||||||
*
|
|
||||||
* Since not all events are associated with callbacks, this function may return
|
|
||||||
* without a callback having been called even if you are monitoring all
|
|
||||||
* callbacks.
|
|
||||||
*
|
|
||||||
* On some platforms, a window move, resize or menu operation will cause event
|
|
||||||
* processing to block. This is due to how event processing is designed on
|
|
||||||
* those platforms. You can use the
|
|
||||||
* [window refresh callback](@ref window_refresh) to redraw the contents of
|
|
||||||
* your window when necessary during such operations.
|
|
||||||
*
|
|
||||||
* Do not assume that callbacks you set will _only_ be called in response to
|
|
||||||
* event processing functions like this one. While it is necessary to poll for
|
|
||||||
* events, 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.
|
|
||||||
*
|
|
||||||
* If no windows exist, this function returns immediately. For synchronization
|
|
||||||
* of threads in applications that do not create windows, use your threading
|
|
||||||
* library of choice.
|
|
||||||
*
|
|
||||||
* Event processing is not required for joystick input to work.
|
|
||||||
*
|
|
||||||
* @param[in] timeout The maximum amount of time, in seconds, to wait.
|
|
||||||
*
|
|
||||||
* @reentrancy This function must not be called from a callback.
|
|
||||||
*
|
|
||||||
* @thread_safety This function must only be called from the main thread.
|
|
||||||
*
|
|
||||||
* @sa @ref events
|
|
||||||
* @sa @ref glfwPollEvents
|
|
||||||
* @sa @ref glfwWaitEvents
|
|
||||||
*
|
|
||||||
* @since Added in version 3.2.
|
|
||||||
*
|
|
||||||
* @ingroup window
|
|
||||||
*/
|
|
||||||
GLFWAPI void glfwWaitEventsTimeout(double timeout);
|
|
||||||
|
|
||||||
/*! @brief Posts an empty event to the event queue.
|
/*! @brief Posts an empty event to the event queue.
|
||||||
*
|
*
|
||||||
* This function posts an empty event from the current thread to the event
|
* This function posts an empty event from the current thread to the event
|
||||||
* queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.
|
* queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.
|
||||||
*
|
*
|
||||||
* If no windows exist, this function returns immediately. For synchronization
|
|
||||||
* of threads in applications that do not create windows, use your threading
|
|
||||||
* library of choice.
|
|
||||||
*
|
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
@@ -3874,23 +3787,23 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
|||||||
* and unlimited cursor movement. This is useful for implementing for
|
* and unlimited cursor movement. This is useful for implementing for
|
||||||
* example 3D camera controls.
|
* example 3D camera controls.
|
||||||
*
|
*
|
||||||
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
|
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `true` to
|
||||||
* enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
|
* enable sticky keys, or `false` to disable it. If sticky keys are
|
||||||
* enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
|
* enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`
|
||||||
* the next time it is called even if the key had been released before the
|
* the next time it is called even if the key had been released before the
|
||||||
* call. This is useful when you are only interested in whether keys have been
|
* call. This is useful when you are only interested in whether keys have been
|
||||||
* pressed but not when or in which order.
|
* pressed but not when or in which order.
|
||||||
*
|
*
|
||||||
* If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
|
* If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either
|
||||||
* `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it.
|
* `true` to enable sticky mouse buttons, or `false` to disable it.
|
||||||
* If sticky mouse buttons are enabled, a mouse button press will ensure that
|
* If sticky mouse buttons are enabled, a mouse button press will ensure that
|
||||||
* @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even
|
* @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even
|
||||||
* if the mouse button had been released before the call. This is useful when
|
* if the mouse button had been released before the call. This is useful when
|
||||||
* you are only interested in whether mouse buttons have been pressed but not
|
* you are only interested in whether mouse buttons have been pressed but not
|
||||||
* when or in which order.
|
* when or in which order.
|
||||||
*
|
*
|
||||||
* If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
|
* If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `true` to
|
||||||
* enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled,
|
* enable lock key modifier bits, or `false` to disable them. If enabled,
|
||||||
* callbacks that receive modifier bits will also have the @ref
|
* callbacks that receive modifier bits will also have the @ref
|
||||||
* GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
|
* GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
|
||||||
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
|
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
|
||||||
@@ -4072,11 +3985,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
||||||
|
|
||||||
/*! @brief Retrieves the position of the cursor relative to the client area of
|
/*! @brief Retrieves the position of the cursor relative to the content area of
|
||||||
* the window.
|
* the window.
|
||||||
*
|
*
|
||||||
* This function returns the position of the cursor, in screen coordinates,
|
* This function returns the position of the cursor, in screen coordinates,
|
||||||
* relative to the upper-left corner of the client area of the specified
|
* relative to the upper-left corner of the content area of the specified
|
||||||
* window.
|
* window.
|
||||||
*
|
*
|
||||||
* If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
|
* If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
|
||||||
@@ -4092,9 +4005,9 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
|||||||
*
|
*
|
||||||
* @param[in] window The desired window.
|
* @param[in] window The desired window.
|
||||||
* @param[out] xpos Where to store the cursor x-coordinate, relative to the
|
* @param[out] xpos Where to store the cursor x-coordinate, relative to the
|
||||||
* left edge of the client area, or `NULL`.
|
* left edge of the content area, or `NULL`.
|
||||||
* @param[out] ypos Where to store the cursor y-coordinate, relative to the to
|
* @param[out] ypos Where to store the cursor y-coordinate, relative to the to
|
||||||
* top edge of the client area, or `NULL`.
|
* top edge of the content area, or `NULL`.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -4110,11 +4023,11 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
|||||||
*/
|
*/
|
||||||
GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
||||||
|
|
||||||
/*! @brief Sets the position of the cursor, relative to the client area of the
|
/*! @brief Sets the position of the cursor, relative to the content area of the
|
||||||
* window.
|
* window.
|
||||||
*
|
*
|
||||||
* This function sets the position, in screen coordinates, of the cursor
|
* This function sets the position, in screen coordinates, of the cursor
|
||||||
* relative to the upper-left corner of the client area of the specified
|
* relative to the upper-left corner of the content area of the specified
|
||||||
* window. The window must have input focus. If the window does not have
|
* window. The window must have input focus. If the window does not have
|
||||||
* input focus when this function is called, it fails silently.
|
* input focus when this function is called, it fails silently.
|
||||||
*
|
*
|
||||||
@@ -4129,9 +4042,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
|||||||
*
|
*
|
||||||
* @param[in] window The desired window.
|
* @param[in] window The desired window.
|
||||||
* @param[in] xpos The desired x-coordinate, relative to the left edge of the
|
* @param[in] xpos The desired x-coordinate, relative to the left edge of the
|
||||||
* client area.
|
* content area.
|
||||||
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
|
* @param[in] ypos The desired y-coordinate, relative to the top edge of the
|
||||||
* client area.
|
* content area.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* GLFW_PLATFORM_ERROR.
|
||||||
@@ -4210,7 +4123,7 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot,
|
|||||||
*
|
*
|
||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
|
GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape);
|
||||||
|
|
||||||
/*! @brief Destroys a cursor.
|
/*! @brief Destroys a cursor.
|
||||||
*
|
*
|
||||||
@@ -4242,7 +4155,7 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
|
|||||||
/*! @brief Sets the cursor for the window.
|
/*! @brief Sets the cursor for the window.
|
||||||
*
|
*
|
||||||
* This function sets the cursor image to be used when the cursor is over the
|
* This function sets the cursor image to be used when the cursor is over the
|
||||||
* client area of the specified window. The set cursor will only be visible
|
* content area of the specified window. The set cursor will only be visible
|
||||||
* when the [cursor mode](@ref cursor_mode) of the window is
|
* when the [cursor mode](@ref cursor_mode) of the window is
|
||||||
* `GLFW_CURSOR_NORMAL`.
|
* `GLFW_CURSOR_NORMAL`.
|
||||||
*
|
*
|
||||||
@@ -4324,7 +4237,7 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmo
|
|||||||
* This function sets the cursor position callback of the specified window,
|
* This function sets the cursor position callback of the specified window,
|
||||||
* which is called when the cursor is moved. The callback is provided with the
|
* which is called when the cursor is moved. The callback is provided with the
|
||||||
* position, in screen coordinates, relative to the upper-left corner of the
|
* position, in screen coordinates, relative to the upper-left corner of the
|
||||||
* client area of the window.
|
* content area of the window.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose callback to set.
|
* @param[in] window The window whose callback to set.
|
||||||
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
* @param[in] cbfun The new callback, or `NULL` to remove the currently set
|
||||||
@@ -4347,7 +4260,7 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursor
|
|||||||
/*! @brief Sets the cursor enter/exit callback.
|
/*! @brief Sets the cursor enter/exit callback.
|
||||||
*
|
*
|
||||||
* This function sets the cursor boundary crossing callback of the specified
|
* This function sets the cursor boundary crossing callback of the specified
|
||||||
* window, which is called when the cursor enters or leaves the client area of
|
* window, which is called when the cursor enters or leaves the content area of
|
||||||
* the window.
|
* the window.
|
||||||
*
|
*
|
||||||
* @param[in] window The window whose callback to set.
|
* @param[in] window The window whose callback to set.
|
||||||
@@ -4424,6 +4337,7 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb
|
|||||||
* @ingroup input
|
* @ingroup input
|
||||||
*/
|
*/
|
||||||
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||||
|
GLFWAPI GLFWliveresizefun glfwSetLiveResizeCallback(GLFWwindow* window, GLFWliveresizefun cbfun);
|
||||||
|
|
||||||
/*! @brief Returns whether the specified joystick is present.
|
/*! @brief Returns whether the specified joystick is present.
|
||||||
*
|
*
|
||||||
@@ -4434,7 +4348,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
|||||||
* work.
|
* work.
|
||||||
*
|
*
|
||||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||||
* @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.
|
* @return `true` if the joystick is present, or `false` otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||||
@@ -4708,13 +4622,13 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid);
|
|||||||
* a gamepad mapping.
|
* a gamepad mapping.
|
||||||
*
|
*
|
||||||
* If the specified joystick is present but does not have a gamepad mapping
|
* If the specified joystick is present but does not have a gamepad mapping
|
||||||
* this function will return `GLFW_FALSE` but will not generate an error. Call
|
* this function will return `false` but will not generate an error. Call
|
||||||
* @ref glfwJoystickPresent to check if a joystick is present regardless of
|
* @ref glfwJoystickPresent to check if a joystick is present regardless of
|
||||||
* whether it has a mapping.
|
* whether it has a mapping.
|
||||||
*
|
*
|
||||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||||
* @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
|
* @return `true` if a joystick is both present and has a gamepad mapping,
|
||||||
* or `GLFW_FALSE` otherwise.
|
* or `false` otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_INVALID_ENUM.
|
* GLFW_INVALID_ENUM.
|
||||||
@@ -4775,7 +4689,7 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
|
|||||||
* default.
|
* default.
|
||||||
*
|
*
|
||||||
* @param[in] string The string containing the gamepad mappings.
|
* @param[in] string The string containing the gamepad mappings.
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
|
* @return `true` if successful, or `false` if an
|
||||||
* [error](@ref error_handling) occurred.
|
* [error](@ref error_handling) occurred.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
@@ -4829,7 +4743,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
|||||||
* an Xbox-like gamepad.
|
* an Xbox-like gamepad.
|
||||||
*
|
*
|
||||||
* If the specified joystick is not present or does not have a gamepad mapping
|
* If the specified joystick is not present or does not have a gamepad mapping
|
||||||
* this function will return `GLFW_FALSE` but will not generate an error. Call
|
* this function will return `false` but will not generate an error. Call
|
||||||
* @ref glfwJoystickPresent to check whether it is present regardless of
|
* @ref glfwJoystickPresent to check whether it is present regardless of
|
||||||
* whether it has a mapping.
|
* whether it has a mapping.
|
||||||
*
|
*
|
||||||
@@ -4842,7 +4756,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
|||||||
*
|
*
|
||||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||||
* @param[out] state The gamepad input state of the joystick.
|
* @param[out] state The gamepad input state of the joystick.
|
||||||
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is
|
* @return `true` if successful, or `false` if no joystick is
|
||||||
* connected, it has no gamepad mapping or an [error](@ref error_handling)
|
* connected, it has no gamepad mapping or an [error](@ref error_handling)
|
||||||
* occurred.
|
* occurred.
|
||||||
*
|
*
|
||||||
@@ -5175,7 +5089,7 @@ GLFWAPI void glfwSwapInterval(int interval);
|
|||||||
* and `vkEnumerateDeviceExtensionProperties` instead.
|
* and `vkEnumerateDeviceExtensionProperties` instead.
|
||||||
*
|
*
|
||||||
* @param[in] extension The ASCII encoded name of the extension.
|
* @param[in] extension The ASCII encoded name of the extension.
|
||||||
* @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`
|
* @return `true` if the extension is available, or `false`
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
@@ -5248,7 +5162,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
|
|||||||
* and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue
|
* and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue
|
||||||
* family of a physical device supports image presentation.
|
* family of a physical device supports image presentation.
|
||||||
*
|
*
|
||||||
* @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE`
|
* @return `true` if Vulkan is minimally available, or `false`
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||||
@@ -5360,7 +5274,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
|||||||
*
|
*
|
||||||
* If Vulkan or the required window surface creation instance extensions are
|
* If Vulkan or the required window surface creation instance extensions are
|
||||||
* not available on the machine, or if the specified instance was not created
|
* not available on the machine, or if the specified instance was not created
|
||||||
* with the required extensions, this function returns `GLFW_FALSE` and
|
* with the required extensions, this function returns `false` and
|
||||||
* generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
|
* generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported
|
||||||
* to check whether Vulkan is at least minimally available and @ref
|
* to check whether Vulkan is at least minimally available and @ref
|
||||||
* glfwGetRequiredInstanceExtensions to check what instance extensions are
|
* glfwGetRequiredInstanceExtensions to check what instance extensions are
|
||||||
@@ -5369,13 +5283,13 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
|||||||
* @param[in] instance The instance that the physical device belongs to.
|
* @param[in] instance The instance that the physical device belongs to.
|
||||||
* @param[in] device The physical device that the queue family belongs to.
|
* @param[in] device The physical device that the queue family belongs to.
|
||||||
* @param[in] queuefamily The index of the queue family to query.
|
* @param[in] queuefamily The index of the queue family to query.
|
||||||
* @return `GLFW_TRUE` if the queue family supports presentation, or
|
* @return `true` if the queue family supports presentation, or
|
||||||
* `GLFW_FALSE` otherwise.
|
* `false` otherwise.
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
* GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
||||||
*
|
*
|
||||||
* @remark @macos This function currently always returns `GLFW_TRUE`, as the
|
* @remark @macos This function currently always returns `true`, as the
|
||||||
* `VK_MVK_macos_surface` extension does not provide
|
* `VK_MVK_macos_surface` extension does not provide
|
||||||
* a `vkGetPhysicalDevice*PresentationSupport` type function.
|
* a `vkGetPhysicalDevice*PresentationSupport` type function.
|
||||||
*
|
*
|
||||||
|
|||||||
87
glfw/glx_context.c
vendored
87
glfw/glx_context.c
vendored
@@ -47,7 +47,7 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
|
|||||||
|
|
||||||
// Return the GLXFBConfig most closely matching the specified hints
|
// Return the GLXFBConfig most closely matching the specified hints
|
||||||
//
|
//
|
||||||
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||||
GLXFBConfig* result)
|
GLXFBConfig* result)
|
||||||
{
|
{
|
||||||
GLXFBConfig* nativeConfigs;
|
GLXFBConfig* nativeConfigs;
|
||||||
@@ -55,20 +55,20 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
|||||||
const _GLFWfbconfig* closest;
|
const _GLFWfbconfig* closest;
|
||||||
int i, nativeCount, usableCount;
|
int i, nativeCount, usableCount;
|
||||||
const char* vendor;
|
const char* vendor;
|
||||||
GLFWbool trustWindowBit = GLFW_TRUE;
|
bool trustWindowBit = true;
|
||||||
|
|
||||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||||
if (vendor && strcmp(vendor, "Chromium") == 0)
|
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||||
trustWindowBit = GLFW_FALSE;
|
trustWindowBit = false;
|
||||||
|
|
||||||
nativeConfigs =
|
nativeConfigs =
|
||||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||||
if (!nativeConfigs || !nativeCount)
|
if (!nativeConfigs || !nativeCount)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||||
@@ -116,9 +116,9 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
|||||||
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
||||||
|
|
||||||
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
||||||
u->stereo = GLFW_TRUE;
|
u->stereo = true;
|
||||||
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
||||||
u->doublebuffer = GLFW_TRUE;
|
u->doublebuffer = true;
|
||||||
|
|
||||||
if (_glfw.glx.ARB_multisample)
|
if (_glfw.glx.ARB_multisample)
|
||||||
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
||||||
@@ -210,10 +210,10 @@ static int extensionSupportedGLX(const char* extension)
|
|||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWglproc getProcAddressGLX(const char* procname)
|
static GLFWglproc getProcAddressGLX(const char* procname)
|
||||||
@@ -226,8 +226,6 @@ static GLFWglproc getProcAddressGLX(const char* procname)
|
|||||||
return _glfw_dlsym(_glfw.glx.handle, procname);
|
return _glfw_dlsym(_glfw.glx.handle, procname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the OpenGL context
|
|
||||||
//
|
|
||||||
static void destroyContextGLX(_GLFWwindow* window)
|
static void destroyContextGLX(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->context.glx.window)
|
if (window->context.glx.window)
|
||||||
@@ -250,7 +248,7 @@ static void destroyContextGLX(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Initialize GLX
|
// Initialize GLX
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitGLX(void)
|
bool _glfwInitGLX(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
@@ -267,7 +265,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (_glfw.glx.handle)
|
if (_glfw.glx.handle)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
for (i = 0; sonames[i]; i++)
|
||||||
{
|
{
|
||||||
@@ -279,7 +277,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
if (!_glfw.glx.handle)
|
if (!_glfw.glx.handle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.glx.GetFBConfigs =
|
_glfw.glx.GetFBConfigs =
|
||||||
@@ -331,7 +329,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"GLX: Failed to load required entry points");
|
"GLX: Failed to load required entry points");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!glXQueryExtension(_glfw.x11.display,
|
if (!glXQueryExtension(_glfw.x11.display,
|
||||||
@@ -339,21 +337,21 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
&_glfw.glx.eventBase))
|
&_glfw.glx.eventBase))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
|
if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"GLX: Failed to query GLX version");
|
"GLX: Failed to query GLX version");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
|
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"GLX: GLX version 1.3 is required");
|
"GLX: GLX version 1.3 is required");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_EXT_swap_control"))
|
if (extensionSupportedGLX("GLX_EXT_swap_control"))
|
||||||
@@ -362,7 +360,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
getProcAddressGLX("glXSwapIntervalEXT");
|
getProcAddressGLX("glXSwapIntervalEXT");
|
||||||
|
|
||||||
if (_glfw.glx.SwapIntervalEXT)
|
if (_glfw.glx.SwapIntervalEXT)
|
||||||
_glfw.glx.EXT_swap_control = GLFW_TRUE;
|
_glfw.glx.EXT_swap_control = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_SGI_swap_control"))
|
if (extensionSupportedGLX("GLX_SGI_swap_control"))
|
||||||
@@ -371,7 +369,7 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
getProcAddressGLX("glXSwapIntervalSGI");
|
getProcAddressGLX("glXSwapIntervalSGI");
|
||||||
|
|
||||||
if (_glfw.glx.SwapIntervalSGI)
|
if (_glfw.glx.SwapIntervalSGI)
|
||||||
_glfw.glx.SGI_swap_control = GLFW_TRUE;
|
_glfw.glx.SGI_swap_control = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_MESA_swap_control"))
|
if (extensionSupportedGLX("GLX_MESA_swap_control"))
|
||||||
@@ -380,17 +378,17 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
getProcAddressGLX("glXSwapIntervalMESA");
|
getProcAddressGLX("glXSwapIntervalMESA");
|
||||||
|
|
||||||
if (_glfw.glx.SwapIntervalMESA)
|
if (_glfw.glx.SwapIntervalMESA)
|
||||||
_glfw.glx.MESA_swap_control = GLFW_TRUE;
|
_glfw.glx.MESA_swap_control = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_multisample"))
|
if (extensionSupportedGLX("GLX_ARB_multisample"))
|
||||||
_glfw.glx.ARB_multisample = GLFW_TRUE;
|
_glfw.glx.ARB_multisample = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
|
if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
|
||||||
_glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
|
_glfw.glx.ARB_framebuffer_sRGB = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
|
if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
|
||||||
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
|
_glfw.glx.EXT_framebuffer_sRGB = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_create_context"))
|
if (extensionSupportedGLX("GLX_ARB_create_context"))
|
||||||
{
|
{
|
||||||
@@ -398,25 +396,25 @@ GLFWbool _glfwInitGLX(void)
|
|||||||
getProcAddressGLX("glXCreateContextAttribsARB");
|
getProcAddressGLX("glXCreateContextAttribsARB");
|
||||||
|
|
||||||
if (_glfw.glx.CreateContextAttribsARB)
|
if (_glfw.glx.CreateContextAttribsARB)
|
||||||
_glfw.glx.ARB_create_context = GLFW_TRUE;
|
_glfw.glx.ARB_create_context = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
|
if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
|
||||||
_glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
|
_glfw.glx.ARB_create_context_robustness = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
|
if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
|
||||||
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
|
_glfw.glx.ARB_create_context_profile = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
|
||||||
_glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
|
_glfw.glx.EXT_create_context_es2_profile = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
|
if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
|
||||||
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
|
_glfw.glx.ARB_create_context_no_error = true;
|
||||||
|
|
||||||
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
|
||||||
_glfw.glx.ARB_context_flush_control = GLFW_TRUE;
|
_glfw.glx.ARB_context_flush_control = true;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate GLX
|
// Terminate GLX
|
||||||
@@ -442,7 +440,7 @@ void _glfwTerminateGLX(void)
|
|||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
bool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
@@ -457,7 +455,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"GLX: Failed to find a suitable GLXFBConfig");
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||||
@@ -468,7 +466,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
|
"GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,7 +476,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
|
"GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,7 +487,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
|
"GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +552,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
if (ctxconfig->noerror)
|
if (ctxconfig->noerror)
|
||||||
{
|
{
|
||||||
if (_glfw.glx.ARB_create_context_no_error)
|
if (_glfw.glx.ARB_create_context_no_error)
|
||||||
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
@@ -590,7 +588,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
||||||
ctxconfig->client == GLFW_OPENGL_API &&
|
ctxconfig->client == GLFW_OPENGL_API &&
|
||||||
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
||||||
ctxconfig->forward == GLFW_FALSE)
|
ctxconfig->forward == false)
|
||||||
{
|
{
|
||||||
window->context.glx.handle =
|
window->context.glx.handle =
|
||||||
createLegacyContextGLX(window, native, share);
|
createLegacyContextGLX(window, native, share);
|
||||||
@@ -608,7 +606,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
if (!window->context.glx.handle)
|
if (!window->context.glx.handle)
|
||||||
{
|
{
|
||||||
_glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
|
_glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.glx.window =
|
window->context.glx.window =
|
||||||
@@ -616,7 +614,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
if (!window->context.glx.window)
|
if (!window->context.glx.window)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentGLX;
|
window->context.makeCurrent = makeContextCurrentGLX;
|
||||||
@@ -626,14 +624,14 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressGLX;
|
window->context.getProcAddress = getProcAddressGLX;
|
||||||
window->context.destroy = destroyContextGLX;
|
window->context.destroy = destroyContextGLX;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setAttrib
|
#undef setAttrib
|
||||||
|
|
||||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||||
//
|
//
|
||||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
@@ -645,7 +643,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"GLX: Failed to find a suitable GLXFBConfig");
|
"GLX: Failed to find a suitable GLXFBConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
|
result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
|
||||||
@@ -653,14 +651,14 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"GLX: Failed to retrieve Visual for GLXFBConfig");
|
"GLX: Failed to retrieve Visual for GLXFBConfig");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*visual = result->visual;
|
*visual = result->visual;
|
||||||
*depth = result->depth;
|
*depth = result->depth;
|
||||||
|
|
||||||
XFree(result);
|
XFree(result);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -695,4 +693,3 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
|
|||||||
|
|
||||||
return window->context.glx.window;
|
return window->context.glx.window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
glfw/glx_context.h
vendored
36
glfw/glx_context.h
vendored
@@ -29,11 +29,11 @@
|
|||||||
#define GLX_RGBA_BIT 0x00000001
|
#define GLX_RGBA_BIT 0x00000001
|
||||||
#define GLX_WINDOW_BIT 0x00000001
|
#define GLX_WINDOW_BIT 0x00000001
|
||||||
#define GLX_DRAWABLE_TYPE 0x8010
|
#define GLX_DRAWABLE_TYPE 0x8010
|
||||||
#define GLX_RENDER_TYPE 0x8011
|
#define GLX_RENDER_TYPE 0x8011
|
||||||
#define GLX_RGBA_TYPE 0x8014
|
#define GLX_RGBA_TYPE 0x8014
|
||||||
#define GLX_DOUBLEBUFFER 5
|
#define GLX_DOUBLEBUFFER 5
|
||||||
#define GLX_STEREO 6
|
#define GLX_STEREO 6
|
||||||
#define GLX_AUX_BUFFERS 7
|
#define GLX_AUX_BUFFERS 7
|
||||||
#define GLX_RED_SIZE 8
|
#define GLX_RED_SIZE 8
|
||||||
#define GLX_GREEN_SIZE 9
|
#define GLX_GREEN_SIZE 9
|
||||||
#define GLX_BLUE_SIZE 10
|
#define GLX_BLUE_SIZE 10
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
#define GLX_STENCIL_SIZE 13
|
#define GLX_STENCIL_SIZE 13
|
||||||
#define GLX_ACCUM_RED_SIZE 14
|
#define GLX_ACCUM_RED_SIZE 14
|
||||||
#define GLX_ACCUM_GREEN_SIZE 15
|
#define GLX_ACCUM_GREEN_SIZE 15
|
||||||
#define GLX_ACCUM_BLUE_SIZE 16
|
#define GLX_ACCUM_BLUE_SIZE 16
|
||||||
#define GLX_ACCUM_ALPHA_SIZE 17
|
#define GLX_ACCUM_ALPHA_SIZE 17
|
||||||
#define GLX_SAMPLES 0x186a1
|
#define GLX_SAMPLES 0x186a1
|
||||||
#define GLX_VISUAL_ID 0x800b
|
#define GLX_VISUAL_ID 0x800b
|
||||||
@@ -153,28 +153,28 @@ typedef struct _GLFWlibraryGLX
|
|||||||
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
||||||
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
GLFWbool SGI_swap_control;
|
bool SGI_swap_control;
|
||||||
GLFWbool EXT_swap_control;
|
bool EXT_swap_control;
|
||||||
GLFWbool MESA_swap_control;
|
bool MESA_swap_control;
|
||||||
GLFWbool ARB_multisample;
|
bool ARB_multisample;
|
||||||
GLFWbool ARB_framebuffer_sRGB;
|
bool ARB_framebuffer_sRGB;
|
||||||
GLFWbool EXT_framebuffer_sRGB;
|
bool EXT_framebuffer_sRGB;
|
||||||
GLFWbool ARB_create_context;
|
bool ARB_create_context;
|
||||||
GLFWbool ARB_create_context_profile;
|
bool ARB_create_context_profile;
|
||||||
GLFWbool ARB_create_context_robustness;
|
bool ARB_create_context_robustness;
|
||||||
GLFWbool EXT_create_context_es2_profile;
|
bool EXT_create_context_es2_profile;
|
||||||
GLFWbool ARB_create_context_no_error;
|
bool ARB_create_context_no_error;
|
||||||
GLFWbool ARB_context_flush_control;
|
bool ARB_context_flush_control;
|
||||||
|
|
||||||
} _GLFWlibraryGLX;
|
} _GLFWlibraryGLX;
|
||||||
|
|
||||||
GLFWbool _glfwInitGLX(void);
|
bool _glfwInitGLX(void);
|
||||||
void _glfwTerminateGLX(void);
|
void _glfwTerminateGLX(void);
|
||||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
bool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
||||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth);
|
Visual** visual, int* depth);
|
||||||
|
|||||||
72
glfw/ibus_glfw.c
vendored
72
glfw/ibus_glfw.c
vendored
@@ -50,13 +50,13 @@ enum Capabilities {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static inline GLFWbool
|
static inline bool
|
||||||
test_env_var(const char *name, const char *val) {
|
test_env_var(const char *name, const char *val) {
|
||||||
const char *q = getenv(name);
|
const char *q = getenv(name);
|
||||||
return (q && strcmp(q, val) == 0) ? GLFW_TRUE : GLFW_FALSE;
|
return (q && strcmp(q, val) == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline GLFWbool
|
static inline size_t
|
||||||
MIN(size_t a, size_t b) {
|
MIN(size_t a, size_t b) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
@@ -193,39 +193,39 @@ get_ibus_address_file_name(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline GLFWbool
|
static inline bool
|
||||||
read_ibus_address(_GLFWIBUSData *ibus) {
|
read_ibus_address(_GLFWIBUSData *ibus) {
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
struct stat s;
|
struct stat s;
|
||||||
FILE *addr_file = fopen(ibus->address_file_name, "r");
|
FILE *addr_file = fopen(ibus->address_file_name, "r");
|
||||||
if (!addr_file) {
|
if (!addr_file) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to open IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno));
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to open IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
int stat_result = fstat(fileno(addr_file), &s);
|
int stat_result = fstat(fileno(addr_file), &s);
|
||||||
GLFWbool found = GLFW_FALSE;
|
bool found = false;
|
||||||
while (fgets(buf, sizeof(buf), addr_file)) {
|
while (fgets(buf, sizeof(buf), addr_file)) {
|
||||||
if (strncmp(buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
|
if (strncmp(buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
|
||||||
size_t sz = strlen(buf);
|
size_t sz = strlen(buf);
|
||||||
if (buf[sz-1] == '\n') buf[sz-1] = 0;
|
if (buf[sz-1] == '\n') buf[sz-1] = 0;
|
||||||
if (buf[sz-2] == '\r') buf[sz-2] = 0;
|
if (buf[sz-2] == '\r') buf[sz-2] = 0;
|
||||||
found = GLFW_TRUE;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(addr_file); addr_file = NULL;
|
fclose(addr_file); addr_file = NULL;
|
||||||
if (stat_result != 0) {
|
if (stat_result != 0) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to stat IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno));
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to stat IBUS address file: %s with error: %s", ibus->address_file_name, strerror(errno));
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
ibus->address_file_mtime = s.st_mtime;
|
ibus->address_file_mtime = s.st_mtime;
|
||||||
if (found) {
|
if (found) {
|
||||||
free((void*)ibus->address);
|
free((void*)ibus->address);
|
||||||
ibus->address = _glfw_strdup(buf + sizeof("IBUS_ADDRESS=") - 1);
|
ibus->address = _glfw_strdup(buf + sizeof("IBUS_ADDRESS=") - 1);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Could not find IBUS_ADDRESS in %s", ibus->address_file_name);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Could not find IBUS_ADDRESS in %s", ibus->address_file_name);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -245,35 +245,35 @@ input_context_created(DBusMessage *msg, const char* errmsg, void *data) {
|
|||||||
dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL);
|
dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL);
|
||||||
enum Capabilities caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
|
enum Capabilities caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
|
||||||
if (!glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return;
|
if (!glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return;
|
||||||
ibus->ok = GLFW_TRUE;
|
ibus->ok = true;
|
||||||
glfw_ibus_set_focused(ibus, GLFW_FALSE);
|
glfw_ibus_set_focused(ibus, false);
|
||||||
glfw_ibus_set_cursor_geometry(ibus, 0, 0, 0, 0);
|
glfw_ibus_set_cursor_geometry(ibus, 0, 0, 0, 0);
|
||||||
debug("Connected to IBUS daemon for IME input management\n");
|
debug("Connected to IBUS daemon for IME input management\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
setup_connection(_GLFWIBUSData *ibus) {
|
setup_connection(_GLFWIBUSData *ibus) {
|
||||||
const char *client_name = "GLFW_Application";
|
const char *client_name = "GLFW_Application";
|
||||||
const char *address_file_name = get_ibus_address_file_name();
|
const char *address_file_name = get_ibus_address_file_name();
|
||||||
ibus->ok = GLFW_FALSE;
|
ibus->ok = false;
|
||||||
if (!address_file_name) return GLFW_FALSE;
|
if (!address_file_name) return false;
|
||||||
free((void*)ibus->address_file_name);
|
free((void*)ibus->address_file_name);
|
||||||
ibus->address_file_name = _glfw_strdup(address_file_name);
|
ibus->address_file_name = _glfw_strdup(address_file_name);
|
||||||
if (!read_ibus_address(ibus)) return GLFW_FALSE;
|
if (!read_ibus_address(ibus)) return false;
|
||||||
if (ibus->conn) {
|
if (ibus->conn) {
|
||||||
glfw_dbus_close_connection(ibus->conn);
|
glfw_dbus_close_connection(ibus->conn);
|
||||||
ibus->conn = NULL;
|
ibus->conn = NULL;
|
||||||
}
|
}
|
||||||
debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address);
|
debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address);
|
||||||
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error", "ibus", GLFW_FALSE);
|
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error", "ibus", false);
|
||||||
if (!ibus->conn) return GLFW_FALSE;
|
if (!ibus->conn) return false;
|
||||||
free((void*)ibus->input_ctx_path); ibus->input_ctx_path = NULL;
|
free((void*)ibus->input_ctx_path); ibus->input_ctx_path = NULL;
|
||||||
if (!glfw_dbus_call_method_with_reply(
|
if (!glfw_dbus_call_method_with_reply(
|
||||||
ibus->conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext", DBUS_TIMEOUT_USE_DEFAULT, input_context_created, ibus,
|
ibus->conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext", DBUS_TIMEOUT_USE_DEFAULT, input_context_created, ibus,
|
||||||
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID)) {
|
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID)) {
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -281,7 +281,7 @@ void
|
|||||||
glfw_connect_to_ibus(_GLFWIBUSData *ibus) {
|
glfw_connect_to_ibus(_GLFWIBUSData *ibus) {
|
||||||
if (ibus->inited) return;
|
if (ibus->inited) return;
|
||||||
if (!test_env_var("GLFW_IM_MODULE", "ibus")) return;
|
if (!test_env_var("GLFW_IM_MODULE", "ibus")) return;
|
||||||
ibus->inited = GLFW_TRUE;
|
ibus->inited = true;
|
||||||
setup_connection(ibus);
|
setup_connection(ibus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,21 +297,21 @@ glfw_ibus_terminate(_GLFWIBUSData *ibus) {
|
|||||||
F(address_file_name);
|
F(address_file_name);
|
||||||
#undef F
|
#undef F
|
||||||
|
|
||||||
ibus->ok = GLFW_FALSE;
|
ibus->ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool
|
static bool
|
||||||
check_connection(_GLFWIBUSData *ibus) {
|
check_connection(_GLFWIBUSData *ibus) {
|
||||||
if (!ibus->inited) return GLFW_FALSE;
|
if (!ibus->inited) return false;
|
||||||
if (ibus->conn && dbus_connection_get_is_connected(ibus->conn)) {
|
if (ibus->conn && dbus_connection_get_is_connected(ibus->conn)) {
|
||||||
return ibus->ok;
|
return ibus->ok;
|
||||||
}
|
}
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if (stat(ibus->address_file_name, &s) != 0 || s.st_mtime != ibus->address_file_mtime) {
|
if (stat(ibus->address_file_name, &s) != 0 || s.st_mtime != ibus->address_file_mtime) {
|
||||||
if (!read_ibus_address(ibus)) return GLFW_FALSE;
|
if (!read_ibus_address(ibus)) return false;
|
||||||
setup_connection(ibus);
|
setup_connection(ibus);
|
||||||
}
|
}
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ simple_message(_GLFWIBUSData *ibus, const char *method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused) {
|
glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused) {
|
||||||
simple_message(ibus, focused ? "FocusIn" : "FocusOut");
|
simple_message(ibus, focused ? "FocusIn" : "FocusOut");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,24 +394,24 @@ void
|
|||||||
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
|
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
|
||||||
uint32_t handled = 0;
|
uint32_t handled = 0;
|
||||||
KeyEvent *ev = (KeyEvent*)data;
|
KeyEvent *ev = (KeyEvent*)data;
|
||||||
GLFWbool is_release = ev->action == GLFW_RELEASE;
|
bool is_release = ev->action == GLFW_RELEASE;
|
||||||
GLFWbool failed = GLFW_FALSE;
|
bool failed = false;
|
||||||
if (errmsg) {
|
if (errmsg) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
|
||||||
failed = GLFW_TRUE;
|
failed = true;
|
||||||
} else {
|
} else {
|
||||||
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
|
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
|
||||||
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->keycode, is_release, handled);
|
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->keycode, is_release, handled);
|
||||||
}
|
}
|
||||||
glfw_xkb_key_from_ime(ev, handled ? GLFW_TRUE : GLFW_FALSE, failed);
|
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
|
||||||
free(ev);
|
free(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
|
ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
|
||||||
if (!check_connection(ibus)) return GLFW_FALSE;
|
if (!check_connection(ibus)) return false;
|
||||||
KeyEvent *ev = malloc(sizeof(KeyEvent));
|
KeyEvent *ev = malloc(sizeof(KeyEvent));
|
||||||
if (!ev) return GLFW_FALSE;
|
if (!ev) return false;
|
||||||
memcpy(ev, ev_, sizeof(KeyEvent));
|
memcpy(ev, ev_, sizeof(KeyEvent));
|
||||||
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
|
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
|
||||||
if (!glfw_dbus_call_method_with_reply(
|
if (!glfw_dbus_call_method_with_reply(
|
||||||
@@ -420,7 +420,7 @@ ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
|
|||||||
DBUS_TYPE_UINT32, &ev->ibus_sym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
|
DBUS_TYPE_UINT32, &ev->ibus_sym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
|
||||||
&state, DBUS_TYPE_INVALID)) {
|
&state, DBUS_TYPE_INVALID)) {
|
||||||
free(ev);
|
free(ev);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
6
glfw/ibus_glfw.h
vendored
6
glfw/ibus_glfw.h
vendored
@@ -31,7 +31,7 @@
|
|||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GLFWbool ok, inited;
|
bool ok, inited;
|
||||||
time_t address_file_mtime;
|
time_t address_file_mtime;
|
||||||
DBusConnection *conn;
|
DBusConnection *conn;
|
||||||
const char *input_ctx_path, *address_file_name, *address;
|
const char *input_ctx_path, *address_file_name, *address;
|
||||||
@@ -49,7 +49,7 @@ typedef struct {
|
|||||||
|
|
||||||
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
|
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
|
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused);
|
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused);
|
||||||
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
|
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
|
||||||
GLFWbool ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus);
|
bool ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);
|
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);
|
||||||
|
|||||||
71
glfw/init.c
vendored
71
glfw/init.c
vendored
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
// Global state shared between compilation units of GLFW
|
// Global state shared between compilation units of GLFW
|
||||||
//
|
//
|
||||||
_GLFWlibrary _glfw = { GLFW_FALSE };
|
_GLFWlibrary _glfw = { false };
|
||||||
|
|
||||||
// These are outside of _glfw so they can be used before initialization and
|
// These are outside of _glfw so they can be used before initialization and
|
||||||
// after termination
|
// after termination
|
||||||
@@ -50,12 +50,12 @@ static _GLFWerror _glfwMainThreadError;
|
|||||||
static GLFWerrorfun _glfwErrorCallback;
|
static GLFWerrorfun _glfwErrorCallback;
|
||||||
static _GLFWinitconfig _glfwInitHints =
|
static _GLFWinitconfig _glfwInitHints =
|
||||||
{
|
{
|
||||||
GLFW_TRUE, // hat buttons
|
true, // hat buttons
|
||||||
GLFW_FALSE, // debug keyboard
|
false, // debug keyboard
|
||||||
GLFW_TRUE, // enable joystick
|
true, // enable joystick
|
||||||
{
|
{
|
||||||
GLFW_TRUE, // macOS menu bar
|
true, // macOS menu bar
|
||||||
GLFW_TRUE // macOS bundle chdir
|
true // macOS bundle chdir
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ static void terminate(void)
|
|||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
_glfwPlatformTerminate();
|
_glfwPlatformTerminate();
|
||||||
|
|
||||||
_glfw.initialized = GLFW_FALSE;
|
_glfw.initialized = false;
|
||||||
|
|
||||||
while (_glfw.errorListHead)
|
while (_glfw.errorListHead)
|
||||||
{
|
{
|
||||||
@@ -193,6 +193,20 @@ void _glfwInputError(int code, const char* format, ...)
|
|||||||
_glfwErrorCallback(code, description);
|
_glfwErrorCallback(code, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_glfwDebug(const char *format, ...) {
|
||||||
|
if (format)
|
||||||
|
{
|
||||||
|
va_list vl;
|
||||||
|
|
||||||
|
fprintf(stderr, "[%.4f] ", glfwGetTime());
|
||||||
|
va_start(vl, format);
|
||||||
|
vfprintf(stderr, format, vl);
|
||||||
|
va_end(vl);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
@@ -201,7 +215,7 @@ void _glfwInputError(int code, const char* format, ...)
|
|||||||
GLFWAPI int glfwInit(void)
|
GLFWAPI int glfwInit(void)
|
||||||
{
|
{
|
||||||
if (_glfw.initialized)
|
if (_glfw.initialized)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
_glfw.hints.init = _glfwInitHints;
|
_glfw.hints.init = _glfwInitHints;
|
||||||
@@ -209,7 +223,7 @@ GLFWAPI int glfwInit(void)
|
|||||||
if (!_glfwPlatformInit())
|
if (!_glfwPlatformInit())
|
||||||
{
|
{
|
||||||
terminate();
|
terminate();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
||||||
@@ -217,12 +231,12 @@ GLFWAPI int glfwInit(void)
|
|||||||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
||||||
{
|
{
|
||||||
terminate();
|
terminate();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||||
|
|
||||||
_glfw.initialized = GLFW_TRUE;
|
_glfw.initialized = true;
|
||||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||||
|
|
||||||
glfwDefaultWindowHints();
|
glfwDefaultWindowHints();
|
||||||
@@ -235,12 +249,12 @@ GLFWAPI int glfwInit(void)
|
|||||||
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
|
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
|
||||||
{
|
{
|
||||||
terminate();
|
terminate();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwTerminate(void)
|
GLFWAPI void glfwTerminate(void)
|
||||||
@@ -320,3 +334,34 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
|||||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
_GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
|
||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *data)
|
||||||
|
{
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformRunMainLoop(callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwRequestTickCallback(void) {
|
||||||
|
_glfwPlatformRequestTickCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwStopMainLoop(void) {
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
_glfwPlatformStopMainLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI unsigned long long glfwAddTimer(
|
||||||
|
double interval, bool repeats, GLFWuserdatafun callback,
|
||||||
|
void *callback_data, GLFWuserdatafun free_callback)
|
||||||
|
{
|
||||||
|
return _glfwPlatformAddTimer(interval, repeats, callback, callback_data, free_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
||||||
|
_glfwPlatformUpdateTimer(timer_id, interval, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwRemoveTimer(unsigned long long timer_id) {
|
||||||
|
_glfwPlatformRemoveTimer(timer_id);
|
||||||
|
}
|
||||||
|
|||||||
93
glfw/input.c
vendored
93
glfw/input.c
vendored
@@ -58,17 +58,17 @@ static _GLFWmapping* findMapping(const char* guid)
|
|||||||
|
|
||||||
// Checks whether a gamepad mapping element is present in the hardware
|
// Checks whether a gamepad mapping element is present in the hardware
|
||||||
//
|
//
|
||||||
static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
|
static bool isValidElementForJoystick(const _GLFWmapelement* e,
|
||||||
const _GLFWjoystick* js)
|
const _GLFWjoystick* js)
|
||||||
{
|
{
|
||||||
if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
|
if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
|
else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
|
else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds a mapping based on joystick GUID and verifies element indices
|
// Finds a mapping based on joystick GUID and verifies element indices
|
||||||
@@ -110,7 +110,7 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
|
|||||||
|
|
||||||
// Parses an SDL_GameControllerDB line and adds it to the mapping list
|
// Parses an SDL_GameControllerDB line and adds it to the mapping list
|
||||||
//
|
//
|
||||||
static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
static bool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||||
{
|
{
|
||||||
const char* c = string;
|
const char* c = string;
|
||||||
size_t i, length;
|
size_t i, length;
|
||||||
@@ -148,7 +148,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
if (length != 32 || c[length] != ',')
|
if (length != 32 || c[length] != ',')
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(mapping->guid, c, length);
|
memcpy(mapping->guid, c, length);
|
||||||
@@ -158,7 +158,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
if (length >= sizeof(mapping->name) || c[length] != ',')
|
if (length >= sizeof(mapping->name) || c[length] != ',')
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(mapping->name, c, length);
|
memcpy(mapping->name, c, length);
|
||||||
@@ -168,7 +168,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
{
|
{
|
||||||
// TODO: Implement output modifiers
|
// TODO: Implement output modifiers
|
||||||
if (*c == '+' || *c == '-')
|
if (*c == '+' || *c == '-')
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
|
for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
|
||||||
{
|
{
|
||||||
@@ -229,7 +229,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
{
|
{
|
||||||
length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
|
length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
|
||||||
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
|
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -246,7 +246,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfwPlatformUpdateGamepadGUID(mapping->guid);
|
_glfwPlatformUpdateGamepadGUID(mapping->guid);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,13 +260,13 @@ void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action,
|
|||||||
{
|
{
|
||||||
if (key >= 0 && key <= GLFW_KEY_LAST)
|
if (key >= 0 && key <= GLFW_KEY_LAST)
|
||||||
{
|
{
|
||||||
GLFWbool repeated = GLFW_FALSE;
|
bool repeated = false;
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
||||||
repeated = GLFW_TRUE;
|
repeated = true;
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && window->stickyKeys)
|
if (action == GLFW_RELEASE && window->stickyKeys)
|
||||||
window->keys[key] = _GLFW_STICK;
|
window->keys[key] = _GLFW_STICK;
|
||||||
@@ -312,7 +312,7 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notifies shared code of a cursor motion event
|
// Notifies shared code of a cursor motion event
|
||||||
// The position is specified in client-area relative screen coordinates
|
// The position is specified in content area relative screen coordinates
|
||||||
//
|
//
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
@@ -328,7 +328,7 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
|||||||
|
|
||||||
// Notifies shared code of a cursor enter/leave event
|
// Notifies shared code of a cursor enter/leave event
|
||||||
//
|
//
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
|
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered)
|
||||||
{
|
{
|
||||||
if (window->callbacks.cursorEnter)
|
if (window->callbacks.cursorEnter)
|
||||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||||
@@ -406,7 +406,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
js = _glfw.joysticks + jid;
|
js = _glfw.joysticks + jid;
|
||||||
js->present = GLFW_TRUE;
|
js->present = true;
|
||||||
js->name = _glfw_strdup(name);
|
js->name = _glfw_strdup(name);
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
js->axes = calloc(axisCount, sizeof(float));
|
||||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||||
@@ -415,7 +415,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||||||
js->buttonCount = buttonCount;
|
js->buttonCount = buttonCount;
|
||||||
js->hatCount = hatCount;
|
js->hatCount = hatCount;
|
||||||
|
|
||||||
strcpy(js->guid, guid);
|
strncpy(js->guid, guid, sizeof(js->guid) - 1);
|
||||||
js->mapping = findValidMapping(js);
|
js->mapping = findValidMapping(js);
|
||||||
|
|
||||||
return js;
|
return js;
|
||||||
@@ -488,6 +488,7 @@ const char* _glfwGetKeyName(int key)
|
|||||||
case GLFW_KEY_WORLD_1: return "WORLD 1";
|
case GLFW_KEY_WORLD_1: return "WORLD 1";
|
||||||
case GLFW_KEY_WORLD_2: return "WORLD 2";
|
case GLFW_KEY_WORLD_2: return "WORLD 2";
|
||||||
case GLFW_KEY_PLUS: return "PLUS";
|
case GLFW_KEY_PLUS: return "PLUS";
|
||||||
|
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
|
||||||
|
|
||||||
// Function keys
|
// Function keys
|
||||||
case GLFW_KEY_ESCAPE: return "ESCAPE";
|
case GLFW_KEY_ESCAPE: return "ESCAPE";
|
||||||
@@ -565,6 +566,15 @@ const char* _glfwGetKeyName(int key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Center the cursor in the middle of the content area of the specified window
|
||||||
|
//
|
||||||
|
void _glfwCenterCursorInContentArea(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -623,7 +633,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
}
|
}
|
||||||
else if (mode == GLFW_STICKY_KEYS)
|
else if (mode == GLFW_STICKY_KEYS)
|
||||||
{
|
{
|
||||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
value = value ? true : false;
|
||||||
if (window->stickyKeys == value)
|
if (window->stickyKeys == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -643,7 +653,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
}
|
}
|
||||||
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
|
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
|
||||||
{
|
{
|
||||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
value = value ? true : false;
|
||||||
if (window->stickyMouseButtons == value)
|
if (window->stickyMouseButtons == value)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -662,7 +672,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
window->stickyMouseButtons = value;
|
window->stickyMouseButtons = value;
|
||||||
}
|
}
|
||||||
else if (mode == GLFW_LOCK_KEY_MODS)
|
else if (mode == GLFW_LOCK_KEY_MODS)
|
||||||
window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
|
window->lockKeyMods = value ? true : false;
|
||||||
else
|
else
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
}
|
}
|
||||||
@@ -822,20 +832,15 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot,
|
|||||||
return (GLFWcursor*) cursor;
|
return (GLFWcursor*) cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape)
|
||||||
{
|
{
|
||||||
_GLFWcursor* cursor;
|
_GLFWcursor* cursor;
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
if (shape != GLFW_ARROW_CURSOR &&
|
if (shape >= GLFW_INVALID_CURSOR)
|
||||||
shape != GLFW_IBEAM_CURSOR &&
|
|
||||||
shape != GLFW_CROSSHAIR_CURSOR &&
|
|
||||||
shape != GLFW_HAND_CURSOR &&
|
|
||||||
shape != GLFW_HRESIZE_CURSOR &&
|
|
||||||
shape != GLFW_VRESIZE_CURSOR)
|
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor: %d", shape);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,7 +920,7 @@ GLFWAPI void glfwUpdateIMEState(GLFWwindow* handle, int which, int a, int b, int
|
|||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) || defined(_GLFW_COCOA)
|
||||||
_glfwPlatformUpdateIMEState(window, which, a, b, c, d);
|
_glfwPlatformUpdateIMEState(window, which, a, b, c, d);
|
||||||
#else
|
#else
|
||||||
(void)window; (void)which; (void)a; (void)b; (void)c; (void)d;
|
(void)window; (void)which; (void)a; (void)b; (void)c; (void)d;
|
||||||
@@ -983,17 +988,17 @@ GLFWAPI int glfwJoystickPresent(int jid)
|
|||||||
assert(jid >= GLFW_JOYSTICK_1);
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
js = _glfw.joysticks + jid;
|
js = _glfw.joysticks + jid;
|
||||||
if (!js->present)
|
if (!js->present)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||||
}
|
}
|
||||||
@@ -1185,7 +1190,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
|||||||
|
|
||||||
assert(string != NULL);
|
assert(string != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
while (*c)
|
while (*c)
|
||||||
{
|
{
|
||||||
@@ -1235,7 +1240,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
|||||||
js->mapping = findValidMapping(js);
|
js->mapping = findValidMapping(js);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwJoystickIsGamepad(int jid)
|
GLFWAPI int glfwJoystickIsGamepad(int jid)
|
||||||
@@ -1245,20 +1250,20 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
|
|||||||
assert(jid >= GLFW_JOYSTICK_1);
|
assert(jid >= GLFW_JOYSTICK_1);
|
||||||
assert(jid <= GLFW_JOYSTICK_LAST);
|
assert(jid <= GLFW_JOYSTICK_LAST);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
js = _glfw.joysticks + jid;
|
js = _glfw.joysticks + jid;
|
||||||
if (!js->present)
|
if (!js->present)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
return js->mapping != NULL;
|
return js->mapping != NULL;
|
||||||
}
|
}
|
||||||
@@ -1302,23 +1307,23 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||||||
|
|
||||||
memset(state, 0, sizeof(GLFWgamepadstate));
|
memset(state, 0, sizeof(GLFWgamepadstate));
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
js = _glfw.joysticks + jid;
|
js = _glfw.joysticks + jid;
|
||||||
if (!js->present)
|
if (!js->present)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
|
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (!js->mapping)
|
if (!js->mapping)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
||||||
{
|
{
|
||||||
@@ -1359,7 +1364,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||||||
state->axes[i] = (float) js->buttons[e->index];
|
state->axes[i] = (float) js->buttons[e->index];
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||||
|
|||||||
156
glfw/internal.h
vendored
156
glfw/internal.h
vendored
@@ -60,7 +60,6 @@
|
|||||||
|
|
||||||
#define _GLFW_MESSAGE_SIZE 1024
|
#define _GLFW_MESSAGE_SIZE 1024
|
||||||
|
|
||||||
typedef int GLFWbool;
|
|
||||||
typedef unsigned long long GLFWid;
|
typedef unsigned long long GLFWid;
|
||||||
|
|
||||||
typedef struct _GLFWerror _GLFWerror;
|
typedef struct _GLFWerror _GLFWerror;
|
||||||
@@ -87,8 +86,8 @@ typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
|||||||
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||||
|
|
||||||
#define GL_VERSION 0x1f02
|
#define GL_VERSION 0x1f02
|
||||||
#define GL_NONE 0
|
#define GL_NONE 0
|
||||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||||
#define GL_UNSIGNED_BYTE 0x1401
|
#define GL_UNSIGNED_BYTE 0x1401
|
||||||
#define GL_EXTENSIONS 0x1f03
|
#define GL_EXTENSIONS 0x1f03
|
||||||
#define GL_NUM_EXTENSIONS 0x821d
|
#define GL_NUM_EXTENSIONS 0x821d
|
||||||
@@ -105,7 +104,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
|||||||
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
|
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
|
||||||
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
|
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
|
||||||
|
|
||||||
typedef int GLint;
|
typedef int GLint;
|
||||||
typedef unsigned int GLuint;
|
typedef unsigned int GLuint;
|
||||||
typedef unsigned int GLenum;
|
typedef unsigned int GLenum;
|
||||||
typedef unsigned int GLbitfield;
|
typedef unsigned int GLbitfield;
|
||||||
@@ -196,6 +195,13 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
#error "No supported window creation API selected"
|
#error "No supported window creation API selected"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define remove_i_from_array(array, i, count) { \
|
||||||
|
(count)--; \
|
||||||
|
if ((i) < (count)) { \
|
||||||
|
memmove((array) + (i), (array) + (i) + 1, sizeof((array)[0]) * ((count) - (i))); \
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
// Constructs a version number string from the public header macros
|
// Constructs a version number string from the public header macros
|
||||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||||
@@ -241,12 +247,12 @@ struct _GLFWerror
|
|||||||
//
|
//
|
||||||
struct _GLFWinitconfig
|
struct _GLFWinitconfig
|
||||||
{
|
{
|
||||||
GLFWbool hatButtons;
|
bool hatButtons;
|
||||||
GLFWbool debugKeyboard;
|
bool debugKeyboard;
|
||||||
GLFWbool enableJoysticks;
|
bool enableJoysticks;
|
||||||
struct {
|
struct {
|
||||||
GLFWbool menubar;
|
bool menubar;
|
||||||
GLFWbool chdir;
|
bool chdir;
|
||||||
} ns;
|
} ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -261,18 +267,18 @@ struct _GLFWwndconfig
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
const char* title;
|
const char* title;
|
||||||
GLFWbool resizable;
|
bool resizable;
|
||||||
GLFWbool visible;
|
bool visible;
|
||||||
GLFWbool decorated;
|
bool decorated;
|
||||||
GLFWbool focused;
|
bool focused;
|
||||||
GLFWbool autoIconify;
|
bool autoIconify;
|
||||||
GLFWbool floating;
|
bool floating;
|
||||||
GLFWbool maximized;
|
bool maximized;
|
||||||
GLFWbool centerCursor;
|
bool centerCursor;
|
||||||
GLFWbool focusOnShow;
|
bool focusOnShow;
|
||||||
GLFWbool scaleToMonitor;
|
bool scaleToMonitor;
|
||||||
struct {
|
struct {
|
||||||
GLFWbool retina;
|
bool retina;
|
||||||
char frameName[256];
|
char frameName[256];
|
||||||
} ns;
|
} ns;
|
||||||
struct {
|
struct {
|
||||||
@@ -296,15 +302,15 @@ struct _GLFWctxconfig
|
|||||||
int source;
|
int source;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
GLFWbool forward;
|
bool forward;
|
||||||
GLFWbool debug;
|
bool debug;
|
||||||
GLFWbool noerror;
|
bool noerror;
|
||||||
int profile;
|
int profile;
|
||||||
int robustness;
|
int robustness;
|
||||||
int release;
|
int release;
|
||||||
_GLFWwindow* share;
|
_GLFWwindow* share;
|
||||||
struct {
|
struct {
|
||||||
GLFWbool offline;
|
bool offline;
|
||||||
} nsgl;
|
} nsgl;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -329,11 +335,11 @@ struct _GLFWfbconfig
|
|||||||
int accumBlueBits;
|
int accumBlueBits;
|
||||||
int accumAlphaBits;
|
int accumAlphaBits;
|
||||||
int auxBuffers;
|
int auxBuffers;
|
||||||
GLFWbool stereo;
|
bool stereo;
|
||||||
int samples;
|
int samples;
|
||||||
GLFWbool sRGB;
|
bool sRGB;
|
||||||
GLFWbool doublebuffer;
|
bool doublebuffer;
|
||||||
GLFWbool transparent;
|
bool transparent;
|
||||||
uintptr_t handle;
|
uintptr_t handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -344,7 +350,7 @@ struct _GLFWcontext
|
|||||||
int client;
|
int client;
|
||||||
int source;
|
int source;
|
||||||
int major, minor, revision;
|
int major, minor, revision;
|
||||||
GLFWbool forward, debug, noerror;
|
bool forward, debug, noerror;
|
||||||
int profile;
|
int profile;
|
||||||
int robustness;
|
int robustness;
|
||||||
int release;
|
int release;
|
||||||
@@ -375,12 +381,12 @@ struct _GLFWwindow
|
|||||||
struct _GLFWwindow* next;
|
struct _GLFWwindow* next;
|
||||||
|
|
||||||
// Window settings and state
|
// Window settings and state
|
||||||
GLFWbool resizable;
|
bool resizable;
|
||||||
GLFWbool decorated;
|
bool decorated;
|
||||||
GLFWbool autoIconify;
|
bool autoIconify;
|
||||||
GLFWbool floating;
|
bool floating;
|
||||||
GLFWbool focusOnShow;
|
bool focusOnShow;
|
||||||
GLFWbool shouldClose;
|
bool shouldClose;
|
||||||
void* userPointer;
|
void* userPointer;
|
||||||
GLFWid id;
|
GLFWid id;
|
||||||
GLFWvidmode videoMode;
|
GLFWvidmode videoMode;
|
||||||
@@ -391,9 +397,9 @@ struct _GLFWwindow
|
|||||||
int maxwidth, maxheight;
|
int maxwidth, maxheight;
|
||||||
int numer, denom;
|
int numer, denom;
|
||||||
|
|
||||||
GLFWbool stickyKeys;
|
bool stickyKeys;
|
||||||
GLFWbool stickyMouseButtons;
|
bool stickyMouseButtons;
|
||||||
GLFWbool lockKeyMods;
|
bool lockKeyMods;
|
||||||
int cursorMode;
|
int cursorMode;
|
||||||
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
||||||
char keys[GLFW_KEY_LAST + 1];
|
char keys[GLFW_KEY_LAST + 1];
|
||||||
@@ -408,6 +414,7 @@ struct _GLFWwindow
|
|||||||
GLFWwindowclosefun close;
|
GLFWwindowclosefun close;
|
||||||
GLFWwindowrefreshfun refresh;
|
GLFWwindowrefreshfun refresh;
|
||||||
GLFWwindowfocusfun focus;
|
GLFWwindowfocusfun focus;
|
||||||
|
GLFWwindowocclusionfun occlusion;
|
||||||
GLFWwindowiconifyfun iconify;
|
GLFWwindowiconifyfun iconify;
|
||||||
GLFWwindowmaximizefun maximize;
|
GLFWwindowmaximizefun maximize;
|
||||||
GLFWframebuffersizefun fbsize;
|
GLFWframebuffersizefun fbsize;
|
||||||
@@ -418,6 +425,7 @@ struct _GLFWwindow
|
|||||||
GLFWscrollfun scroll;
|
GLFWscrollfun scroll;
|
||||||
GLFWkeyboardfun keyboard;
|
GLFWkeyboardfun keyboard;
|
||||||
GLFWdropfun drop;
|
GLFWdropfun drop;
|
||||||
|
GLFWliveresizefun liveResize;
|
||||||
} callbacks;
|
} callbacks;
|
||||||
|
|
||||||
// This is defined in the window API's platform.h
|
// This is defined in the window API's platform.h
|
||||||
@@ -482,7 +490,7 @@ struct _GLFWmapping
|
|||||||
//
|
//
|
||||||
struct _GLFWjoystick
|
struct _GLFWjoystick
|
||||||
{
|
{
|
||||||
GLFWbool present;
|
bool present;
|
||||||
float* axes;
|
float* axes;
|
||||||
int axisCount;
|
int axisCount;
|
||||||
unsigned char* buttons;
|
unsigned char* buttons;
|
||||||
@@ -518,7 +526,7 @@ struct _GLFWmutex
|
|||||||
//
|
//
|
||||||
struct _GLFWlibrary
|
struct _GLFWlibrary
|
||||||
{
|
{
|
||||||
GLFWbool initialized;
|
bool initialized;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
_GLFWinitconfig init;
|
_GLFWinitconfig init;
|
||||||
@@ -551,23 +559,23 @@ struct _GLFWlibrary
|
|||||||
} timer;
|
} timer;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
char* extensions[2];
|
char* extensions[2];
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||||
#endif
|
#endif
|
||||||
GLFWbool KHR_surface;
|
bool KHR_surface;
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
GLFWbool KHR_win32_surface;
|
bool KHR_win32_surface;
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
GLFWbool MVK_macos_surface;
|
bool MVK_macos_surface;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
GLFWbool KHR_xlib_surface;
|
bool KHR_xlib_surface;
|
||||||
GLFWbool KHR_xcb_surface;
|
bool KHR_xcb_surface;
|
||||||
#elif defined(_GLFW_WAYLAND)
|
#elif defined(_GLFW_WAYLAND)
|
||||||
GLFWbool KHR_wayland_surface;
|
bool KHR_wayland_surface;
|
||||||
#endif
|
#endif
|
||||||
} vk;
|
} vk;
|
||||||
|
|
||||||
@@ -606,7 +614,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
|||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image, int xhot, int yhot, int count);
|
const GLFWimage* image, int xhot, int yhot, int count);
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape);
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||||
|
|
||||||
@@ -617,9 +625,10 @@ void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
|||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||||
float* xscale, float* yscale);
|
float* xscale, float* yscale);
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string);
|
void _glfwPlatformSetClipboardString(const char* string);
|
||||||
@@ -652,6 +661,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
int maxwidth, int maxheight);
|
int maxwidth, int maxheight);
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||||
|
void _glfwInputLiveResize(_GLFWwindow* window, bool started);
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
int* left, int* top,
|
int* left, int* top,
|
||||||
int* right, int* bottom);
|
int* right, int* bottom);
|
||||||
@@ -669,16 +679,18 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
|||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
||||||
int xpos, int ypos, int width, int height,
|
int xpos, int ypos, int width, int height,
|
||||||
int refreshRate);
|
int refreshRate);
|
||||||
|
bool _glfwPlatformToggleFullscreen(_GLFWwindow *w, unsigned int flags);
|
||||||
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
||||||
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowHovered(_GLFWwindow* window);
|
int _glfwPlatformWindowHovered(_GLFWwindow* window);
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
||||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled);
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled);
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled);
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
||||||
void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d);
|
void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int d);
|
||||||
|
|
||||||
@@ -696,12 +708,12 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
const VkAllocationCallbacks* allocator,
|
const VkAllocationCallbacks* allocator,
|
||||||
VkSurfaceKHR* surface);
|
VkSurfaceKHR* surface);
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
bool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||||
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
bool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
||||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
||||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
||||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
||||||
@@ -711,14 +723,15 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
|||||||
////// GLFW event API //////
|
////// GLFW event API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
|
void _glfwInputWindowFocus(_GLFWwindow* window, bool focused);
|
||||||
|
void _glfwInputWindowOcclusion(_GLFWwindow* window, bool occluded);
|
||||||
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
|
||||||
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||||
void _glfwInputWindowContentScale(_GLFWwindow* window,
|
void _glfwInputWindowContentScale(_GLFWwindow* window,
|
||||||
float xscale, float yscale);
|
float xscale, float yscale);
|
||||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
void _glfwInputWindowIconify(_GLFWwindow* window, bool iconified);
|
||||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
void _glfwInputWindowMaximize(_GLFWwindow* window, bool maximized);
|
||||||
void _glfwInputWindowDamage(_GLFWwindow* window);
|
void _glfwInputWindowDamage(_GLFWwindow* window);
|
||||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||||
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||||
@@ -727,7 +740,7 @@ void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action,
|
|||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
|
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
||||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
||||||
@@ -737,25 +750,33 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
|
|||||||
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
|
||||||
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
void _glfwInputError(int code, const char* format, ...)
|
void _glfwInputError(int code, const char* format, ...)
|
||||||
__attribute__((format(printf, 2, 3)));
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
void _glfwDebug(const char* format, ...)
|
||||||
|
__attribute__((format(printf, 1, 2)));
|
||||||
#else
|
#else
|
||||||
void _glfwInputError(int code, const char* format, ...);
|
void _glfwInputError(int code, const char* format, ...);
|
||||||
|
void _glfwDebug(const char* format, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_EVENT_LOOP
|
||||||
|
#define EVDBG(...) _glfwDebug(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define EVDBG(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
|
bool _glfwStringInExtensionString(const char* string, const char* extensions);
|
||||||
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||||
const _GLFWfbconfig* alternatives,
|
const _GLFWfbconfig* alternatives,
|
||||||
unsigned int count);
|
unsigned int count);
|
||||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig);
|
const _GLFWctxconfig* ctxconfig);
|
||||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||||
|
|
||||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||||
const GLFWvidmode* desired);
|
const GLFWvidmode* desired);
|
||||||
@@ -773,11 +794,18 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||||||
int hatCount);
|
int hatCount);
|
||||||
void _glfwFreeJoystick(_GLFWjoystick* js);
|
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||||
const char* _glfwGetKeyName(int key);
|
const char* _glfwGetKeyName(int key);
|
||||||
|
void _glfwCenterCursorInContentArea(_GLFWwindow* window);
|
||||||
|
|
||||||
GLFWbool _glfwInitVulkan(int mode);
|
bool _glfwInitVulkan(int mode);
|
||||||
void _glfwTerminateVulkan(void);
|
void _glfwTerminateVulkan(void);
|
||||||
const char* _glfwGetVulkanResultString(VkResult result);
|
const char* _glfwGetVulkanResultString(VkResult result);
|
||||||
_GLFWwindow* _glfwFocusedWindow();
|
_GLFWwindow* _glfwFocusedWindow(void);
|
||||||
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
||||||
|
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
|
||||||
|
void _glfwPlatformRequestTickCallback(void);
|
||||||
|
void _glfwPlatformStopMainLoop(void);
|
||||||
|
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
|
||||||
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
||||||
|
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source);
|
char* _glfw_strdup(const char* source);
|
||||||
|
|||||||
24
glfw/linux_joystick.c
vendored
24
glfw/linux_joystick.c
vendored
@@ -124,7 +124,7 @@ static void pollAbsState(_GLFWjoystick* js)
|
|||||||
|
|
||||||
// Attempt to open the specified joystick device
|
// Attempt to open the specified joystick device
|
||||||
//
|
//
|
||||||
static GLFWbool openJoystickDevice(const char* path)
|
static bool openJoystickDevice(const char* path)
|
||||||
{
|
{
|
||||||
int jid, code;
|
int jid, code;
|
||||||
char name[256] = "";
|
char name[256] = "";
|
||||||
@@ -142,12 +142,12 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
if (!_glfw.joysticks[jid].present)
|
if (!_glfw.joysticks[jid].present)
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||||
if (linjs.fd == -1)
|
if (linjs.fd == -1)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
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_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
||||||
@@ -158,14 +158,14 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
"Linux: Failed to query input device: %s",
|
"Linux: Failed to query input device: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
close(linjs.fd);
|
close(linjs.fd);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure this device supports the events expected of a joystick
|
// Ensure this device supports the events expected of a joystick
|
||||||
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||||
{
|
{
|
||||||
close(linjs.fd);
|
close(linjs.fd);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||||
@@ -225,7 +225,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
close(linjs.fd);
|
close(linjs.fd);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
|
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
|
||||||
@@ -234,7 +234,7 @@ static GLFWbool openJoystickDevice(const char* path)
|
|||||||
pollAbsState(js);
|
pollAbsState(js);
|
||||||
|
|
||||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef isBitSet
|
#undef isBitSet
|
||||||
@@ -264,7 +264,7 @@ static int compareJoysticks(const void* fp, const void* sp)
|
|||||||
|
|
||||||
// Initialize joystick interface
|
// Initialize joystick interface
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitJoysticksLinux(void)
|
bool _glfwInitJoysticksLinux(void)
|
||||||
{
|
{
|
||||||
DIR* dir;
|
DIR* dir;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@@ -286,7 +286,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir(dirname);
|
dir = opendir(dirname);
|
||||||
@@ -315,7 +315,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
|||||||
// Continue with no joysticks if enumeration fails
|
// Continue with no joysticks if enumeration fails
|
||||||
|
|
||||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all opened joystick handles
|
// Close all opened joystick handles
|
||||||
@@ -408,10 +408,10 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|||||||
if (e.type == EV_SYN)
|
if (e.type == EV_SYN)
|
||||||
{
|
{
|
||||||
if (e.code == SYN_DROPPED)
|
if (e.code == SYN_DROPPED)
|
||||||
_glfw.linjs.dropped = GLFW_TRUE;
|
_glfw.linjs.dropped = true;
|
||||||
else if (e.code == SYN_REPORT)
|
else if (e.code == SYN_REPORT)
|
||||||
{
|
{
|
||||||
_glfw.linjs.dropped = GLFW_FALSE;
|
_glfw.linjs.dropped = false;
|
||||||
pollAbsState(js);
|
pollAbsState(js);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
glfw/linux_joystick.h
vendored
4
glfw/linux_joystick.h
vendored
@@ -52,11 +52,11 @@ typedef struct _GLFWlibraryLinux
|
|||||||
int inotify;
|
int inotify;
|
||||||
int watch;
|
int watch;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
GLFWbool dropped;
|
bool dropped;
|
||||||
} _GLFWlibraryLinux;
|
} _GLFWlibraryLinux;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitJoysticksLinux(void);
|
bool _glfwInitJoysticksLinux(void);
|
||||||
void _glfwTerminateJoysticksLinux(void);
|
void _glfwTerminateJoysticksLinux(void);
|
||||||
void _glfwDetectJoystickConnectionLinux(void);
|
void _glfwDetectJoystickConnectionLinux(void);
|
||||||
|
|
||||||
|
|||||||
106
glfw/linux_notify.c
vendored
Normal file
106
glfw/linux_notify.c
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* linux_notify.c
|
||||||
|
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "linux_notify.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define NOTIFICATIONS_SERVICE "org.freedesktop.Notifications"
|
||||||
|
#define NOTIFICATIONS_PATH "/org/freedesktop/Notifications"
|
||||||
|
#define NOTIFICATIONS_IFACE "org.freedesktop.Notifications"
|
||||||
|
|
||||||
|
static notification_id_type notification_id = 0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
notification_id_type next_id;
|
||||||
|
GLFWDBusnotificationcreatedfun callback;
|
||||||
|
void *data;
|
||||||
|
} NotificationCreatedData;
|
||||||
|
|
||||||
|
static GLFWDBusnotificationactivatedfun activated_handler = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
glfw_dbus_set_user_notification_activated_handler(GLFWDBusnotificationactivatedfun handler) {
|
||||||
|
activated_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
notification_created(DBusMessage *msg, const char* errmsg, void *data) {
|
||||||
|
if (errmsg) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Notify: Failed to create notification error: %s", errmsg);
|
||||||
|
if (data) free(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t notification_id;
|
||||||
|
if (!glfw_dbus_get_args(msg, "Failed to get Notification uid", DBUS_TYPE_UINT32, ¬ification_id, DBUS_TYPE_INVALID)) return;
|
||||||
|
NotificationCreatedData *ncd = (NotificationCreatedData*)data;
|
||||||
|
if (ncd->callback) ncd->callback(ncd->next_id, notification_id, ncd->data);
|
||||||
|
if (data) free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusHandlerResult
|
||||||
|
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) {
|
||||||
|
(void)(user_data);
|
||||||
|
/* printf("session_bus message_handler invoked interface: %s member: %s\n", dbus_message_get_interface(msg), dbus_message_get_member(msg)); */
|
||||||
|
if (dbus_message_is_signal(msg, NOTIFICATIONS_IFACE, "ActionInvoked")) {
|
||||||
|
uint32_t notification_id;
|
||||||
|
const char *action;
|
||||||
|
if (glfw_dbus_get_args(msg, "Failed to get args from ActionInvoked notification signal",
|
||||||
|
DBUS_TYPE_UINT32, ¬ification_id, DBUS_TYPE_STRING, &action, DBUS_TYPE_INVALID)) {
|
||||||
|
if (activated_handler) {
|
||||||
|
activated_handler(notification_id, action);
|
||||||
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
notification_id_type
|
||||||
|
glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, const char* action_name, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *user_data) {
|
||||||
|
DBusConnection *session_bus = glfw_dbus_session_bus();
|
||||||
|
static DBusConnection *added_signal_match = NULL;
|
||||||
|
if (!session_bus) return 0;
|
||||||
|
if (added_signal_match != session_bus) {
|
||||||
|
dbus_bus_add_match(session_bus, "type='signal',interface='" NOTIFICATIONS_IFACE "',member='ActionInvoked'", NULL);
|
||||||
|
dbus_connection_add_filter(session_bus, message_handler, NULL, NULL);
|
||||||
|
added_signal_match = session_bus;
|
||||||
|
}
|
||||||
|
NotificationCreatedData *data = malloc(sizeof(NotificationCreatedData));
|
||||||
|
if (!data) return 0;
|
||||||
|
data->next_id = ++notification_id;
|
||||||
|
data->callback = callback; data->data = user_data;
|
||||||
|
if (!data->next_id) data->next_id = ++notification_id;
|
||||||
|
uint32_t replaces_id = 0;
|
||||||
|
|
||||||
|
DBusMessage *msg = dbus_message_new_method_call(NOTIFICATIONS_SERVICE, NOTIFICATIONS_PATH, NOTIFICATIONS_IFACE, "Notify");
|
||||||
|
if (!msg) { free(data); return 0; }
|
||||||
|
DBusMessageIter args, array;
|
||||||
|
dbus_message_iter_init_append(msg, &args);
|
||||||
|
#define OOMMSG { free(data); data = NULL; dbus_message_unref(msg); _glfwInputError(GLFW_PLATFORM_ERROR, "%s", "Out of memory allocating DBUS message for notification\n"); return 0; }
|
||||||
|
#define APPEND(type, val) { if (!dbus_message_iter_append_basic(&args, type, val)) OOMMSG }
|
||||||
|
APPEND(DBUS_TYPE_STRING, &app_name)
|
||||||
|
APPEND(DBUS_TYPE_UINT32, &replaces_id)
|
||||||
|
APPEND(DBUS_TYPE_STRING, &icon)
|
||||||
|
APPEND(DBUS_TYPE_STRING, &summary)
|
||||||
|
APPEND(DBUS_TYPE_STRING, &body)
|
||||||
|
if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &array)) OOMMSG;
|
||||||
|
if (action_name) {
|
||||||
|
static const char* default_action = "default";
|
||||||
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &default_action);
|
||||||
|
dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &action_name);
|
||||||
|
}
|
||||||
|
if (!dbus_message_iter_close_container(&args, &array)) OOMMSG;
|
||||||
|
if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "{sv}", &array)) OOMMSG;
|
||||||
|
if (!dbus_message_iter_close_container(&args, &array)) OOMMSG;
|
||||||
|
APPEND(DBUS_TYPE_INT32, &timeout)
|
||||||
|
#undef OOMMSG
|
||||||
|
#undef APPEND
|
||||||
|
if (!call_method_with_msg(session_bus, msg, 5000, notification_created, data)) return 0;
|
||||||
|
return data->next_id;
|
||||||
|
}
|
||||||
19
glfw/linux_notify.h
vendored
Normal file
19
glfw/linux_notify.h
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "dbus_glfw.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
typedef unsigned long long notification_id_type;
|
||||||
|
typedef void (*GLFWDBusnotificationcreatedfun)(notification_id_type, uint32_t, void*);
|
||||||
|
typedef void (*GLFWDBusnotificationactivatedfun)(uint32_t, const char*);
|
||||||
|
notification_id_type
|
||||||
|
glfw_dbus_send_user_notification(const char *app_name, const char* icon, const char *summary, const char *body, const char *action_name, int32_t timeout, GLFWDBusnotificationcreatedfun, void*);
|
||||||
|
void
|
||||||
|
glfw_dbus_set_user_notification_activated_handler(GLFWDBusnotificationactivatedfun handler);
|
||||||
47
glfw/main_loop.h
vendored
Normal file
47
glfw/main_loop.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#ifndef GLFW_LOOP_BACKEND
|
||||||
|
#define GLFW_LOOP_BACKEND x11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool keep_going = false;
|
||||||
|
|
||||||
|
void _glfwPlatformRequestTickCallback() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
|
if (keep_going) {
|
||||||
|
keep_going = false;
|
||||||
|
_glfwPlatformPostEmptyEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
|
||||||
|
keep_going = true;
|
||||||
|
while(keep_going) {
|
||||||
|
_glfwPlatformWaitEvents();
|
||||||
|
EVDBG("loop tick");
|
||||||
|
tick_callback(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback) {
|
||||||
|
return addTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, "user timer", interval, 1, repeats, callback, callback_data, free_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
|
||||||
|
removeTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
||||||
|
changeTimerInterval(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, interval);
|
||||||
|
toggleTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, enabled);
|
||||||
|
}
|
||||||
4
glfw/memfd.h
vendored
4
glfw/memfd.h
vendored
@@ -29,8 +29,8 @@ static inline int memfd_create(const char *name, unsigned int flags) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MFD_CLOEXEC
|
#ifndef MFD_CLOEXEC
|
||||||
#define MFD_CLOEXEC 0x0001U
|
#define MFD_CLOEXEC 0x0001U
|
||||||
#define MFD_ALLOW_SEALING 0x0002U
|
#define MFD_ALLOW_SEALING 0x0002U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
32
glfw/monitor.c
vendored
32
glfw/monitor.c
vendored
@@ -60,17 +60,17 @@ static int compareVideoModes(const void* fp, const void* sp)
|
|||||||
|
|
||||||
// Retrieves the available modes for the specified monitor
|
// Retrieves the available modes for the specified monitor
|
||||||
//
|
//
|
||||||
static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
static bool refreshVideoModes(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
int modeCount;
|
int modeCount;
|
||||||
GLFWvidmode* modes;
|
GLFWvidmode* modes;
|
||||||
|
|
||||||
if (monitor->modes)
|
if (monitor->modes)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
|
modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
|
||||||
if (!modes)
|
if (!modes)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
|||||||
monitor->modes = modes;
|
monitor->modes = modes;
|
||||||
monitor->modeCount = modeCount;
|
monitor->modeCount = modeCount;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -127,10 +127,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
|||||||
{
|
{
|
||||||
if (_glfw.monitors[i] == monitor)
|
if (_glfw.monitors[i] == monitor)
|
||||||
{
|
{
|
||||||
_glfw.monitorCount--;
|
remove_i_from_array(_glfw.monitors, i, _glfw.monitorCount);
|
||||||
memmove(_glfw.monitors + i,
|
|
||||||
_glfw.monitors + i + 1,
|
|
||||||
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,6 +327,25 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
|
|||||||
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, int* width, int* height)
|
||||||
|
{
|
||||||
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
assert(monitor != NULL);
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = 0;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = 0;
|
||||||
|
if (width)
|
||||||
|
*width = 0;
|
||||||
|
if (height)
|
||||||
|
*height = 0;
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
_glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
|
GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
|
|||||||
6
glfw/nsgl_context.h
vendored
6
glfw/nsgl_context.h
vendored
@@ -33,7 +33,7 @@
|
|||||||
typedef struct _GLFWcontextNSGL
|
typedef struct _GLFWcontextNSGL
|
||||||
{
|
{
|
||||||
id pixelFormat;
|
id pixelFormat;
|
||||||
id object;
|
id object;
|
||||||
|
|
||||||
} _GLFWcontextNSGL;
|
} _GLFWcontextNSGL;
|
||||||
|
|
||||||
@@ -47,9 +47,9 @@ typedef struct _GLFWlibraryNSGL
|
|||||||
} _GLFWlibraryNSGL;
|
} _GLFWlibraryNSGL;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitNSGL(void);
|
bool _glfwInitNSGL(void);
|
||||||
void _glfwTerminateNSGL(void);
|
void _glfwTerminateNSGL(void);
|
||||||
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||||
|
|||||||
@@ -27,11 +27,6 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
|
||||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < 101400)
|
|
||||||
#define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
|
|
||||||
#define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
static void makeContextCurrentNSGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window)
|
if (window)
|
||||||
@@ -50,17 +45,16 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
static void swapIntervalNSGL(int interval)
|
static void swapIntervalNSGL(int interval)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
// As of Mojave this does not work so we use CVDisplayLink instead
|
||||||
|
(void)(interval);
|
||||||
GLint sync = interval;
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
[window->context.nsgl.object setValues:&sync
|
"NSGL: Swap intervals do not work on macOS");
|
||||||
forParameter:NSOpenGLContextParameterSwapInterval];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extensionSupportedNSGL(const char* extension)
|
static int extensionSupportedNSGL(const char* extension)
|
||||||
{
|
{
|
||||||
// There are no NSGL extensions
|
// There are no NSGL extensions
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWglproc getProcAddressNSGL(const char* procname)
|
static GLFWglproc getProcAddressNSGL(const char* procname)
|
||||||
@@ -77,8 +71,6 @@ static GLFWglproc getProcAddressNSGL(const char* procname)
|
|||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the OpenGL context
|
|
||||||
//
|
|
||||||
static void destroyContextNSGL(_GLFWwindow* window)
|
static void destroyContextNSGL(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
[window->context.nsgl.pixelFormat release];
|
[window->context.nsgl.pixelFormat release];
|
||||||
@@ -95,10 +87,10 @@ static void destroyContextNSGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Initialize OpenGL support
|
// Initialize OpenGL support
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitNSGL(void)
|
bool _glfwInitNSGL(void)
|
||||||
{
|
{
|
||||||
if (_glfw.nsgl.framework)
|
if (_glfw.nsgl.framework)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
_glfw.nsgl.framework =
|
_glfw.nsgl.framework =
|
||||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||||
@@ -106,10 +98,10 @@ GLFWbool _glfwInitNSGL(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"NSGL: Failed to locate OpenGL framework");
|
"NSGL: Failed to locate OpenGL framework");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate OpenGL support
|
// Terminate OpenGL support
|
||||||
@@ -120,7 +112,7 @@ void _glfwTerminateNSGL(void)
|
|||||||
|
|
||||||
// Create the OpenGL context
|
// Create the OpenGL context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
@@ -128,7 +120,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"NSGL: OpenGL ES is not available on macOS");
|
"NSGL: OpenGL ES is not available on macOS");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->major > 2)
|
if (ctxconfig->major > 2)
|
||||||
@@ -137,15 +129,9 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"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 by
|
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
||||||
@@ -180,9 +166,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
// Info.plist for unbundled applications
|
// Info.plist for unbundled applications
|
||||||
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||||
// a straightforward wrapper of its CGL counterpart
|
// a straightforward wrapper of its CGL counterpart
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
|
||||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||||
@@ -247,7 +231,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"NSGL: Stereo rendering is deprecated");
|
"NSGL: Stereo rendering is deprecated");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
#else
|
#else
|
||||||
addAttrib(NSOpenGLPFAStereo);
|
addAttrib(NSOpenGLPFAStereo);
|
||||||
#endif
|
#endif
|
||||||
@@ -283,7 +267,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||||
"NSGL: Failed to find a suitable pixel format");
|
"NSGL: Failed to find a suitable pixel format");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSOpenGLContext* share = NULL;
|
NSOpenGLContext* share = NULL;
|
||||||
@@ -298,7 +282,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"NSGL: Failed to create OpenGL context");
|
"NSGL: Failed to create OpenGL context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fbconfig->transparent)
|
if (fbconfig->transparent)
|
||||||
@@ -307,6 +291,13 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->ns.retina)
|
||||||
|
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
||||||
|
|
||||||
|
GLint interval = 0;
|
||||||
|
[window->context.nsgl.object setValues:&interval
|
||||||
|
forParameter:NSOpenGLContextParameterSwapInterval];
|
||||||
|
|
||||||
[window->context.nsgl.object setView:window->ns.view];
|
[window->context.nsgl.object setView:window->ns.view];
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentNSGL;
|
window->context.makeCurrent = makeContextCurrentNSGL;
|
||||||
@@ -316,7 +307,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressNSGL;
|
window->context.getProcAddress = getProcAddressNSGL;
|
||||||
window->context.destroy = destroyContextNSGL;
|
window->context.destroy = destroyContextNSGL;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
glfw/null_init.c
vendored
2
glfw/null_init.c
vendored
@@ -35,7 +35,7 @@
|
|||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
|
|||||||
2
glfw/null_joystick.c
vendored
2
glfw/null_joystick.c
vendored
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||||
|
|||||||
8
glfw/null_monitor.c
vendored
8
glfw/null_monitor.c
vendored
@@ -49,6 +49,10 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = 1.f;
|
*yscale = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -58,9 +62,9 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
|||||||
43
glfw/null_window.c
vendored
43
glfw/null_window.c
vendored
@@ -34,7 +34,7 @@ static int createNativeWindow(_GLFWwindow* window,
|
|||||||
window->null.width = wndconfig->width;
|
window->null.width = wndconfig->width;
|
||||||
window->null.height = wndconfig->height;
|
window->null.height = wndconfig->height;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
if (!createNativeWindow(window, wndconfig))
|
if (!createNativeWindow(window, wndconfig))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
@@ -56,18 +56,18 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitOSMesa())
|
if (!_glfwInitOSMesa())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
@@ -167,28 +167,28 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||||
@@ -229,17 +229,22 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformPollEvents(void)
|
void _glfwPlatformPollEvents(void)
|
||||||
@@ -274,12 +279,12 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
const GLFWimage* image,
|
const GLFWimage* image,
|
||||||
int xhot, int yhot, int count)
|
int xhot, int yhot, int count)
|
||||||
{
|
{
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||||
{
|
{
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
@@ -317,7 +322,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||||
|
|||||||
36
glfw/osmesa_context.c
vendored
36
glfw/osmesa_context.c
vendored
@@ -100,7 +100,7 @@ static void swapIntervalOSMesa(int interval)
|
|||||||
static int extensionSupportedOSMesa(const char* extension)
|
static int extensionSupportedOSMesa(const char* extension)
|
||||||
{
|
{
|
||||||
// OSMesa does not have extensions
|
// OSMesa does not have extensions
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ static int extensionSupportedOSMesa(const char* extension)
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwInitOSMesa(void)
|
bool _glfwInitOSMesa(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
const char* sonames[] =
|
const char* sonames[] =
|
||||||
@@ -130,7 +130,7 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (_glfw.osmesa.handle)
|
if (_glfw.osmesa.handle)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
for (i = 0; sonames[i]; i++)
|
for (i = 0; sonames[i]; i++)
|
||||||
{
|
{
|
||||||
@@ -142,7 +142,7 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
if (!_glfw.osmesa.handle)
|
if (!_glfw.osmesa.handle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
||||||
@@ -171,10 +171,10 @@ GLFWbool _glfwInitOSMesa(void)
|
|||||||
"OSMesa: Failed to load required entry points");
|
"OSMesa: Failed to load required entry points");
|
||||||
|
|
||||||
_glfwTerminateOSMesa();
|
_glfwTerminateOSMesa();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwTerminateOSMesa(void)
|
void _glfwTerminateOSMesa(void)
|
||||||
@@ -193,7 +193,7 @@ void _glfwTerminateOSMesa(void)
|
|||||||
attribs[index++] = v; \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
bool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
@@ -207,7 +207,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"OSMesa: OpenGL ES is not available on OSMesa");
|
"OSMesa: OpenGL ES is not available on OSMesa");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
@@ -241,7 +241,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"OSMesa: Forward-compatible contexts not supported");
|
"OSMesa: Forward-compatible contexts not supported");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setAttrib(0, 0);
|
setAttrib(0, 0);
|
||||||
@@ -255,7 +255,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"OSMesa: OpenGL profiles unavailable");
|
"OSMesa: OpenGL profiles unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.osmesa.handle =
|
window->context.osmesa.handle =
|
||||||
@@ -270,7 +270,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"OSMesa: Failed to create context");
|
"OSMesa: Failed to create context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentOSMesa;
|
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||||
@@ -280,7 +280,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressOSMesa;
|
window->context.getProcAddress = getProcAddressOSMesa;
|
||||||
window->context.destroy = destroyContextOSMesa;
|
window->context.destroy = destroyContextOSMesa;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setAttrib
|
#undef setAttrib
|
||||||
@@ -298,7 +298,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
|||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
||||||
&mesaWidth, &mesaHeight,
|
&mesaWidth, &mesaHeight,
|
||||||
@@ -306,7 +306,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"OSMesa: Failed to retrieve color buffer");
|
"OSMesa: Failed to retrieve color buffer");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width)
|
if (width)
|
||||||
@@ -318,7 +318,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
|||||||
if (buffer)
|
if (buffer)
|
||||||
*buffer = mesaBuffer;
|
*buffer = mesaBuffer;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||||
@@ -331,7 +331,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
|||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
||||||
&mesaWidth, &mesaHeight,
|
&mesaWidth, &mesaHeight,
|
||||||
@@ -339,7 +339,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"OSMesa: Failed to retrieve depth buffer");
|
"OSMesa: Failed to retrieve depth buffer");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width)
|
if (width)
|
||||||
@@ -351,7 +351,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
|||||||
if (buffer)
|
if (buffer)
|
||||||
*buffer = mesaBuffer;
|
*buffer = mesaBuffer;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||||
|
|||||||
4
glfw/osmesa_context.h
vendored
4
glfw/osmesa_context.h
vendored
@@ -86,9 +86,9 @@ typedef struct _GLFWlibraryOSMesa
|
|||||||
} _GLFWlibraryOSMesa;
|
} _GLFWlibraryOSMesa;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitOSMesa(void);
|
bool _glfwInitOSMesa(void);
|
||||||
void _glfwTerminateOSMesa(void);
|
void _glfwTerminateOSMesa(void);
|
||||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
bool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
|||||||
26
glfw/posix_thread.c
vendored
26
glfw/posix_thread.c
vendored
@@ -35,19 +35,19 @@
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
|
bool _glfwPlatformCreateTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
assert(tls->posix.allocated == GLFW_FALSE);
|
assert(tls->posix.allocated == false);
|
||||||
|
|
||||||
if (pthread_key_create(&tls->posix.key, NULL) != 0)
|
if (pthread_key_create(&tls->posix.key, NULL) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"POSIX: Failed to create context TLS");
|
"POSIX: Failed to create context TLS");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->posix.allocated = GLFW_TRUE;
|
tls->posix.allocated = true;
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||||
@@ -59,27 +59,27 @@ void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
|||||||
|
|
||||||
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||||
{
|
{
|
||||||
assert(tls->posix.allocated == GLFW_TRUE);
|
assert(tls->posix.allocated == true);
|
||||||
return pthread_getspecific(tls->posix.key);
|
return pthread_getspecific(tls->posix.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||||
{
|
{
|
||||||
assert(tls->posix.allocated == GLFW_TRUE);
|
assert(tls->posix.allocated == true);
|
||||||
pthread_setspecific(tls->posix.key, value);
|
pthread_setspecific(tls->posix.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
bool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
|
||||||
{
|
{
|
||||||
assert(mutex->posix.allocated == GLFW_FALSE);
|
assert(mutex->posix.allocated == false);
|
||||||
|
|
||||||
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
|
if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mutex->posix.allocated = GLFW_TRUE;
|
return mutex->posix.allocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||||
@@ -91,13 +91,13 @@ void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
|||||||
|
|
||||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||||
{
|
{
|
||||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
assert(mutex->posix.allocated == true);
|
||||||
pthread_mutex_lock(&mutex->posix.handle);
|
pthread_mutex_lock(&mutex->posix.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||||
{
|
{
|
||||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
assert(mutex->posix.allocated == true);
|
||||||
pthread_mutex_unlock(&mutex->posix.handle);
|
pthread_mutex_unlock(&mutex->posix.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
glfw/posix_thread.h
vendored
4
glfw/posix_thread.h
vendored
@@ -35,7 +35,7 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWtlsPOSIX
|
typedef struct _GLFWtlsPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
bool allocated;
|
||||||
pthread_key_t key;
|
pthread_key_t key;
|
||||||
|
|
||||||
} _GLFWtlsPOSIX;
|
} _GLFWtlsPOSIX;
|
||||||
@@ -44,7 +44,7 @@ typedef struct _GLFWtlsPOSIX
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWmutexPOSIX
|
typedef struct _GLFWmutexPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool allocated;
|
bool allocated;
|
||||||
pthread_mutex_t handle;
|
pthread_mutex_t handle;
|
||||||
|
|
||||||
} _GLFWmutexPOSIX;
|
} _GLFWmutexPOSIX;
|
||||||
|
|||||||
4
glfw/posix_time.c
vendored
4
glfw/posix_time.c
vendored
@@ -44,13 +44,13 @@ void _glfwInitTimerPOSIX(void)
|
|||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
||||||
{
|
{
|
||||||
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
_glfw.timer.posix.monotonic = true;
|
||||||
_glfw.timer.posix.frequency = 1000000000;
|
_glfw.timer.posix.frequency = 1000000000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
_glfw.timer.posix.monotonic = false;
|
||||||
_glfw.timer.posix.frequency = 1000000;
|
_glfw.timer.posix.frequency = 1000000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
glfw/posix_time.h
vendored
2
glfw/posix_time.h
vendored
@@ -34,7 +34,7 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWtimerPOSIX
|
typedef struct _GLFWtimerPOSIX
|
||||||
{
|
{
|
||||||
GLFWbool monotonic;
|
bool monotonic;
|
||||||
uint64_t frequency;
|
uint64_t frequency;
|
||||||
|
|
||||||
} _GLFWtimerPOSIX;
|
} _GLFWtimerPOSIX;
|
||||||
|
|||||||
@@ -64,7 +64,9 @@
|
|||||||
"egl_context.h",
|
"egl_context.h",
|
||||||
"osmesa_context.h",
|
"osmesa_context.h",
|
||||||
"linux_joystick.h",
|
"linux_joystick.h",
|
||||||
"null_joystick.h"
|
"null_joystick.h",
|
||||||
|
"linux_notify.h",
|
||||||
|
"main_loop.h"
|
||||||
],
|
],
|
||||||
"protocols": [
|
"protocols": [
|
||||||
"stable/xdg-shell/xdg-shell.xml",
|
"stable/xdg-shell/xdg-shell.xml",
|
||||||
@@ -88,7 +90,8 @@
|
|||||||
"osmesa_context.c",
|
"osmesa_context.c",
|
||||||
"backend_utils.c",
|
"backend_utils.c",
|
||||||
"linux_joystick.c",
|
"linux_joystick.c",
|
||||||
"null_joystick.c"
|
"null_joystick.c",
|
||||||
|
"linux_notify.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"wayland_protocols": [
|
"wayland_protocols": [
|
||||||
@@ -128,7 +131,9 @@
|
|||||||
"egl_context.h",
|
"egl_context.h",
|
||||||
"osmesa_context.h",
|
"osmesa_context.h",
|
||||||
"linux_joystick.h",
|
"linux_joystick.h",
|
||||||
"null_joystick.h"
|
"null_joystick.h",
|
||||||
|
"linux_notify.h",
|
||||||
|
"main_loop.h"
|
||||||
],
|
],
|
||||||
"sources": [
|
"sources": [
|
||||||
"x11_init.c",
|
"x11_init.c",
|
||||||
@@ -144,7 +149,8 @@
|
|||||||
"osmesa_context.c",
|
"osmesa_context.c",
|
||||||
"backend_utils.c",
|
"backend_utils.c",
|
||||||
"linux_joystick.c",
|
"linux_joystick.c",
|
||||||
"null_joystick.c"
|
"null_joystick.c",
|
||||||
|
"linux_notify.c"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
38
glfw/vulkan.c
vendored
38
glfw/vulkan.c
vendored
@@ -39,14 +39,14 @@
|
|||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWbool _glfwInitVulkan(int mode)
|
bool _glfwInitVulkan(int mode)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
VkExtensionProperties* ep;
|
VkExtensionProperties* ep;
|
||||||
uint32_t i, count;
|
uint32_t i, count;
|
||||||
|
|
||||||
if (_glfw.vk.available)
|
if (_glfw.vk.available)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
#if defined(_GLFW_VULKAN_LIBRARY)
|
#if defined(_GLFW_VULKAN_LIBRARY)
|
||||||
@@ -63,7 +63,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
if (mode == _GLFW_REQUIRE_LOADER)
|
if (mode == _GLFW_REQUIRE_LOADER)
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||||
@@ -74,7 +74,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
||||||
@@ -85,7 +85,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // _GLFW_VULKAN_STATIC
|
#endif // _GLFW_VULKAN_STATIC
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ep = calloc(count, sizeof(VkExtensionProperties));
|
ep = calloc(count, sizeof(VkExtensionProperties));
|
||||||
@@ -115,37 +115,37 @@ GLFWbool _glfwInitVulkan(int mode)
|
|||||||
|
|
||||||
free(ep);
|
free(ep);
|
||||||
_glfwTerminateVulkan();
|
_glfwTerminateVulkan();
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
||||||
_glfw.vk.KHR_surface = GLFW_TRUE;
|
_glfw.vk.KHR_surface = true;
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
|
||||||
_glfw.vk.KHR_win32_surface = GLFW_TRUE;
|
_glfw.vk.KHR_win32_surface = true;
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||||
_glfw.vk.MVK_macos_surface = GLFW_TRUE;
|
_glfw.vk.MVK_macos_surface = true;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
_glfw.vk.KHR_xlib_surface = GLFW_TRUE;
|
_glfw.vk.KHR_xlib_surface = true;
|
||||||
else 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;
|
_glfw.vk.KHR_xcb_surface = true;
|
||||||
#elif defined(_GLFW_WAYLAND)
|
#elif defined(_GLFW_WAYLAND)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||||
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
_glfw.vk.KHR_wayland_surface = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
free(ep);
|
free(ep);
|
||||||
|
|
||||||
_glfw.vk.available = GLFW_TRUE;
|
_glfw.vk.available = true;
|
||||||
|
|
||||||
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwTerminateVulkan(void)
|
void _glfwTerminateVulkan(void)
|
||||||
@@ -218,7 +218,7 @@ const char* _glfwGetVulkanResultString(VkResult result)
|
|||||||
|
|
||||||
GLFWAPI int glfwVulkanSupported(void)
|
GLFWAPI int glfwVulkanSupported(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,16 +273,16 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
assert(instance != VK_NULL_HANDLE);
|
assert(instance != VK_NULL_HANDLE);
|
||||||
assert(device != VK_NULL_HANDLE);
|
assert(device != VK_NULL_HANDLE);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (!_glfw.vk.extensions[0])
|
if (!_glfw.vk.extensions[0])
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"Vulkan: Window surface creation extensions not found");
|
"Vulkan: Window surface creation extensions not found");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
||||||
|
|||||||
61
glfw/wgl_context.c
vendored
61
glfw/wgl_context.c
vendored
@@ -122,9 +122,9 @@ static int choosePixelFormat(_GLFWwindow* window,
|
|||||||
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
|
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
|
||||||
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
|
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
|
||||||
u->stereo = GLFW_TRUE;
|
u->stereo = true;
|
||||||
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
|
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
|
||||||
u->doublebuffer = GLFW_TRUE;
|
u->doublebuffer = true;
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_multisample)
|
if (_glfw.wgl.ARB_multisample)
|
||||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||||
@@ -135,7 +135,7 @@ static int choosePixelFormat(_GLFWwindow* window,
|
|||||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||||
{
|
{
|
||||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||||
u->sRGB = GLFW_TRUE;
|
u->sRGB = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -145,7 +145,7 @@ static int choosePixelFormat(_GLFWwindow* window,
|
|||||||
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
||||||
WGL_COLORSPACE_SRGB_EXT)
|
WGL_COLORSPACE_SRGB_EXT)
|
||||||
{
|
{
|
||||||
u->sRGB = GLFW_TRUE;
|
u->sRGB = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,9 +195,9 @@ static int choosePixelFormat(_GLFWwindow* window,
|
|||||||
u->auxBuffers = pfd.cAuxBuffers;
|
u->auxBuffers = pfd.cAuxBuffers;
|
||||||
|
|
||||||
if (pfd.dwFlags & PFD_STEREO)
|
if (pfd.dwFlags & PFD_STEREO)
|
||||||
u->stereo = GLFW_TRUE;
|
u->stereo = true;
|
||||||
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
||||||
u->doublebuffer = GLFW_TRUE;
|
u->doublebuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
u->handle = n;
|
u->handle = n;
|
||||||
@@ -308,7 +308,7 @@ static int extensionSupportedWGL(const char* extension)
|
|||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,11 +318,11 @@ static int extensionSupportedWGL(const char* extension)
|
|||||||
if (extensions)
|
if (extensions)
|
||||||
{
|
{
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
if (_glfwStringInExtensionString(extension, extensions))
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWglproc getProcAddressWGL(const char* procname)
|
static GLFWglproc getProcAddressWGL(const char* procname)
|
||||||
@@ -352,21 +352,21 @@ static void destroyContextWGL(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Initialize WGL
|
// Initialize WGL
|
||||||
//
|
//
|
||||||
GLFWbool _glfwInitWGL(void)
|
bool _glfwInitWGL(void)
|
||||||
{
|
{
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
PIXELFORMATDESCRIPTOR pfd;
|
||||||
HGLRC prc, rc;
|
HGLRC prc, rc;
|
||||||
HDC pdc, dc;
|
HDC pdc, dc;
|
||||||
|
|
||||||
if (_glfw.wgl.instance)
|
if (_glfw.wgl.instance)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
|
|
||||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||||
if (!_glfw.wgl.instance)
|
if (!_glfw.wgl.instance)
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to load opengl32.dll");
|
"WGL: Failed to load opengl32.dll");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
||||||
@@ -389,7 +389,7 @@ GLFWbool _glfwInitWGL(void)
|
|||||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
||||||
// creation failure occurs during manual pixel format enumeration
|
// creation failure occurs during manual pixel format enumeration
|
||||||
|
|
||||||
dc = GetDC(_glfw.win32.helperWindowHandle);;
|
dc = GetDC(_glfw.win32.helperWindowHandle);
|
||||||
|
|
||||||
ZeroMemory(&pfd, sizeof(pfd));
|
ZeroMemory(&pfd, sizeof(pfd));
|
||||||
pfd.nSize = sizeof(pfd);
|
pfd.nSize = sizeof(pfd);
|
||||||
@@ -402,7 +402,7 @@ GLFWbool _glfwInitWGL(void)
|
|||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to set pixel format for dummy context");
|
"WGL: Failed to set pixel format for dummy context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = wglCreateContext(dc);
|
rc = wglCreateContext(dc);
|
||||||
@@ -410,7 +410,7 @@ GLFWbool _glfwInitWGL(void)
|
|||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to create dummy context");
|
"WGL: Failed to create dummy context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdc = wglGetCurrentDC();
|
pdc = wglGetCurrentDC();
|
||||||
@@ -422,7 +422,7 @@ GLFWbool _glfwInitWGL(void)
|
|||||||
"WGL: Failed to make dummy context current");
|
"WGL: Failed to make dummy context current");
|
||||||
wglMakeCurrent(pdc, prc);
|
wglMakeCurrent(pdc, prc);
|
||||||
wglDeleteContext(rc);
|
wglDeleteContext(rc);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||||
@@ -467,7 +467,7 @@ GLFWbool _glfwInitWGL(void)
|
|||||||
|
|
||||||
wglMakeCurrent(pdc, prc);
|
wglMakeCurrent(pdc, prc);
|
||||||
wglDeleteContext(rc);
|
wglDeleteContext(rc);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminate WGL
|
// Terminate WGL
|
||||||
@@ -487,7 +487,7 @@ void _glfwTerminateWGL(void)
|
|||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
// Create the OpenGL or OpenGL ES context
|
||||||
//
|
//
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig)
|
const _GLFWfbconfig* fbconfig)
|
||||||
{
|
{
|
||||||
@@ -504,26 +504,26 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to retrieve DC for window");
|
"WGL: Failed to retrieve DC for window");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||||
if (!pixelFormat)
|
if (!pixelFormat)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||||
pixelFormat, sizeof(pfd), &pfd))
|
pixelFormat, sizeof(pfd), &pfd))
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to set selected pixel format");
|
"WGL: Failed to set selected pixel format");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||||
@@ -534,7 +534,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -544,7 +544,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||||
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -556,7 +556,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,7 +619,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
if (ctxconfig->noerror)
|
if (ctxconfig->noerror)
|
||||||
{
|
{
|
||||||
if (_glfw.wgl.ARB_create_context_no_error)
|
if (_glfw.wgl.ARB_create_context_no_error)
|
||||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
|
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
// NOTE: Only request an explicitly versioned context when necessary, as
|
||||||
@@ -687,7 +687,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -697,7 +697,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||||
"WGL: Failed to create OpenGL context");
|
"WGL: Failed to create OpenGL context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (share)
|
if (share)
|
||||||
@@ -706,7 +706,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
"WGL: Failed to enable sharing with specified OpenGL context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -718,7 +718,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
|||||||
window->context.getProcAddress = getProcAddressWGL;
|
window->context.getProcAddress = getProcAddressWGL;
|
||||||
window->context.destroy = destroyContextWGL;
|
window->context.destroy = destroyContextWGL;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef setAttrib
|
#undef setAttrib
|
||||||
@@ -741,4 +741,3 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
|||||||
|
|
||||||
return window->context.wgl.handle;
|
return window->context.wgl.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
glfw/wgl_context.h
vendored
28
glfw/wgl_context.h
vendored
@@ -135,25 +135,25 @@ typedef struct _GLFWlibraryWGL
|
|||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
||||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
GLFWbool EXT_swap_control;
|
bool EXT_swap_control;
|
||||||
GLFWbool EXT_colorspace;
|
bool EXT_colorspace;
|
||||||
GLFWbool ARB_multisample;
|
bool ARB_multisample;
|
||||||
GLFWbool ARB_framebuffer_sRGB;
|
bool ARB_framebuffer_sRGB;
|
||||||
GLFWbool EXT_framebuffer_sRGB;
|
bool EXT_framebuffer_sRGB;
|
||||||
GLFWbool ARB_pixel_format;
|
bool ARB_pixel_format;
|
||||||
GLFWbool ARB_create_context;
|
bool ARB_create_context;
|
||||||
GLFWbool ARB_create_context_profile;
|
bool ARB_create_context_profile;
|
||||||
GLFWbool EXT_create_context_es2_profile;
|
bool EXT_create_context_es2_profile;
|
||||||
GLFWbool ARB_create_context_robustness;
|
bool ARB_create_context_robustness;
|
||||||
GLFWbool ARB_create_context_no_error;
|
bool ARB_create_context_no_error;
|
||||||
GLFWbool ARB_context_flush_control;
|
bool ARB_context_flush_control;
|
||||||
|
|
||||||
} _GLFWlibraryWGL;
|
} _GLFWlibraryWGL;
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwInitWGL(void);
|
bool _glfwInitWGL(void);
|
||||||
void _glfwTerminateWGL(void);
|
void _glfwTerminateWGL(void);
|
||||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
|
|
||||||
|
|||||||
627
glfw/win32_init.c
vendored
627
glfw/win32_init.c
vendored
@@ -1,627 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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 <stdlib.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
#endif // _GLFW_USE_HYBRID_HPG
|
|
||||||
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
|
||||||
|
|
||||||
// GLFW DLL entry point
|
|
||||||
//
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _GLFW_BUILD_DLL
|
|
||||||
|
|
||||||
// Load necessary libraries (DLLs)
|
|
||||||
//
|
|
||||||
static GLFWbool loadLibraries(void)
|
|
||||||
{
|
|
||||||
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
|
|
||||||
if (!_glfw.win32.winmm.instance)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to load winmm.dll");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.winmm.GetTime = (PFN_timeGetTime)
|
|
||||||
GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
|
|
||||||
|
|
||||||
_glfw.win32.user32.instance = LoadLibraryA("user32.dll");
|
|
||||||
if (!_glfw.win32.user32.instance)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to load user32.dll");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
|
|
||||||
_glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
|
|
||||||
_glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
|
|
||||||
_glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
|
|
||||||
_glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
|
|
||||||
_glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
|
|
||||||
GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
|
|
||||||
|
|
||||||
_glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
|
|
||||||
GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
const char* names[] =
|
|
||||||
{
|
|
||||||
"xinput1_4.dll",
|
|
||||||
"xinput1_3.dll",
|
|
||||||
"xinput9_1_0.dll",
|
|
||||||
"xinput1_2.dll",
|
|
||||||
"xinput1_1.dll",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
for (i = 0; names[i]; i++)
|
|
||||||
{
|
|
||||||
_glfw.win32.xinput.instance = LoadLibraryA(names[i]);
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
|
|
||||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
|
|
||||||
_glfw.win32.xinput.GetState = (PFN_XInputGetState)
|
|
||||||
GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
|
|
||||||
if (_glfw.win32.dwmapi.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
|
|
||||||
_glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
|
||||||
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
|
||||||
if (_glfw.win32.shcore.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
|
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
|
|
||||||
_glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
|
|
||||||
GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
|
||||||
{
|
|
||||||
_glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
|
|
||||||
GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
|
|
||||||
}
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload used libraries (DLLs)
|
|
||||||
//
|
|
||||||
static void freeLibraries(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
FreeLibrary(_glfw.win32.xinput.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
FreeLibrary(_glfw.win32.dinput8.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.winmm.instance)
|
|
||||||
FreeLibrary(_glfw.win32.winmm.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.user32.instance)
|
|
||||||
FreeLibrary(_glfw.win32.user32.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.dwmapi.instance)
|
|
||||||
FreeLibrary(_glfw.win32.dwmapi.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.shcore.instance)
|
|
||||||
FreeLibrary(_glfw.win32.shcore.instance);
|
|
||||||
|
|
||||||
if (_glfw.win32.ntdll.instance)
|
|
||||||
FreeLibrary(_glfw.win32.ntdll.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create key code translation tables
|
|
||||||
//
|
|
||||||
static void createKeyTables(void)
|
|
||||||
{
|
|
||||||
int scancode;
|
|
||||||
|
|
||||||
memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
|
|
||||||
memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
|
|
||||||
|
|
||||||
_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.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.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.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[0x059] = GLFW_KEY_KP_EQUAL;
|
|
||||||
_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.keycodes[scancode] > 0)
|
|
||||||
_glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a dummy window for behind-the-scenes work
|
|
||||||
//
|
|
||||||
static HWND createHelperWindow(void)
|
|
||||||
{
|
|
||||||
MSG msg;
|
|
||||||
HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
|
|
||||||
_GLFW_WNDCLASSNAME,
|
|
||||||
L"GLFW message window",
|
|
||||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
|
||||||
0, 0, 1, 1,
|
|
||||||
NULL, NULL,
|
|
||||||
GetModuleHandleW(NULL),
|
|
||||||
NULL);
|
|
||||||
if (!window)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to create helper window");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// HACK: The command to the first ShowWindow call is ignored if the parent
|
|
||||||
// process passed along a STARTUPINFO, so clear that with a no-op call
|
|
||||||
ShowWindow(window, SW_HIDE);
|
|
||||||
|
|
||||||
// Register for HID device notifications
|
|
||||||
{
|
|
||||||
DEV_BROADCAST_DEVICEINTERFACE_W dbi;
|
|
||||||
ZeroMemory(&dbi, sizeof(dbi));
|
|
||||||
dbi.dbcc_size = sizeof(dbi);
|
|
||||||
dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
||||||
dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
|
||||||
|
|
||||||
_glfw.win32.deviceNotificationHandle =
|
|
||||||
RegisterDeviceNotificationW(window,
|
|
||||||
(DEV_BROADCAST_HDR*) &dbi,
|
|
||||||
DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
|
|
||||||
{
|
|
||||||
TranslateMessage(&msg);
|
|
||||||
DispatchMessageW(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Returns a wide string version of the specified UTF-8 string
|
|
||||||
//
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
|
|
||||||
{
|
|
||||||
WCHAR* target;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
|
|
||||||
if (!count)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string from UTF-8");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = calloc(count, sizeof(WCHAR));
|
|
||||||
|
|
||||||
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string from UTF-8");
|
|
||||||
free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a UTF-8 string version of the specified wide string
|
|
||||||
//
|
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
|
|
||||||
{
|
|
||||||
char* target;
|
|
||||||
int size;
|
|
||||||
|
|
||||||
size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
|
|
||||||
if (!size)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string to UTF-8");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = calloc(size, 1);
|
|
||||||
|
|
||||||
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert string to UTF-8");
|
|
||||||
free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reports the specified error, appending information about the last Win32 error
|
|
||||||
//
|
|
||||||
void _glfwInputErrorWin32(int error, const char* description)
|
|
||||||
{
|
|
||||||
WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
|
|
||||||
char message[_GLFW_MESSAGE_SIZE] = "";
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates key names according to the current keyboard layout
|
|
||||||
//
|
|
||||||
void _glfwUpdateKeyNamesWin32(void)
|
|
||||||
{
|
|
||||||
int key;
|
|
||||||
BYTE state[256] = {0};
|
|
||||||
|
|
||||||
memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
|
|
||||||
|
|
||||||
for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
|
|
||||||
{
|
|
||||||
UINT vk;
|
|
||||||
int scancode, length;
|
|
||||||
WCHAR chars[16];
|
|
||||||
|
|
||||||
scancode = _glfw.win32.scancodes[key];
|
|
||||||
if (scancode == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
|
|
||||||
{
|
|
||||||
const UINT vks[] = {
|
|
||||||
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
|
|
||||||
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
|
|
||||||
VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
|
|
||||||
VK_MULTIPLY, VK_SUBTRACT, VK_ADD
|
|
||||||
};
|
|
||||||
|
|
||||||
vk = vks[key - GLFW_KEY_KP_0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
|
|
||||||
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (length == -1)
|
|
||||||
{
|
|
||||||
length = ToUnicode(vk, scancode, state,
|
|
||||||
chars, sizeof(chars) / sizeof(WCHAR),
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (length < 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0, chars, 1,
|
|
||||||
_glfw.win32.keynames[key],
|
|
||||||
sizeof(_glfw.win32.keynames[key]),
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
|
|
||||||
//
|
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
|
|
||||||
{
|
|
||||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
|
|
||||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
|
|
||||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
|
|
||||||
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
|
||||||
// latter lies unless the user knew to embedd a non-default manifest
|
|
||||||
// announcing support for Windows 10 via supportedOS GUID
|
|
||||||
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks whether we are on at least the specified build of Windows 10
|
|
||||||
//
|
|
||||||
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
|
|
||||||
{
|
|
||||||
OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
|
|
||||||
DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
|
|
||||||
ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
|
|
||||||
cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
|
|
||||||
// HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
|
|
||||||
// latter lies unless the user knew to embedd a non-default manifest
|
|
||||||
// announcing support for Windows 10 via supportedOS GUID
|
|
||||||
return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int _glfwPlatformInit(void)
|
|
||||||
{
|
|
||||||
// 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)
|
|
||||||
SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
|
|
||||||
&_glfw.win32.foregroundLockTimeout, 0);
|
|
||||||
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
|
|
||||||
SPIF_SENDCHANGE);
|
|
||||||
|
|
||||||
if (!loadLibraries())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
createKeyTables();
|
|
||||||
_glfwUpdateKeyNamesWin32();
|
|
||||||
|
|
||||||
if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
|
|
||||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
|
||||||
else if (IsWindows8Point1OrGreater())
|
|
||||||
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
|
||||||
else if (IsWindowsVistaOrGreater())
|
|
||||||
SetProcessDPIAware();
|
|
||||||
|
|
||||||
if (!_glfwRegisterWindowClassWin32())
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfw.win32.helperWindowHandle = createHelperWindow();
|
|
||||||
if (!_glfw.win32.helperWindowHandle)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
_glfwInitTimerWin32();
|
|
||||||
_glfwInitJoysticksWin32();
|
|
||||||
|
|
||||||
_glfwPollMonitorsWin32();
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.deviceNotificationHandle)
|
|
||||||
UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
|
|
||||||
|
|
||||||
if (_glfw.win32.helperWindowHandle)
|
|
||||||
DestroyWindow(_glfw.win32.helperWindowHandle);
|
|
||||||
|
|
||||||
_glfwUnregisterWindowClassWin32();
|
|
||||||
|
|
||||||
// Restore previous foreground lock timeout system setting
|
|
||||||
SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
|
|
||||||
UIntToPtr(_glfw.win32.foregroundLockTimeout),
|
|
||||||
SPIF_SENDCHANGE);
|
|
||||||
|
|
||||||
free(_glfw.win32.clipboardString);
|
|
||||||
free(_glfw.win32.rawInput);
|
|
||||||
|
|
||||||
_glfwTerminateWGL();
|
|
||||||
_glfwTerminateEGL();
|
|
||||||
|
|
||||||
_glfwTerminateJoysticksWin32();
|
|
||||||
|
|
||||||
freeLibraries();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
|
||||||
{
|
|
||||||
return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
|
|
||||||
#if defined(__MINGW32__)
|
|
||||||
" MinGW"
|
|
||||||
#elif defined(_MSC_VER)
|
|
||||||
" VisualC"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
|
|
||||||
" hybrid-GPU"
|
|
||||||
#endif
|
|
||||||
#if defined(_GLFW_BUILD_DLL)
|
|
||||||
" DLL"
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
751
glfw/win32_joystick.c
vendored
751
glfw/win32_joystick.c
vendored
@@ -1,751 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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 <stdio.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#define _GLFW_TYPE_AXIS 0
|
|
||||||
#define _GLFW_TYPE_SLIDER 1
|
|
||||||
#define _GLFW_TYPE_BUTTON 2
|
|
||||||
#define _GLFW_TYPE_POV 3
|
|
||||||
|
|
||||||
// Data produced with DirectInput device object enumeration
|
|
||||||
//
|
|
||||||
typedef struct _GLFWobjenumWin32
|
|
||||||
{
|
|
||||||
IDirectInputDevice8W* device;
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
|
||||||
int objectCount;
|
|
||||||
int axisCount;
|
|
||||||
int sliderCount;
|
|
||||||
int buttonCount;
|
|
||||||
int povCount;
|
|
||||||
} _GLFWobjenumWin32;
|
|
||||||
|
|
||||||
// Define local copies of the necessary GUIDs
|
|
||||||
//
|
|
||||||
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_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_POV _glfw_GUID_POV
|
|
||||||
|
|
||||||
// Object data array for our clone of c_dfDIJoystick
|
|
||||||
// Generated with https://github.com/elmindreda/c_dfDIJoystick2
|
|
||||||
//
|
|
||||||
static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
|
|
||||||
{
|
|
||||||
{ &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
{ NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
// Our clone of c_dfDIJoystick
|
|
||||||
//
|
|
||||||
static const DIDATAFORMAT _glfwDataFormat =
|
|
||||||
{
|
|
||||||
sizeof(DIDATAFORMAT),
|
|
||||||
sizeof(DIOBJECTDATAFORMAT),
|
|
||||||
DIDFT_ABSAXIS,
|
|
||||||
sizeof(DIJOYSTATE),
|
|
||||||
sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
|
|
||||||
_glfwObjectDataFormats
|
|
||||||
};
|
|
||||||
|
|
||||||
// Returns a description fitting the specified XInput capabilities
|
|
||||||
//
|
|
||||||
static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
|
|
||||||
{
|
|
||||||
switch (xic->SubType)
|
|
||||||
{
|
|
||||||
case XINPUT_DEVSUBTYPE_WHEEL:
|
|
||||||
return "XInput Wheel";
|
|
||||||
case XINPUT_DEVSUBTYPE_ARCADE_STICK:
|
|
||||||
return "XInput Arcade Stick";
|
|
||||||
case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
|
|
||||||
return "XInput Flight Stick";
|
|
||||||
case XINPUT_DEVSUBTYPE_DANCE_PAD:
|
|
||||||
return "XInput Dance Pad";
|
|
||||||
case XINPUT_DEVSUBTYPE_GUITAR:
|
|
||||||
return "XInput Guitar";
|
|
||||||
case XINPUT_DEVSUBTYPE_DRUM_KIT:
|
|
||||||
return "XInput Drum Kit";
|
|
||||||
case XINPUT_DEVSUBTYPE_GAMEPAD:
|
|
||||||
{
|
|
||||||
if (xic->Flags & XINPUT_CAPS_WIRELESS)
|
|
||||||
return "Wireless Xbox Controller";
|
|
||||||
else
|
|
||||||
return "Xbox Controller";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Unknown XInput Device";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lexically compare device objects
|
|
||||||
//
|
|
||||||
static int compareJoystickObjects(const void* first, const void* second)
|
|
||||||
{
|
|
||||||
const _GLFWjoyobjectWin32* fo = first;
|
|
||||||
const _GLFWjoyobjectWin32* so = second;
|
|
||||||
|
|
||||||
if (fo->type != so->type)
|
|
||||||
return fo->type - so->type;
|
|
||||||
|
|
||||||
return fo->offset - so->offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks whether the specified device supports XInput
|
|
||||||
// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
|
|
||||||
//
|
|
||||||
static GLFWbool supportsXInput(const GUID* guid)
|
|
||||||
{
|
|
||||||
UINT i, count = 0;
|
|
||||||
RAWINPUTDEVICELIST* ridl;
|
|
||||||
GLFWbool result = GLFW_FALSE;
|
|
||||||
|
|
||||||
if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
|
|
||||||
return GLFW_FALSE;
|
|
||||||
|
|
||||||
ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
|
|
||||||
|
|
||||||
if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
|
|
||||||
{
|
|
||||||
free(ridl);
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
RID_DEVICE_INFO rdi;
|
|
||||||
char name[256];
|
|
||||||
UINT size;
|
|
||||||
|
|
||||||
if (ridl[i].dwType != RIM_TYPEHID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
ZeroMemory(&rdi, sizeof(rdi));
|
|
||||||
rdi.cbSize = sizeof(rdi);
|
|
||||||
size = sizeof(rdi);
|
|
||||||
|
|
||||||
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
|
||||||
RIDI_DEVICEINFO,
|
|
||||||
&rdi, &size) == -1)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
memset(name, 0, sizeof(name));
|
|
||||||
size = sizeof(name);
|
|
||||||
|
|
||||||
if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
|
|
||||||
RIDI_DEVICENAME,
|
|
||||||
name, &size) == -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
name[sizeof(name) - 1] = '\0';
|
|
||||||
if (strstr(name, "IG_"))
|
|
||||||
{
|
|
||||||
result = GLFW_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ridl);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Frees all resources associated with the specified joystick
|
|
||||||
//
|
|
||||||
static void closeJoystick(_GLFWjoystick* js)
|
|
||||||
{
|
|
||||||
if (js->win32.device)
|
|
||||||
{
|
|
||||||
IDirectInputDevice8_Unacquire(js->win32.device);
|
|
||||||
IDirectInputDevice8_Release(js->win32.device);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwFreeJoystick(js);
|
|
||||||
_glfwInputJoystick(js, GLFW_DISCONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DirectInput device object enumeration callback
|
|
||||||
// Insights gleaned from SDL
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
|
|
||||||
void* user)
|
|
||||||
{
|
|
||||||
_GLFWobjenumWin32* data = user;
|
|
||||||
_GLFWjoyobjectWin32* object = data->objects + data->objectCount;
|
|
||||||
|
|
||||||
if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
|
|
||||||
{
|
|
||||||
DIPROPRANGE dipr;
|
|
||||||
|
|
||||||
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_SLIDER(data->sliderCount);
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_X;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_Y;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_Z;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RX;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RY;
|
|
||||||
else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
|
|
||||||
object->offset = DIJOFS_RZ;
|
|
||||||
else
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
|
|
||||||
ZeroMemory(&dipr, sizeof(dipr));
|
|
||||||
dipr.diph.dwSize = sizeof(dipr);
|
|
||||||
dipr.diph.dwHeaderSize = sizeof(dipr.diph);
|
|
||||||
dipr.diph.dwObj = doi->dwType;
|
|
||||||
dipr.diph.dwHow = DIPH_BYID;
|
|
||||||
dipr.lMin = -32768;
|
|
||||||
dipr.lMax = 32767;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetProperty(data->device,
|
|
||||||
DIPROP_RANGE,
|
|
||||||
&dipr.diph)))
|
|
||||||
{
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
|
|
||||||
{
|
|
||||||
object->type = _GLFW_TYPE_SLIDER;
|
|
||||||
data->sliderCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
object->type = _GLFW_TYPE_AXIS;
|
|
||||||
data->axisCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
|
|
||||||
{
|
|
||||||
object->offset = DIJOFS_BUTTON(data->buttonCount);
|
|
||||||
object->type = _GLFW_TYPE_BUTTON;
|
|
||||||
data->buttonCount++;
|
|
||||||
}
|
|
||||||
else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
|
|
||||||
{
|
|
||||||
object->offset = DIJOFS_POV(data->povCount);
|
|
||||||
object->type = _GLFW_TYPE_POV;
|
|
||||||
data->povCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->objectCount++;
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DirectInput device enumeration callback
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
|
|
||||||
{
|
|
||||||
int jid = 0;
|
|
||||||
DIDEVCAPS dc;
|
|
||||||
DIPROPDWORD dipd;
|
|
||||||
IDirectInputDevice8* device;
|
|
||||||
_GLFWobjenumWin32 data;
|
|
||||||
_GLFWjoystick* js;
|
|
||||||
char guid[33];
|
|
||||||
char name[256];
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
|
||||||
if (js->present)
|
|
||||||
{
|
|
||||||
if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (supportsXInput(&di->guidProduct))
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
|
|
||||||
&di->guidInstance,
|
|
||||||
&device,
|
|
||||||
NULL)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to set device data format");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&dc, sizeof(dc));
|
|
||||||
dc.dwSize = sizeof(dc);
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to query device capabilities");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMemory(&dipd, sizeof(dipd));
|
|
||||||
dipd.diph.dwSize = sizeof(dipd);
|
|
||||||
dipd.diph.dwHeaderSize = sizeof(dipd.diph);
|
|
||||||
dipd.diph.dwHow = DIPH_DEVICE;
|
|
||||||
dipd.dwData = DIPROPAXISMODE_ABS;
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_SetProperty(device,
|
|
||||||
DIPROP_AXISMODE,
|
|
||||||
&dipd.diph)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to set device axis mode");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&data, 0, sizeof(data));
|
|
||||||
data.device = device;
|
|
||||||
data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,
|
|
||||||
sizeof(_GLFWjoyobjectWin32));
|
|
||||||
|
|
||||||
if (FAILED(IDirectInputDevice8_EnumObjects(device,
|
|
||||||
deviceObjectCallback,
|
|
||||||
&data,
|
|
||||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to enumerate device objects");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
free(data.objects);
|
|
||||||
return DIENUM_CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(data.objects, data.objectCount,
|
|
||||||
sizeof(_GLFWjoyobjectWin32),
|
|
||||||
compareJoystickObjects);
|
|
||||||
|
|
||||||
if (!WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
di->tszInstanceName, -1,
|
|
||||||
name, sizeof(name),
|
|
||||||
NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to convert joystick name to UTF-8");
|
|
||||||
|
|
||||||
IDirectInputDevice8_Release(device);
|
|
||||||
free(data.objects);
|
|
||||||
return DIENUM_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
|
||||||
if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize joystick interface
|
|
||||||
//
|
|
||||||
void _glfwInitJoysticksWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.dinput8.instance)
|
|
||||||
{
|
|
||||||
if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
|
|
||||||
DIRECTINPUT_VERSION,
|
|
||||||
&IID_IDirectInput8W,
|
|
||||||
(void**) &_glfw.win32.dinput8.api,
|
|
||||||
NULL)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to create interface");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwDetectJoystickConnectionWin32();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close all opened joystick handles
|
|
||||||
//
|
|
||||||
void _glfwTerminateJoysticksWin32(void)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for new joysticks after DBT_DEVICEARRIVAL
|
|
||||||
//
|
|
||||||
void _glfwDetectJoystickConnectionWin32(void)
|
|
||||||
{
|
|
||||||
if (_glfw.win32.xinput.instance)
|
|
||||||
{
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
|
|
||||||
DI8DEVCLASS_GAMECTRL,
|
|
||||||
deviceCallback,
|
|
||||||
NULL,
|
|
||||||
DIEDFL_ALLDEVICES)))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Failed to enumerate DirectInput8 devices");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
|
|
||||||
//
|
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void)
|
|
||||||
{
|
|
||||||
int jid;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
|
||||||
_GLFWjoystick* js = _glfw.joysticks + jid;
|
|
||||||
if (js->present)
|
|
||||||
_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
|
|
||||||
_glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
|
|
||||||
_glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
|
|
||||||
_glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
|
||||||
{
|
|
||||||
if (strcmp(guid + 20, "504944564944") == 0)
|
|
||||||
{
|
|
||||||
char original[33];
|
|
||||||
strcpy(original, guid);
|
|
||||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
|
||||||
original, original + 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
56
glfw/win32_joystick.h
vendored
56
glfw/win32_joystick.h
vendored
@@ -1,56 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 Win32 - 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 _GLFWjoystickWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int dummy
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
|
|
||||||
|
|
||||||
// Joystick element (axis, button or slider)
|
|
||||||
//
|
|
||||||
typedef struct _GLFWjoyobjectWin32
|
|
||||||
{
|
|
||||||
int offset;
|
|
||||||
int type;
|
|
||||||
} _GLFWjoyobjectWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-joystick data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWjoystickWin32
|
|
||||||
{
|
|
||||||
_GLFWjoyobjectWin32* objects;
|
|
||||||
int objectCount;
|
|
||||||
IDirectInputDevice8W* device;
|
|
||||||
DWORD index;
|
|
||||||
GUID guid;
|
|
||||||
} _GLFWjoystickWin32;
|
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitJoysticksWin32(void);
|
|
||||||
void _glfwTerminateJoysticksWin32(void);
|
|
||||||
void _glfwDetectJoystickConnectionWin32(void);
|
|
||||||
void _glfwDetectJoystickDisconnectionWin32(void);
|
|
||||||
|
|
||||||
514
glfw/win32_monitor.c
vendored
514
glfw/win32_monitor.c
vendored
@@ -1,514 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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 <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Callback for EnumDisplayMonitors in createMonitor
|
|
||||||
//
|
|
||||||
static BOOL CALLBACK monitorCallback(HMONITOR handle,
|
|
||||||
HDC dc,
|
|
||||||
RECT* rect,
|
|
||||||
LPARAM data)
|
|
||||||
{
|
|
||||||
MONITORINFOEXW mi;
|
|
||||||
ZeroMemory(&mi, sizeof(mi));
|
|
||||||
mi.cbSize = sizeof(mi);
|
|
||||||
|
|
||||||
if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) data;
|
|
||||||
if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
|
|
||||||
monitor->win32.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create monitor from an adapter and (optionally) a display
|
|
||||||
//
|
|
||||||
static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
|
|
||||||
DISPLAY_DEVICEW* display)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
int widthMM, heightMM;
|
|
||||||
char* name;
|
|
||||||
HDC dc;
|
|
||||||
DEVMODEW dm;
|
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
if (display)
|
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
|
|
||||||
else
|
|
||||||
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
|
|
||||||
if (!name)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
|
|
||||||
|
|
||||||
if (IsWindows8Point1OrGreater())
|
|
||||||
{
|
|
||||||
widthMM = GetDeviceCaps(dc, HORZSIZE);
|
|
||||||
heightMM = GetDeviceCaps(dc, VERTSIZE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
|
|
||||||
heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteDC(dc);
|
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(name, widthMM, heightMM);
|
|
||||||
free(name);
|
|
||||||
|
|
||||||
if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
|
|
||||||
monitor->win32.modesPruned = GLFW_TRUE;
|
|
||||||
|
|
||||||
wcscpy(monitor->win32.adapterName, adapter->DeviceName);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
adapter->DeviceName, -1,
|
|
||||||
monitor->win32.publicAdapterName,
|
|
||||||
sizeof(monitor->win32.publicAdapterName),
|
|
||||||
NULL, NULL);
|
|
||||||
|
|
||||||
if (display)
|
|
||||||
{
|
|
||||||
wcscpy(monitor->win32.displayName, display->DeviceName);
|
|
||||||
WideCharToMultiByte(CP_UTF8, 0,
|
|
||||||
display->DeviceName, -1,
|
|
||||||
monitor->win32.publicDisplayName,
|
|
||||||
sizeof(monitor->win32.publicDisplayName),
|
|
||||||
NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
rect.left = dm.dmPosition.x;
|
|
||||||
rect.top = dm.dmPosition.y;
|
|
||||||
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
|
||||||
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
|
||||||
|
|
||||||
EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
|
|
||||||
return monitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// 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(adapter));
|
|
||||||
adapter.cb = sizeof(adapter);
|
|
||||||
|
|
||||||
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));
|
|
||||||
display.cb = sizeof(display);
|
|
||||||
|
|
||||||
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
|
|
||||||
//
|
|
||||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|
||||||
{
|
|
||||||
GLFWvidmode current;
|
|
||||||
const GLFWvidmode* best;
|
|
||||||
DEVMODEW dm;
|
|
||||||
LONG result;
|
|
||||||
|
|
||||||
best = _glfwChooseVideoMode(monitor, desired);
|
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
|
|
||||||
DM_DISPLAYFREQUENCY;
|
|
||||||
dm.dmPelsWidth = best->width;
|
|
||||||
dm.dmPelsHeight = best->height;
|
|
||||||
dm.dmBitsPerPel = best->redBits + best->greenBits + best->blueBits;
|
|
||||||
dm.dmDisplayFrequency = best->refreshRate;
|
|
||||||
|
|
||||||
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
|
|
||||||
dm.dmBitsPerPel = 32;
|
|
||||||
|
|
||||||
result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
&dm,
|
|
||||||
NULL,
|
|
||||||
CDS_FULLSCREEN,
|
|
||||||
NULL);
|
|
||||||
if (result == DISP_CHANGE_SUCCESSFUL)
|
|
||||||
monitor->win32.modeChanged = GLFW_TRUE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the previously saved (original) video mode
|
|
||||||
//
|
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
if (monitor->win32.modeChanged)
|
|
||||||
{
|
|
||||||
ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
NULL, NULL, CDS_FULLSCREEN, NULL);
|
|
||||||
monitor->win32.modeChanged = GLFW_FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
|
|
||||||
{
|
|
||||||
UINT xdpi, ydpi;
|
|
||||||
|
|
||||||
if (IsWindows8Point1OrGreater())
|
|
||||||
GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const HDC dc = GetDC(NULL);
|
|
||||||
xdpi = GetDeviceCaps(dc, LOGPIXELSX);
|
|
||||||
ydpi = GetDeviceCaps(dc, LOGPIXELSY);
|
|
||||||
ReleaseDC(NULL, dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xscale)
|
|
||||||
*xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
|
|
||||||
if (yscale)
|
|
||||||
*yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|
||||||
{
|
|
||||||
DEVMODEW dm;
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
EnumDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
ENUM_CURRENT_SETTINGS,
|
|
||||||
&dm,
|
|
||||||
EDS_ROTATEDMODE);
|
|
||||||
|
|
||||||
if (xpos)
|
|
||||||
*xpos = dm.dmPosition.x;
|
|
||||||
if (ypos)
|
|
||||||
*ypos = dm.dmPosition.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|
||||||
float* xscale, float* yscale)
|
|
||||||
{
|
|
||||||
_glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|
||||||
{
|
|
||||||
int modeIndex = 0, size = 0;
|
|
||||||
GLFWvidmode* result = NULL;
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
GLFWvidmode mode;
|
|
||||||
DEVMODEW dm;
|
|
||||||
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
|
|
||||||
break;
|
|
||||||
|
|
||||||
modeIndex++;
|
|
||||||
|
|
||||||
// Skip modes with less than 15 BPP
|
|
||||||
if (dm.dmBitsPerPel < 15)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mode.width = dm.dmPelsWidth;
|
|
||||||
mode.height = dm.dmPelsHeight;
|
|
||||||
mode.refreshRate = dm.dmDisplayFrequency;
|
|
||||||
_glfwSplitBPP(dm.dmBitsPerPel,
|
|
||||||
&mode.redBits,
|
|
||||||
&mode.greenBits,
|
|
||||||
&mode.blueBits);
|
|
||||||
|
|
||||||
for (i = 0; i < *count; i++)
|
|
||||||
{
|
|
||||||
if (_glfwCompareVideoModes(result + i, &mode) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip duplicate modes
|
|
||||||
if (i < *count)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (monitor->win32.modesPruned)
|
|
||||||
{
|
|
||||||
// Skip modes not supported by the connected displays
|
|
||||||
if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
|
|
||||||
&dm,
|
|
||||||
NULL,
|
|
||||||
CDS_TEST,
|
|
||||||
NULL) != DISP_CHANGE_SUCCESSFUL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*count == size)
|
|
||||||
{
|
|
||||||
size += 128;
|
|
||||||
result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
|
|
||||||
}
|
|
||||||
|
|
||||||
(*count)++;
|
|
||||||
result[*count - 1] = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*count)
|
|
||||||
{
|
|
||||||
// HACK: Report the current mode if no valid modes were found
|
|
||||||
result = calloc(1, sizeof(GLFWvidmode));
|
|
||||||
_glfwPlatformGetVideoMode(monitor, result);
|
|
||||||
*count = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|
||||||
{
|
|
||||||
DEVMODEW dm;
|
|
||||||
ZeroMemory(&dm, sizeof(dm));
|
|
||||||
dm.dmSize = sizeof(dm);
|
|
||||||
|
|
||||||
EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
|
|
||||||
|
|
||||||
mode->width = dm.dmPelsWidth;
|
|
||||||
mode->height = dm.dmPelsHeight;
|
|
||||||
mode->refreshRate = dm.dmDisplayFrequency;
|
|
||||||
_glfwSplitBPP(dm.dmBitsPerPel,
|
|
||||||
&mode->redBits,
|
|
||||||
&mode->greenBits,
|
|
||||||
&mode->blueBits);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
WORD values[768];
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
|
||||||
GetDeviceGammaRamp(dc, values);
|
|
||||||
DeleteDC(dc);
|
|
||||||
|
|
||||||
_glfwAllocGammaArrays(ramp, 256);
|
|
||||||
|
|
||||||
memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
|
|
||||||
memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
|
|
||||||
memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
WORD values[768];
|
|
||||||
|
|
||||||
if (ramp->size != 256)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Gamma ramp size must be 256");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(values + 0, ramp->red, 256 * sizeof(unsigned short));
|
|
||||||
memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
|
|
||||||
memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short));
|
|
||||||
|
|
||||||
dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
|
|
||||||
SetDeviceGammaRamp(dc, values);
|
|
||||||
DeleteDC(dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->win32.publicAdapterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
|
|
||||||
{
|
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
return monitor->win32.publicDisplayName;
|
|
||||||
}
|
|
||||||
449
glfw/win32_platform.h
vendored
449
glfw/win32_platform.h
vendored
@@ -1,449 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
// We don't need all the fancy stuff
|
|
||||||
#ifndef NOMINMAX
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef VC_EXTRALEAN
|
|
||||||
#define VC_EXTRALEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
|
|
||||||
// example to allow applications to correctly declare a GL_ARB_debug_output
|
|
||||||
// callback) but windows.h assumes no one will define APIENTRY before it does
|
|
||||||
#undef APIENTRY
|
|
||||||
|
|
||||||
// GLFW on Windows is Unicode only and does not work in MBCS mode
|
|
||||||
#ifndef UNICODE
|
|
||||||
#define UNICODE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW requires Windows XP or later
|
|
||||||
#if WINVER < 0x0501
|
|
||||||
#undef WINVER
|
|
||||||
#define WINVER 0x0501
|
|
||||||
#endif
|
|
||||||
#if _WIN32_WINNT < 0x0501
|
|
||||||
#undef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x0501
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// GLFW uses DirectInput8 interfaces
|
|
||||||
#define DIRECTINPUT_VERSION 0x0800
|
|
||||||
|
|
||||||
#include <wctype.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <dinput.h>
|
|
||||||
#include <xinput.h>
|
|
||||||
#include <dbt.h>
|
|
||||||
|
|
||||||
// HACK: Define macros that some windows.h variants don't
|
|
||||||
#ifndef WM_MOUSEHWHEEL
|
|
||||||
#define WM_MOUSEHWHEEL 0x020E
|
|
||||||
#endif
|
|
||||||
#ifndef WM_DWMCOMPOSITIONCHANGED
|
|
||||||
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
|
||||||
#endif
|
|
||||||
#ifndef WM_COPYGLOBALDATA
|
|
||||||
#define WM_COPYGLOBALDATA 0x0049
|
|
||||||
#endif
|
|
||||||
#ifndef WM_UNICHAR
|
|
||||||
#define WM_UNICHAR 0x0109
|
|
||||||
#endif
|
|
||||||
#ifndef UNICODE_NOCHAR
|
|
||||||
#define UNICODE_NOCHAR 0xFFFF
|
|
||||||
#endif
|
|
||||||
#ifndef WM_DPICHANGED
|
|
||||||
#define WM_DPICHANGED 0x02E0
|
|
||||||
#endif
|
|
||||||
#ifndef GET_XBUTTON_WPARAM
|
|
||||||
#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
|
|
||||||
#endif
|
|
||||||
#ifndef EDS_ROTATEDMODE
|
|
||||||
#define EDS_ROTATEDMODE 0x00000004
|
|
||||||
#endif
|
|
||||||
#ifndef DISPLAY_DEVICE_ACTIVE
|
|
||||||
#define DISPLAY_DEVICE_ACTIVE 0x00000001
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32_WINNT_WINBLUE
|
|
||||||
#define _WIN32_WINNT_WINBLUE 0x0602
|
|
||||||
#endif
|
|
||||||
#ifndef WM_GETDPISCALEDSIZE
|
|
||||||
#define WM_GETDPISCALEDSIZE 0x02e4
|
|
||||||
#endif
|
|
||||||
#ifndef USER_DEFAULT_SCREEN_DPI
|
|
||||||
#define USER_DEFAULT_SCREEN_DPI 96
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WINVER < 0x0601
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD cbSize;
|
|
||||||
DWORD ExtStatus;
|
|
||||||
} CHANGEFILTERSTRUCT;
|
|
||||||
#ifndef MSGFLT_ALLOW
|
|
||||||
#define MSGFLT_ALLOW 1
|
|
||||||
#endif
|
|
||||||
#endif /*Windows 7*/
|
|
||||||
|
|
||||||
#if WINVER < 0x0600
|
|
||||||
#define DWM_BB_ENABLE 0x00000001
|
|
||||||
#define DWM_BB_BLURREGION 0x00000002
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DWORD dwFlags;
|
|
||||||
BOOL fEnable;
|
|
||||||
HRGN hRgnBlur;
|
|
||||||
BOOL fTransitionOnMaximized;
|
|
||||||
} DWM_BLURBEHIND;
|
|
||||||
#else
|
|
||||||
#include <dwmapi.h>
|
|
||||||
#endif /*Windows Vista*/
|
|
||||||
|
|
||||||
#ifndef DPI_ENUMS_DECLARED
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
PROCESS_DPI_UNAWARE = 0,
|
|
||||||
PROCESS_SYSTEM_DPI_AWARE = 1,
|
|
||||||
PROCESS_PER_MONITOR_DPI_AWARE = 2
|
|
||||||
} PROCESS_DPI_AWARENESS;
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MDT_EFFECTIVE_DPI = 0,
|
|
||||||
MDT_ANGULAR_DPI = 1,
|
|
||||||
MDT_RAW_DPI = 2,
|
|
||||||
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
|
||||||
} MONITOR_DPI_TYPE;
|
|
||||||
#endif /*DPI_ENUMS_DECLARED*/
|
|
||||||
|
|
||||||
#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
|
|
||||||
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
|
|
||||||
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT) -4)
|
|
||||||
#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
|
|
||||||
|
|
||||||
// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
|
|
||||||
#define IsWindowsXPOrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WINXP), 0)
|
|
||||||
#define IsWindowsVistaOrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA), \
|
|
||||||
LOBYTE(_WIN32_WINNT_VISTA), 0)
|
|
||||||
#define IsWindows7OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN7), 0)
|
|
||||||
#define IsWindows8OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WIN8), 0)
|
|
||||||
#define IsWindows8Point1OrGreater() \
|
|
||||||
_glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
|
|
||||||
LOBYTE(_WIN32_WINNT_WINBLUE), 0)
|
|
||||||
|
|
||||||
#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
|
|
||||||
_glfwIsWindows10BuildOrGreaterWin32(14393)
|
|
||||||
#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
|
|
||||||
_glfwIsWindows10BuildOrGreaterWin32(15063)
|
|
||||||
|
|
||||||
// HACK: Define macros that some xinput.h variants don't
|
|
||||||
#ifndef XINPUT_CAPS_WIRELESS
|
|
||||||
#define XINPUT_CAPS_WIRELESS 0x0002
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_WHEEL
|
|
||||||
#define XINPUT_DEVSUBTYPE_WHEEL 0x02
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
|
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
|
|
||||||
#define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
|
|
||||||
#define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_GUITAR
|
|
||||||
#define XINPUT_DEVSUBTYPE_GUITAR 0x06
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
|
|
||||||
#define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
|
|
||||||
#endif
|
|
||||||
#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
|
|
||||||
#define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
|
|
||||||
#endif
|
|
||||||
#ifndef XUSER_MAX_COUNT
|
|
||||||
#define XUSER_MAX_COUNT 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// HACK: Define macros that some dinput.h variants don't
|
|
||||||
#ifndef DIDFT_OPTIONAL
|
|
||||||
#define DIDFT_OPTIONAL 0x80000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// winmm.dll function pointer typedefs
|
|
||||||
typedef DWORD (WINAPI * PFN_timeGetTime)(void);
|
|
||||||
#define timeGetTime _glfw.win32.winmm.GetTime
|
|
||||||
|
|
||||||
// xinput.dll function pointer typedefs
|
|
||||||
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 * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
|
|
||||||
#define DirectInput8Create _glfw.win32.dinput8.Create
|
|
||||||
|
|
||||||
// user32.dll function pointer typedefs
|
|
||||||
typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
|
|
||||||
typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
|
|
||||||
typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
|
|
||||||
typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
|
|
||||||
typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
|
|
||||||
typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
|
||||||
#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
|
|
||||||
#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
|
|
||||||
#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
|
|
||||||
#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
|
|
||||||
#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
|
|
||||||
#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
|
|
||||||
|
|
||||||
// dwmapi.dll function pointer typedefs
|
|
||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
|
||||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
|
||||||
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
|
||||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
|
||||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
|
||||||
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
|
||||||
|
|
||||||
// shcore.dll function pointer typedefs
|
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
|
||||||
typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
|
|
||||||
#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
|
|
||||||
#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
|
|
||||||
|
|
||||||
// ntdll.dll function pointer typedefs
|
|
||||||
typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
|
|
||||||
#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
|
|
||||||
|
|
||||||
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
|
|
||||||
|
|
||||||
typedef struct VkWin32SurfaceCreateInfoKHR
|
|
||||||
{
|
|
||||||
VkStructureType sType;
|
|
||||||
const void* pNext;
|
|
||||||
VkWin32SurfaceCreateFlagsKHR flags;
|
|
||||||
HINSTANCE hinstance;
|
|
||||||
HWND hwnd;
|
|
||||||
} VkWin32SurfaceCreateInfoKHR;
|
|
||||||
|
|
||||||
typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
|
||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
|
|
||||||
|
|
||||||
#include "win32_joystick.h"
|
|
||||||
#include "wgl_context.h"
|
|
||||||
#include "egl_context.h"
|
|
||||||
#include "osmesa_context.h"
|
|
||||||
|
|
||||||
#if !defined(_GLFW_WNDCLASSNAME)
|
|
||||||
#define _GLFW_WNDCLASSNAME L"GLFW30"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _glfw_dlopen(name) LoadLibraryA(name)
|
|
||||||
#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
|
|
||||||
#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
|
|
||||||
|
|
||||||
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
|
|
||||||
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
|
|
||||||
#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
|
|
||||||
//
|
|
||||||
typedef struct _GLFWwindowWin32
|
|
||||||
{
|
|
||||||
HWND handle;
|
|
||||||
HICON bigIcon;
|
|
||||||
HICON smallIcon;
|
|
||||||
|
|
||||||
GLFWbool cursorTracked;
|
|
||||||
GLFWbool frameAction;
|
|
||||||
GLFWbool iconified;
|
|
||||||
GLFWbool maximized;
|
|
||||||
// Whether to enable framebuffer transparency on DWM
|
|
||||||
GLFWbool transparent;
|
|
||||||
GLFWbool scaleToMonitor;
|
|
||||||
|
|
||||||
// The last received cursor position, regardless of source
|
|
||||||
int lastCursorPosX, lastCursorPosY;
|
|
||||||
|
|
||||||
} _GLFWwindowWin32;
|
|
||||||
|
|
||||||
// Win32-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryWin32
|
|
||||||
{
|
|
||||||
HWND helperWindowHandle;
|
|
||||||
HDEVNOTIFY deviceNotificationHandle;
|
|
||||||
DWORD foregroundLockTimeout;
|
|
||||||
int acquiredMonitorCount;
|
|
||||||
char* clipboardString;
|
|
||||||
short int keycodes[512];
|
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
|
||||||
char keynames[GLFW_KEY_LAST + 1][5];
|
|
||||||
// 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;
|
|
||||||
UINT mouseTrailSize;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_timeGetTime GetTime;
|
|
||||||
} winmm;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_DirectInput8Create Create;
|
|
||||||
IDirectInput8W* api;
|
|
||||||
} dinput8;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_XInputGetCapabilities GetCapabilities;
|
|
||||||
PFN_XInputGetState GetState;
|
|
||||||
} xinput;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_SetProcessDPIAware SetProcessDPIAware_;
|
|
||||||
PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
|
|
||||||
PFN_EnableNonClientDpiScaling EnableNonClientDpiScaling_;
|
|
||||||
PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
|
|
||||||
PFN_GetDpiForWindow GetDpiForWindow_;
|
|
||||||
PFN_AdjustWindowRectExForDpi AdjustWindowRectExForDpi_;
|
|
||||||
} user32;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
|
||||||
PFN_DwmFlush Flush;
|
|
||||||
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
|
||||||
} dwmapi;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_SetProcessDpiAwareness SetProcessDpiAwareness_;
|
|
||||||
PFN_GetDpiForMonitor GetDpiForMonitor_;
|
|
||||||
} shcore;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo_;
|
|
||||||
} ntdll;
|
|
||||||
|
|
||||||
} _GLFWlibraryWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-monitor data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWmonitorWin32
|
|
||||||
{
|
|
||||||
HMONITOR handle;
|
|
||||||
// This size matches the static size of DISPLAY_DEVICE.DeviceName
|
|
||||||
WCHAR adapterName[32];
|
|
||||||
WCHAR displayName[32];
|
|
||||||
char publicAdapterName[32];
|
|
||||||
char publicDisplayName[32];
|
|
||||||
GLFWbool modesPruned;
|
|
||||||
GLFWbool modeChanged;
|
|
||||||
|
|
||||||
} _GLFWmonitorWin32;
|
|
||||||
|
|
||||||
// Win32-specific per-cursor data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcursorWin32
|
|
||||||
{
|
|
||||||
HCURSOR handle;
|
|
||||||
|
|
||||||
} _GLFWcursorWin32;
|
|
||||||
|
|
||||||
// Win32-specific global timer data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWtimerWin32
|
|
||||||
{
|
|
||||||
GLFWbool hasPC;
|
|
||||||
uint64_t frequency;
|
|
||||||
|
|
||||||
} _GLFWtimerWin32;
|
|
||||||
|
|
||||||
// Win32-specific thread local storage data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWtlsWin32
|
|
||||||
{
|
|
||||||
GLFWbool allocated;
|
|
||||||
DWORD index;
|
|
||||||
|
|
||||||
} _GLFWtlsWin32;
|
|
||||||
|
|
||||||
// Win32-specific mutex data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWmutexWin32
|
|
||||||
{
|
|
||||||
GLFWbool allocated;
|
|
||||||
CRITICAL_SECTION section;
|
|
||||||
|
|
||||||
} _GLFWmutexWin32;
|
|
||||||
|
|
||||||
|
|
||||||
GLFWbool _glfwRegisterWindowClassWin32(void);
|
|
||||||
void _glfwUnregisterWindowClassWin32(void);
|
|
||||||
|
|
||||||
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
|
|
||||||
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
|
|
||||||
BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
|
|
||||||
BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
|
|
||||||
void _glfwInputErrorWin32(int error, const char* description);
|
|
||||||
void _glfwUpdateKeyNamesWin32(void);
|
|
||||||
|
|
||||||
void _glfwInitTimerWin32(void);
|
|
||||||
|
|
||||||
void _glfwPollMonitorsWin32(void);
|
|
||||||
void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
|
||||||
void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
|
|
||||||
void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
|
|
||||||
97
glfw/win32_thread.c
vendored
97
glfw/win32_thread.c
vendored
@@ -1,97 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
74
glfw/win32_time.c
vendored
74
glfw/win32_time.c
vendored
@@ -1,74 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// 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"
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialise timer
|
|
||||||
//
|
|
||||||
void _glfwInitTimerWin32(void)
|
|
||||||
{
|
|
||||||
uint64_t frequency;
|
|
||||||
|
|
||||||
if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
|
|
||||||
{
|
|
||||||
_glfw.timer.win32.hasPC = GLFW_TRUE;
|
|
||||||
_glfw.timer.win32.frequency = frequency;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfw.timer.win32.hasPC = GLFW_FALSE;
|
|
||||||
_glfw.timer.win32.frequency = 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
|
||||||
{
|
|
||||||
if (_glfw.timer.win32.hasPC)
|
|
||||||
{
|
|
||||||
uint64_t value;
|
|
||||||
QueryPerformanceCounter((LARGE_INTEGER*) &value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (uint64_t) timeGetTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
|
||||||
{
|
|
||||||
return _glfw.timer.win32.frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
2197
glfw/win32_window.c
vendored
2197
glfw/win32_window.c
vendored
File diff suppressed because it is too large
Load Diff
161
glfw/window.c
vendored
161
glfw/window.c
vendored
@@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
// Notifies shared code that a window has lost or received input focus
|
// Notifies shared code that a window has lost or received input focus
|
||||||
//
|
//
|
||||||
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
|
void _glfwInputWindowFocus(_GLFWwindow* window, bool focused)
|
||||||
{
|
{
|
||||||
if (window->callbacks.focus)
|
if (window->callbacks.focus)
|
||||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||||
@@ -88,8 +88,16 @@ _GLFWwindow* _glfwWindowForId(GLFWid id) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window's occlusion state has changed
|
||||||
|
//
|
||||||
|
void _glfwInputWindowOcclusion(_GLFWwindow* window, bool occluded)
|
||||||
|
{
|
||||||
|
if (window->callbacks.occlusion)
|
||||||
|
window->callbacks.occlusion((GLFWwindow*) window, occluded);
|
||||||
|
}
|
||||||
|
|
||||||
// Notifies shared code that a window has moved
|
// Notifies shared code that a window has moved
|
||||||
// The position is specified in client-area relative screen coordinates
|
// The position is specified in content area relative screen coordinates
|
||||||
//
|
//
|
||||||
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
|
||||||
{
|
{
|
||||||
@@ -108,7 +116,7 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
|
|
||||||
// Notifies shared code that a window has been iconified or restored
|
// Notifies shared code that a window has been iconified or restored
|
||||||
//
|
//
|
||||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
void _glfwInputWindowIconify(_GLFWwindow* window, bool iconified)
|
||||||
{
|
{
|
||||||
if (window->callbacks.iconify)
|
if (window->callbacks.iconify)
|
||||||
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
window->callbacks.iconify((GLFWwindow*) window, iconified);
|
||||||
@@ -116,7 +124,7 @@ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
|
|||||||
|
|
||||||
// Notifies shared code that a window has been maximized or restored
|
// Notifies shared code that a window has been maximized or restored
|
||||||
//
|
//
|
||||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
void _glfwInputWindowMaximize(_GLFWwindow* window, bool maximized)
|
||||||
{
|
{
|
||||||
if (window->callbacks.maximize)
|
if (window->callbacks.maximize)
|
||||||
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
window->callbacks.maximize((GLFWwindow*) window, maximized);
|
||||||
@@ -131,6 +139,14 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
|
|||||||
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
window->callbacks.fbsize((GLFWwindow*) window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notifies shared code that a window live resize is in progress
|
||||||
|
//
|
||||||
|
void _glfwInputLiveResize(_GLFWwindow* window, bool started)
|
||||||
|
{
|
||||||
|
if (window && window->callbacks.liveResize)
|
||||||
|
window->callbacks.liveResize((GLFWwindow*) window, started);
|
||||||
|
}
|
||||||
|
|
||||||
// Notifies shared code that a window content scale has changed
|
// Notifies shared code that a window content scale has changed
|
||||||
// The scale is specified as the ratio between the current and default DPI
|
// The scale is specified as the ratio between the current and default DPI
|
||||||
//
|
//
|
||||||
@@ -152,7 +168,7 @@ void _glfwInputWindowDamage(_GLFWwindow* window)
|
|||||||
//
|
//
|
||||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
window->shouldClose = GLFW_TRUE;
|
window->shouldClose = true;
|
||||||
|
|
||||||
if (window->callbacks.close)
|
if (window->callbacks.close)
|
||||||
window->callbacks.close((GLFWwindow*) window);
|
window->callbacks.close((GLFWwindow*) window);
|
||||||
@@ -254,19 +270,17 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
{
|
{
|
||||||
if (wndconfig.centerCursor)
|
if (wndconfig.centerCursor)
|
||||||
{
|
_glfwCenterCursorInContentArea(window);
|
||||||
int width, height;
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
|
||||||
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wndconfig.visible)
|
if (wndconfig.visible)
|
||||||
{
|
{
|
||||||
_glfwPlatformShowWindow(window);
|
_glfwPlatformShowWindow(window);
|
||||||
|
#ifndef _GLFW_WAYLAND
|
||||||
if (wndconfig.focused)
|
if (wndconfig.focused)
|
||||||
_glfwPlatformFocusWindow(window);
|
_glfwPlatformFocusWindow(window);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,13 +300,13 @@ void glfwDefaultWindowHints(void)
|
|||||||
|
|
||||||
// The default is a focused, visible, resizable window with decorations
|
// The default is a focused, visible, resizable window with decorations
|
||||||
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
||||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
_glfw.hints.window.resizable = true;
|
||||||
_glfw.hints.window.visible = GLFW_TRUE;
|
_glfw.hints.window.visible = true;
|
||||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
_glfw.hints.window.decorated = true;
|
||||||
_glfw.hints.window.focused = GLFW_TRUE;
|
_glfw.hints.window.focused = true;
|
||||||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
_glfw.hints.window.autoIconify = true;
|
||||||
_glfw.hints.window.centerCursor = GLFW_TRUE;
|
_glfw.hints.window.centerCursor = true;
|
||||||
_glfw.hints.window.focusOnShow = GLFW_TRUE;
|
_glfw.hints.window.focusOnShow = true;
|
||||||
|
|
||||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||||
// double buffered
|
// double buffered
|
||||||
@@ -303,13 +317,13 @@ void glfwDefaultWindowHints(void)
|
|||||||
_glfw.hints.framebuffer.alphaBits = 8;
|
_glfw.hints.framebuffer.alphaBits = 8;
|
||||||
_glfw.hints.framebuffer.depthBits = 24;
|
_glfw.hints.framebuffer.depthBits = 24;
|
||||||
_glfw.hints.framebuffer.stencilBits = 8;
|
_glfw.hints.framebuffer.stencilBits = 8;
|
||||||
_glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
|
_glfw.hints.framebuffer.doublebuffer = true;
|
||||||
|
|
||||||
// The default is to select the highest available refresh rate
|
// The default is to select the highest available refresh rate
|
||||||
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
||||||
|
|
||||||
// The default is to use full Retina resolution framebuffers
|
// The default is to use full Retina resolution framebuffers
|
||||||
_glfw.hints.window.ns.retina = GLFW_TRUE;
|
_glfw.hints.window.ns.retina = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwWindowHint(int hint, int value)
|
GLFWAPI void glfwWindowHint(int hint, int value)
|
||||||
@@ -352,55 +366,55 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||||||
_glfw.hints.framebuffer.auxBuffers = value;
|
_glfw.hints.framebuffer.auxBuffers = value;
|
||||||
return;
|
return;
|
||||||
case GLFW_STEREO:
|
case GLFW_STEREO:
|
||||||
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.stereo = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_DOUBLEBUFFER:
|
case GLFW_DOUBLEBUFFER:
|
||||||
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.doublebuffer = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||||
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.transparent = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_SAMPLES:
|
case GLFW_SAMPLES:
|
||||||
_glfw.hints.framebuffer.samples = value;
|
_glfw.hints.framebuffer.samples = value;
|
||||||
return;
|
return;
|
||||||
case GLFW_SRGB_CAPABLE:
|
case GLFW_SRGB_CAPABLE:
|
||||||
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.framebuffer.sRGB = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.resizable = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.decorated = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_FOCUSED:
|
case GLFW_FOCUSED:
|
||||||
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.focused = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_AUTO_ICONIFY:
|
case GLFW_AUTO_ICONIFY:
|
||||||
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.autoIconify = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_FLOATING:
|
case GLFW_FLOATING:
|
||||||
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.floating = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_MAXIMIZED:
|
case GLFW_MAXIMIZED:
|
||||||
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.maximized = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_VISIBLE:
|
case GLFW_VISIBLE:
|
||||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.visible = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.ns.retina = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
||||||
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.nsgl.offline = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_SCALE_TO_MONITOR:
|
case GLFW_SCALE_TO_MONITOR:
|
||||||
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.scaleToMonitor = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_CENTER_CURSOR:
|
case GLFW_CENTER_CURSOR:
|
||||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.centerCursor = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_FOCUS_ON_SHOW:
|
case GLFW_FOCUS_ON_SHOW:
|
||||||
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.window.focusOnShow = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_CLIENT_API:
|
case GLFW_CLIENT_API:
|
||||||
_glfw.hints.context.client = value;
|
_glfw.hints.context.client = value;
|
||||||
@@ -418,13 +432,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
|||||||
_glfw.hints.context.robustness = value;
|
_glfw.hints.context.robustness = value;
|
||||||
return;
|
return;
|
||||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.forward = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.debug = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_CONTEXT_NO_ERROR:
|
case GLFW_CONTEXT_NO_ERROR:
|
||||||
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
_glfw.hints.context.noerror = value ? true : false;
|
||||||
return;
|
return;
|
||||||
case GLFW_OPENGL_PROFILE:
|
case GLFW_OPENGL_PROFILE:
|
||||||
_glfw.hints.context.profile = value;
|
_glfw.hints.context.profile = value;
|
||||||
@@ -801,8 +815,10 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
|||||||
|
|
||||||
_glfwPlatformShowWindow(window);
|
_glfwPlatformShowWindow(window);
|
||||||
|
|
||||||
|
#ifndef _GLFW_WAYLAND
|
||||||
if (window->focusOnShow)
|
if (window->focusOnShow)
|
||||||
_glfwPlatformFocusWindow(window);
|
_glfwPlatformFocusWindow(window);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||||
@@ -820,7 +836,7 @@ GLFWAPI int glfwWindowBell(GLFWwindow* handle)
|
|||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||||
|
|
||||||
return _glfwPlatformWindowBell(window);
|
return _glfwPlatformWindowBell(window);
|
||||||
}
|
}
|
||||||
@@ -871,6 +887,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
|||||||
return window->focusOnShow;
|
return window->focusOnShow;
|
||||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||||
return _glfwPlatformFramebufferTransparent(window);
|
return _glfwPlatformFramebufferTransparent(window);
|
||||||
|
case GLFW_OCCLUDED:
|
||||||
|
return _glfwPlatformWindowOccluded(window);
|
||||||
case GLFW_RESIZABLE:
|
case GLFW_RESIZABLE:
|
||||||
return window->resizable;
|
return window->resizable;
|
||||||
case GLFW_DECORATED:
|
case GLFW_DECORATED:
|
||||||
@@ -914,7 +932,7 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
|||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
value = value ? true : false;
|
||||||
|
|
||||||
if (attrib == GLFW_AUTO_ICONIFY)
|
if (attrib == GLFW_AUTO_ICONIFY)
|
||||||
window->autoIconify = value;
|
window->autoIconify = value;
|
||||||
@@ -999,6 +1017,12 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
|||||||
refreshRate);
|
refreshRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI bool glfwToggleFullscreen(GLFWwindow* wh, unsigned int flags) {
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) wh;
|
||||||
|
if (window) return _glfwPlatformToggleFullscreen(window, flags);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
|
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
@@ -1072,6 +1096,17 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWwindowocclusionfun glfwSetWindowOcclusionCallback(GLFWwindow* handle,
|
||||||
|
GLFWwindowocclusionfun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.occlusion, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
|
GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
|
||||||
GLFWwindowiconifyfun cbfun)
|
GLFWwindowiconifyfun cbfun)
|
||||||
{
|
{
|
||||||
@@ -1105,6 +1140,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWliveresizefun glfwSetLiveResizeCallback(GLFWwindow* handle,
|
||||||
|
GLFWliveresizefun cbfun)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
_GLFW_SWAP_POINTERS(window->callbacks.liveResize, cbfun);
|
||||||
|
return cbfun;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
|
GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
|
||||||
GLFWwindowcontentscalefun cbfun)
|
GLFWwindowcontentscalefun cbfun)
|
||||||
{
|
{
|
||||||
@@ -1116,44 +1162,9 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
|
|||||||
return cbfun;
|
return cbfun;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwPollEvents(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
_glfwPlatformPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwWaitEvents(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (!_glfw.windowListHead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_glfwPlatformWaitEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformWaitEventsTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwPostEmptyEvent(void)
|
GLFWAPI void glfwPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
if (!_glfw.windowListHead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|||||||
175
glfw/wl_init.c
vendored
175
glfw/wl_init.c
vendored
@@ -103,10 +103,10 @@ static void pointerHandleEnter(void* data,
|
|||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.pointerSerial = serial;
|
||||||
_glfw.wl.pointerFocus = window;
|
_glfw.wl.pointerFocus = window;
|
||||||
|
|
||||||
window->wl.hovered = GLFW_TRUE;
|
window->wl.hovered = true;
|
||||||
|
|
||||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
_glfwInputCursorEnter(window, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleLeave(void* data,
|
static void pointerHandleLeave(void* data,
|
||||||
@@ -119,28 +119,22 @@ static void pointerHandleLeave(void* data,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window->wl.hovered = GLFW_FALSE;
|
window->wl.hovered = false;
|
||||||
|
|
||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.pointerSerial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
_glfwInputCursorEnter(window, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setCursor(const char* name)
|
static void setCursor(GLFWCursorShape shape)
|
||||||
{
|
{
|
||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
struct wl_cursor* cursor;
|
struct wl_cursor* cursor;
|
||||||
struct wl_cursor_image* image;
|
struct wl_cursor_image* image;
|
||||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||||
|
|
||||||
cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
cursor = _glfwLoadCursor(shape);
|
||||||
name);
|
if (!cursor) return;
|
||||||
if (!cursor)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Standard cursor not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: handle animated cursors too.
|
// TODO: handle animated cursors too.
|
||||||
image = cursor->images[0];
|
image = cursor->images[0];
|
||||||
|
|
||||||
@@ -167,56 +161,51 @@ static void pointerHandleMotion(void* data,
|
|||||||
wl_fixed_t sy)
|
wl_fixed_t sy)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
const char* cursorName = NULL;
|
GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR;
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
return;
|
return;
|
||||||
else
|
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||||
{
|
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||||
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
|
||||||
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (window->wl.decorations.focus)
|
switch (window->wl.decorations.focus)
|
||||||
{
|
{
|
||||||
case mainWindow:
|
case mainWindow:
|
||||||
_glfwInputCursorPos(window,
|
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||||
wl_fixed_to_double(sx),
|
|
||||||
wl_fixed_to_double(sy));
|
|
||||||
return;
|
return;
|
||||||
case topDecoration:
|
case topDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
cursorName = "n-resize";
|
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorName = "left_ptr";
|
cursorShape = GLFW_ARROW_CURSOR;
|
||||||
break;
|
break;
|
||||||
case leftDecoration:
|
case leftDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
cursorName = "nw-resize";
|
cursorShape = GLFW_NW_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorName = "w-resize";
|
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||||
break;
|
break;
|
||||||
case rightDecoration:
|
case rightDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
cursorName = "ne-resize";
|
cursorShape = GLFW_NE_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorName = "e-resize";
|
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||||
break;
|
break;
|
||||||
case bottomDecoration:
|
case bottomDecoration:
|
||||||
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
|
||||||
cursorName = "sw-resize";
|
cursorShape = GLFW_SW_RESIZE_CURSOR;
|
||||||
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
|
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
|
||||||
cursorName = "se-resize";
|
cursorShape = GLFW_SE_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorName = "s-resize";
|
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
setCursor(cursorName);
|
setCursor(cursorShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleButton(void* data,
|
static void pointerHandleButton(void* data,
|
||||||
@@ -229,8 +218,7 @@ static void pointerHandleButton(void* data,
|
|||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
int glfwButton;
|
int glfwButton;
|
||||||
|
|
||||||
// Both xdg-shell and wl_shell use the same values.
|
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||||
uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
|
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
@@ -242,46 +230,40 @@ static void pointerHandleButton(void* data,
|
|||||||
break;
|
break;
|
||||||
case topDecoration:
|
case topDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_TOP;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
||||||
else
|
|
||||||
wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case leftDecoration:
|
case leftDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
|
||||||
else
|
else
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_LEFT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
||||||
break;
|
break;
|
||||||
case rightDecoration:
|
case rightDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
|
||||||
else
|
else
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
||||||
break;
|
break;
|
||||||
case bottomDecoration:
|
case bottomDecoration:
|
||||||
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
|
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
|
||||||
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
|
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||||
else
|
else
|
||||||
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
|
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
|
||||||
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
|
serial, edges);
|
||||||
serial, edges);
|
|
||||||
else
|
|
||||||
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
|
|
||||||
serial, edges);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (button == BTN_RIGHT)
|
else if (button == BTN_RIGHT)
|
||||||
@@ -388,7 +370,7 @@ static void keyboardHandleEnter(void* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.keyboardFocus = window;
|
_glfw.wl.keyboardFocus = window;
|
||||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
_glfwInputWindowFocus(window, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleLeave(void* data,
|
static void keyboardHandleLeave(void* data,
|
||||||
@@ -402,7 +384,7 @@ static void keyboardHandleLeave(void* data,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_glfw.wl.keyboardFocus = NULL;
|
_glfw.wl.keyboardFocus = NULL;
|
||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -426,12 +408,12 @@ static void keyboardHandleKey(void* data,
|
|||||||
return;
|
return;
|
||||||
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
||||||
GLFWbool repeatable = GLFW_FALSE;
|
bool repeatable = false;
|
||||||
|
|
||||||
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
|
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
|
||||||
{
|
{
|
||||||
_glfw.wl.keyRepeatInfo.key = key;
|
_glfw.wl.keyRepeatInfo.key = key;
|
||||||
repeatable = GLFW_TRUE;
|
repeatable = true;
|
||||||
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
||||||
}
|
}
|
||||||
if (repeatable) {
|
if (repeatable) {
|
||||||
@@ -544,11 +526,6 @@ static void registryHandleGlobal(void* data,
|
|||||||
_glfw.wl.shm =
|
_glfw.wl.shm =
|
||||||
wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
wl_registry_bind(registry, name, &wl_shm_interface, 1);
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, "wl_shell") == 0)
|
|
||||||
{
|
|
||||||
_glfw.wl.shell =
|
|
||||||
wl_registry_bind(registry, name, &wl_shell_interface, 1);
|
|
||||||
}
|
|
||||||
else if (strcmp(interface, "wl_output") == 0)
|
else if (strcmp(interface, "wl_output") == 0)
|
||||||
{
|
{
|
||||||
_glfwAddOutputWayland(name, version);
|
_glfwAddOutputWayland(name, version);
|
||||||
@@ -636,14 +613,20 @@ static void registryHandleGlobalRemove(void *data,
|
|||||||
struct wl_registry *registry,
|
struct wl_registry *registry,
|
||||||
uint32_t name)
|
uint32_t name)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
_GLFWmonitor* monitor;
|
_GLFWmonitor* monitor;
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; ++i)
|
for (int i = 0; i < _glfw.monitorCount; ++i)
|
||||||
{
|
{
|
||||||
monitor = _glfw.monitors[i];
|
monitor = _glfw.monitors[i];
|
||||||
if (monitor->wl.name == name)
|
if (monitor->wl.name == name)
|
||||||
{
|
{
|
||||||
|
for (_GLFWwindow *window = _glfw.windowListHead; window; window = window->next) {
|
||||||
|
for (int m = window->wl.monitorsCount - 1; m >= 0; m--) {
|
||||||
|
if (window->wl.monitors[m] == monitor) {
|
||||||
|
remove_i_from_array(window->wl.monitors, m, window->wl.monitorsCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
|
_glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -657,6 +640,39 @@ static const struct wl_registry_listener registryListener = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void registry_handle_global(void* data,
|
||||||
|
struct wl_registry* registry,
|
||||||
|
uint32_t name,
|
||||||
|
const char* interface,
|
||||||
|
uint32_t version) {
|
||||||
|
if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
||||||
|
bool *has_ssd = (bool*)data;
|
||||||
|
if (has_ssd) *has_ssd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void registry_handle_global_remove(void *data,
|
||||||
|
struct wl_registry *registry,
|
||||||
|
uint32_t name) {}
|
||||||
|
GLFWAPI const char*
|
||||||
|
glfwWaylandCheckForServerSideDecorations(void) {
|
||||||
|
struct wl_display *display = wl_display_connect(NULL);
|
||||||
|
if (!display) return "ERR: Failed to connect to Wayland display";
|
||||||
|
static const struct wl_registry_listener rl = {
|
||||||
|
registry_handle_global, registry_handle_global_remove
|
||||||
|
};
|
||||||
|
struct wl_registry *registry = wl_display_get_registry(display);
|
||||||
|
bool has_ssd = false;
|
||||||
|
wl_registry_add_listener(registry, &rl, &has_ssd);
|
||||||
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
|
wl_registry_destroy(registry);
|
||||||
|
wl_display_flush(display);
|
||||||
|
wl_display_flush(display);
|
||||||
|
return has_ssd ? "YES" : "NO";
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -667,7 +683,7 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: failed to create self pipe");
|
"Wayland: failed to create self pipe");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
||||||
@@ -675,7 +691,7 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to open libwayland-cursor");
|
"Wayland: Failed to open libwayland-cursor");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
|
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
|
||||||
@@ -692,7 +708,7 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to open libwayland-egl");
|
"Wayland: Failed to open libwayland-egl");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
|
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
|
||||||
@@ -707,17 +723,17 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Failed to connect to display");
|
"Wayland: Failed to connect to display");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
initPollData(&_glfw.wl.eventLoopData, _glfw.wl.eventLoopData.wakeupFds[0], wl_display_get_fd(_glfw.wl.display));
|
initPollData(&_glfw.wl.eventLoopData, _glfw.wl.eventLoopData.wakeupFds[0], wl_display_get_fd(_glfw.wl.display));
|
||||||
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
|
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
|
||||||
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", 0.5, 0, dispatchPendingKeyRepeats, NULL);
|
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", 0.5, 0, true, dispatchPendingKeyRepeats, NULL, NULL);
|
||||||
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, animateCursorImage, NULL);
|
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, true, animateCursorImage, NULL, NULL);
|
||||||
|
|
||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
if (!glfw_xkb_create_context(&_glfw.wl.xkb)) return GLFW_FALSE;
|
if (!glfw_xkb_create_context(&_glfw.wl.xkb)) return false;
|
||||||
|
|
||||||
// Sync so we got all registry objects
|
// Sync so we got all registry objects
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
@@ -728,13 +744,19 @@ int _glfwPlatformInit(void)
|
|||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (_glfw.hints.init.enableJoysticks) {
|
if (_glfw.hints.init.enableJoysticks) {
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
if (!_glfw.wl.wmBase)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to find xdg-shell in your compositor");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (_glfw.wl.pointer && _glfw.wl.shm)
|
if (_glfw.wl.shm)
|
||||||
{
|
{
|
||||||
const char *cursorTheme = getenv("XCURSOR_THEME"), *cursorSizeStr = getenv("XCURSOR_SIZE");
|
const char *cursorTheme = getenv("XCURSOR_THEME"), *cursorSizeStr = getenv("XCURSOR_SIZE");
|
||||||
char *cursorSizeEnd;
|
char *cursorSizeEnd;
|
||||||
@@ -751,13 +773,13 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Unable to load default cursor theme");
|
"Wayland: Unable to load default cursor theme");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
_glfw.wl.cursorSurface =
|
_glfw.wl.cursorSurface =
|
||||||
wl_compositor_create_surface(_glfw.wl.compositor);
|
wl_compositor_create_surface(_glfw.wl.compositor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
@@ -791,8 +813,6 @@ void _glfwPlatformTerminate(void)
|
|||||||
wl_compositor_destroy(_glfw.wl.compositor);
|
wl_compositor_destroy(_glfw.wl.compositor);
|
||||||
if (_glfw.wl.shm)
|
if (_glfw.wl.shm)
|
||||||
wl_shm_destroy(_glfw.wl.shm);
|
wl_shm_destroy(_glfw.wl.shm);
|
||||||
if (_glfw.wl.shell)
|
|
||||||
wl_shell_destroy(_glfw.wl.shell);
|
|
||||||
if (_glfw.wl.viewporter)
|
if (_glfw.wl.viewporter)
|
||||||
wp_viewporter_destroy(_glfw.wl.viewporter);
|
wp_viewporter_destroy(_glfw.wl.viewporter);
|
||||||
if (_glfw.wl.decorationManager)
|
if (_glfw.wl.decorationManager)
|
||||||
@@ -842,7 +862,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " Wayland EGL"
|
return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
|
||||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
" clock_gettime"
|
" clock_gettime"
|
||||||
#else
|
#else
|
||||||
@@ -854,3 +874,6 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLFW_LOOP_BACKEND wl
|
||||||
|
#include "main_loop.h"
|
||||||
|
|||||||
26
glfw/wl_monitor.c
vendored
26
glfw/wl_monitor.c
vendored
@@ -30,6 +30,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
static void outputHandleGeometry(void* data,
|
static void outputHandleGeometry(void* data,
|
||||||
@@ -70,7 +71,7 @@ static void outputHandleMode(void* data,
|
|||||||
mode.redBits = 8;
|
mode.redBits = 8;
|
||||||
mode.greenBits = 8;
|
mode.greenBits = 8;
|
||||||
mode.blueBits = 8;
|
mode.blueBits = 8;
|
||||||
mode.refreshRate = refresh / 1000;
|
mode.refreshRate = (int)round(refresh / 1000.0);
|
||||||
|
|
||||||
monitor->modeCount++;
|
monitor->modeCount++;
|
||||||
monitor->modes =
|
monitor->modes =
|
||||||
@@ -84,6 +85,9 @@ static void outputHandleMode(void* data,
|
|||||||
static void outputHandleDone(void* data, struct wl_output* output)
|
static void outputHandleDone(void* data, struct wl_output* output)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
for (int i = 0; i < _glfw.monitorCount; i++) {
|
||||||
|
if (_glfw.monitors[i] == monitor) return;
|
||||||
|
}
|
||||||
|
|
||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
}
|
}
|
||||||
@@ -93,8 +97,8 @@ static void outputHandleScale(void* data,
|
|||||||
int32_t factor)
|
int32_t factor)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
|
if (factor > 0 && factor < 24)
|
||||||
monitor->wl.scale = factor;
|
monitor->wl.scale = factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_output_listener outputListener = {
|
static const struct wl_output_listener outputListener = {
|
||||||
@@ -169,6 +173,18 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = (float) monitor->wl.scale;
|
*yscale = (float) monitor->wl.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||||
|
{
|
||||||
|
if (xpos)
|
||||||
|
*xpos = monitor->wl.x;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = monitor->wl.y;
|
||||||
|
if (width)
|
||||||
|
*width = monitor->modes[monitor->wl.currentMode].width;
|
||||||
|
if (height)
|
||||||
|
*height = monitor->modes[monitor->wl.currentMode].height;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||||
{
|
{
|
||||||
*found = monitor->modeCount;
|
*found = monitor->modeCount;
|
||||||
@@ -180,11 +196,11 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
*mode = monitor->modes[monitor->wl.currentMode];
|
*mode = monitor->modes[monitor->wl.currentMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Gamma ramp access is not available");
|
"Wayland: Gamma ramp access is not available");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
|
|||||||
20
glfw/wl_platform.h
vendored
20
glfw/wl_platform.h
vendored
@@ -133,13 +133,12 @@ typedef struct _GLFWdecorationWayland
|
|||||||
typedef struct _GLFWwindowWayland
|
typedef struct _GLFWwindowWayland
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
GLFWbool visible;
|
bool visible;
|
||||||
GLFWbool maximized;
|
bool maximized;
|
||||||
GLFWbool hovered;
|
bool hovered;
|
||||||
GLFWbool transparent;
|
bool transparent;
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
struct wl_egl_window* native;
|
struct wl_egl_window* native;
|
||||||
struct wl_shell_surface* shellSurface;
|
|
||||||
struct wl_callback* callback;
|
struct wl_callback* callback;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -168,11 +167,10 @@ typedef struct _GLFWwindowWayland
|
|||||||
|
|
||||||
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||||
|
|
||||||
// This is a hack to prevent auto-iconification on creation.
|
bool fullscreened;
|
||||||
GLFWbool justCreated;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool serverSide;
|
bool serverSide;
|
||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
_GLFWdecorationWayland top, left, right, bottom;
|
_GLFWdecorationWayland top, left, right, bottom;
|
||||||
int focus;
|
int focus;
|
||||||
@@ -227,7 +225,6 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_registry* registry;
|
struct wl_registry* registry;
|
||||||
struct wl_compositor* compositor;
|
struct wl_compositor* compositor;
|
||||||
struct wl_subcompositor* subcompositor;
|
struct wl_subcompositor* subcompositor;
|
||||||
struct wl_shell* shell;
|
|
||||||
struct wl_shm* shm;
|
struct wl_shm* shm;
|
||||||
struct wl_seat* seat;
|
struct wl_seat* seat;
|
||||||
struct wl_pointer* pointer;
|
struct wl_pointer* pointer;
|
||||||
@@ -320,6 +317,7 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
|
|
||||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
void _glfwSetupWaylandDataDevice();
|
void _glfwSetupWaylandDataDevice(void);
|
||||||
void _glfwSetupWaylandPrimarySelectionDevice();
|
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
||||||
void animateCursorImage(id_type timer_id, void *data);
|
void animateCursorImage(id_type timer_id, void *data);
|
||||||
|
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape);
|
||||||
|
|||||||
720
glfw/wl_window.c
vendored
720
glfw/wl_window.c
vendored
File diff suppressed because it is too large
Load Diff
51
glfw/x11_init.c
vendored
51
glfw/x11_init.c
vendored
@@ -137,6 +137,10 @@ static void detectEWMH(void)
|
|||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");
|
||||||
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
_glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL");
|
||||||
|
_glfw.x11.NET_WORKAREA =
|
||||||
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
|
||||||
|
_glfw.x11.NET_CURRENT_DESKTOP =
|
||||||
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
|
||||||
_glfw.x11.NET_ACTIVE_WINDOW =
|
_glfw.x11.NET_ACTIVE_WINDOW =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||||
_glfw.x11.NET_FRAME_EXTENTS =
|
_glfw.x11.NET_FRAME_EXTENTS =
|
||||||
@@ -150,7 +154,7 @@ static void detectEWMH(void)
|
|||||||
|
|
||||||
// Look for and initialize supported X11 extensions
|
// Look for and initialize supported X11 extensions
|
||||||
//
|
//
|
||||||
static GLFWbool initExtensions(void)
|
static bool initExtensions(void)
|
||||||
{
|
{
|
||||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
||||||
if (_glfw.x11.vidmode.handle)
|
if (_glfw.x11.vidmode.handle)
|
||||||
@@ -195,7 +199,7 @@ static GLFWbool initExtensions(void)
|
|||||||
&_glfw.x11.xi.major,
|
&_glfw.x11.xi.major,
|
||||||
&_glfw.x11.xi.minor) == Success)
|
&_glfw.x11.xi.minor) == Success)
|
||||||
{
|
{
|
||||||
_glfw.x11.xi.available = GLFW_TRUE;
|
_glfw.x11.xi.available = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,7 +258,7 @@ static GLFWbool initExtensions(void)
|
|||||||
{
|
{
|
||||||
// The GLFW RandR path requires at least version 1.3
|
// The GLFW RandR path requires at least version 1.3
|
||||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||||
_glfw.x11.randr.available = GLFW_TRUE;
|
_glfw.x11.randr.available = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -273,14 +277,14 @@ static GLFWbool initExtensions(void)
|
|||||||
{
|
{
|
||||||
// This is likely an older Nvidia driver with broken gamma support
|
// This is likely an older Nvidia driver with broken gamma support
|
||||||
// Flag it as useless and fall back to xf86vm gamma, if available
|
// Flag it as useless and fall back to xf86vm gamma, if available
|
||||||
_glfw.x11.randr.gammaBroken = GLFW_TRUE;
|
_glfw.x11.randr.gammaBroken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sr->ncrtc)
|
if (!sr->ncrtc)
|
||||||
{
|
{
|
||||||
// A system without CRTCs is likely a system with broken RandR
|
// A system without CRTCs is likely a system with broken RandR
|
||||||
// Disable the RandR monitor path and fall back to core functions
|
// Disable the RandR monitor path and fall back to core functions
|
||||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
_glfw.x11.randr.monitorBroken = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRRFreeScreenResources(sr);
|
XRRFreeScreenResources(sr);
|
||||||
@@ -326,7 +330,7 @@ static GLFWbool initExtensions(void)
|
|||||||
&_glfw.x11.xinerama.minor))
|
&_glfw.x11.xinerama.minor))
|
||||||
{
|
{
|
||||||
if (XineramaIsActive(_glfw.x11.display))
|
if (XineramaIsActive(_glfw.x11.display))
|
||||||
_glfw.x11.xinerama.available = GLFW_TRUE;
|
_glfw.x11.xinerama.available = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +356,7 @@ static GLFWbool initExtensions(void)
|
|||||||
&_glfw.x11.xrender.major,
|
&_glfw.x11.xrender.major,
|
||||||
&_glfw.x11.xrender.minor))
|
&_glfw.x11.xrender.minor))
|
||||||
{
|
{
|
||||||
_glfw.x11.xrender.available = GLFW_TRUE;
|
_glfw.x11.xrender.available = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,19 +373,19 @@ static GLFWbool initExtensions(void)
|
|||||||
if (!_glfw.x11.xkb.available)
|
if (!_glfw.x11.xkb.available)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xkb extension");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xkb extension");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
Bool supported;
|
Bool supported;
|
||||||
if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported))
|
if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported))
|
||||||
{
|
{
|
||||||
if (supported)
|
if (supported)
|
||||||
_glfw.x11.xkb.detectable = GLFW_TRUE;
|
_glfw.x11.xkb.detectable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!glfw_xkb_set_x11_events_mask()) return GLFW_FALSE;
|
if (!glfw_xkb_set_x11_events_mask()) return false;
|
||||||
if (!glfw_xkb_create_context(&_glfw.x11.xkb)) return GLFW_FALSE;
|
if (!glfw_xkb_create_context(&_glfw.x11.xkb)) return false;
|
||||||
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return GLFW_FALSE;
|
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return false;
|
||||||
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return GLFW_FALSE;
|
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return false;
|
||||||
|
|
||||||
// Detect whether an EWMH-conformant window manager is running
|
// Detect whether an EWMH-conformant window manager is running
|
||||||
detectEWMH();
|
detectEWMH();
|
||||||
@@ -453,12 +457,12 @@ static GLFWbool initExtensions(void)
|
|||||||
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
|
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve system content scale via folklore heuristics
|
// Retrieve system content scale via folklore heuristics
|
||||||
//
|
//
|
||||||
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, GLFWbool bypass_cache)
|
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cache)
|
||||||
{
|
{
|
||||||
// NOTE: Default to the display-wide DPI as we don't currently have a policy
|
// NOTE: Default to the display-wide DPI as we don't currently have a policy
|
||||||
// for which monitor a window is considered to be on
|
// for which monitor a window is considered to be on
|
||||||
@@ -620,7 +624,7 @@ int _glfwPlatformInit(void)
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: failed to create self pipe");
|
"X11: failed to create self pipe");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.x11.display = XOpenDisplay(NULL);
|
_glfw.x11.display = XOpenDisplay(NULL);
|
||||||
@@ -638,7 +642,7 @@ int _glfwPlatformInit(void)
|
|||||||
"X11: The DISPLAY environment variable is missing");
|
"X11: The DISPLAY environment variable is missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
initPollData(&_glfw.x11.eventLoopData, _glfw.x11.eventLoopData.wakeupFds[0], ConnectionNumber(_glfw.x11.display));
|
initPollData(&_glfw.x11.eventLoopData, _glfw.x11.eventLoopData.wakeupFds[0], ConnectionNumber(_glfw.x11.display));
|
||||||
@@ -650,10 +654,10 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.x11.RESOURCE_MANAGER = XInternAtom(_glfw.x11.display, "RESOURCE_MANAGER", True);
|
_glfw.x11.RESOURCE_MANAGER = XInternAtom(_glfw.x11.display, "RESOURCE_MANAGER", True);
|
||||||
XSelectInput(_glfw.x11.display, _glfw.x11.root, PropertyChangeMask);
|
XSelectInput(_glfw.x11.display, _glfw.x11.root, PropertyChangeMask);
|
||||||
|
|
||||||
_glfwGetSystemContentScaleX11(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY, GLFW_FALSE);
|
_glfwGetSystemContentScaleX11(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY, false);
|
||||||
|
|
||||||
if (!initExtensions())
|
if (!initExtensions())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||||
@@ -661,7 +665,7 @@ int _glfwPlatformInit(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
if (_glfw.hints.init.enableJoysticks) {
|
if (_glfw.hints.init.enableJoysticks) {
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (_glfw.linjs.inotify > 0)
|
if (_glfw.linjs.inotify > 0)
|
||||||
addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL);
|
addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL);
|
||||||
}
|
}
|
||||||
@@ -670,11 +674,12 @@ int _glfwPlatformInit(void)
|
|||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
_glfwPollMonitorsX11();
|
_glfwPollMonitorsX11();
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
|
removeAllTimers(&_glfw.x11.eventLoopData);
|
||||||
if (_glfw.x11.helperWindowHandle)
|
if (_glfw.x11.helperWindowHandle)
|
||||||
{
|
{
|
||||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||||
@@ -754,7 +759,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " X11 GLX EGL"
|
return _GLFW_VERSION_NUMBER " X11 GLX EGL OSMesa"
|
||||||
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
|
||||||
" clock_gettime"
|
" clock_gettime"
|
||||||
#else
|
#else
|
||||||
@@ -768,3 +773,5 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "main_loop.h"
|
||||||
|
|||||||
107
glfw/x11_monitor.c
vendored
107
glfw/x11_monitor.c
vendored
@@ -30,11 +30,12 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
// Check whether the display mode should be included in enumeration
|
// Check whether the display mode should be included in enumeration
|
||||||
//
|
//
|
||||||
static GLFWbool modeIsGood(const XRRModeInfo* mi)
|
static bool modeIsGood(const XRRModeInfo* mi)
|
||||||
{
|
{
|
||||||
return (mi->modeFlags & RR_Interlace) == 0;
|
return (mi->modeFlags & RR_Interlace) == 0;
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ static GLFWbool modeIsGood(const XRRModeInfo* mi)
|
|||||||
static int calculateRefreshRate(const XRRModeInfo* mi)
|
static int calculateRefreshRate(const XRRModeInfo* mi)
|
||||||
{
|
{
|
||||||
if (mi->hTotal && mi->vTotal)
|
if (mi->hTotal && mi->vTotal)
|
||||||
return (int) ((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
|
return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -348,6 +349,100 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = _glfw.x11.contentScaleY;
|
*yscale = _glfw.x11.contentScaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||||
|
{
|
||||||
|
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
|
||||||
|
|
||||||
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
|
{
|
||||||
|
XRRScreenResources* sr;
|
||||||
|
XRRCrtcInfo* ci;
|
||||||
|
|
||||||
|
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
|
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
|
areaX = ci->x;
|
||||||
|
areaY = ci->y;
|
||||||
|
|
||||||
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
|
|
||||||
|
if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
|
||||||
|
{
|
||||||
|
areaWidth = mi->height;
|
||||||
|
areaHeight = mi->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
areaWidth = mi->width;
|
||||||
|
areaHeight = mi->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
XRRFreeCrtcInfo(ci);
|
||||||
|
XRRFreeScreenResources(sr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
areaWidth = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
|
||||||
|
{
|
||||||
|
Atom* extents = NULL;
|
||||||
|
Atom* desktop = NULL;
|
||||||
|
const unsigned long extentCount =
|
||||||
|
_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
|
_glfw.x11.NET_WORKAREA,
|
||||||
|
XA_CARDINAL,
|
||||||
|
(unsigned char**) &extents);
|
||||||
|
|
||||||
|
if (_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
|
_glfw.x11.NET_CURRENT_DESKTOP,
|
||||||
|
XA_CARDINAL,
|
||||||
|
(unsigned char**) &desktop) > 0)
|
||||||
|
{
|
||||||
|
if (extentCount >= 4 && *desktop < extentCount / 4)
|
||||||
|
{
|
||||||
|
const int globalX = extents[*desktop * 4 + 0];
|
||||||
|
const int globalY = extents[*desktop * 4 + 1];
|
||||||
|
const int globalWidth = extents[*desktop * 4 + 2];
|
||||||
|
const int globalHeight = extents[*desktop * 4 + 3];
|
||||||
|
|
||||||
|
if (areaX < globalX)
|
||||||
|
{
|
||||||
|
areaWidth -= globalX - areaX;
|
||||||
|
areaX = globalX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaY < globalY)
|
||||||
|
{
|
||||||
|
areaHeight -= globalY - areaY;
|
||||||
|
areaY = globalY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaX + areaWidth > globalX + globalWidth)
|
||||||
|
areaWidth = globalX - areaX + globalWidth;
|
||||||
|
if (areaY + areaHeight > globalY + globalHeight)
|
||||||
|
areaHeight = globalY - areaY + globalHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extents)
|
||||||
|
XFree(extents);
|
||||||
|
if (desktop)
|
||||||
|
XFree(desktop);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xpos)
|
||||||
|
*xpos = areaX;
|
||||||
|
if (ypos)
|
||||||
|
*ypos = areaY;
|
||||||
|
if (width)
|
||||||
|
*width = areaWidth;
|
||||||
|
if (height)
|
||||||
|
*height = areaHeight;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
GLFWvidmode* result;
|
GLFWvidmode* result;
|
||||||
@@ -433,7 +528,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||||
{
|
{
|
||||||
@@ -449,7 +544,7 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||||
|
|
||||||
XRRFreeGamma(gamma);
|
XRRFreeGamma(gamma);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
else if (_glfw.x11.vidmode.available)
|
else if (_glfw.x11.vidmode.available)
|
||||||
{
|
{
|
||||||
@@ -461,13 +556,13 @@ GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
XF86VidModeGetGammaRamp(_glfw.x11.display,
|
XF86VidModeGetGammaRamp(_glfw.x11.display,
|
||||||
_glfw.x11.screen,
|
_glfw.x11.screen,
|
||||||
ramp->size, ramp->red, ramp->green, ramp->blue);
|
ramp->size, ramp->red, ramp->green, ramp->blue);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Gamma ramp access not supported by server");
|
"X11: Gamma ramp access not supported by server");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
glfw/x11_platform.h
vendored
27
glfw/x11_platform.h
vendored
@@ -182,12 +182,11 @@ typedef struct _GLFWwindowX11
|
|||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
Window handle;
|
Window handle;
|
||||||
|
|
||||||
GLFWbool overrideRedirect;
|
bool iconified;
|
||||||
GLFWbool iconified;
|
bool maximized;
|
||||||
GLFWbool maximized;
|
|
||||||
|
|
||||||
// Whether the visual supports framebuffer transparency
|
// Whether the visual supports framebuffer transparency
|
||||||
GLFWbool transparent;
|
bool transparent;
|
||||||
|
|
||||||
// Cached position and size used to filter out duplicate events
|
// Cached position and size used to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -248,6 +247,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom NET_WM_FULLSCREEN_MONITORS;
|
Atom NET_WM_FULLSCREEN_MONITORS;
|
||||||
Atom NET_WM_WINDOW_OPACITY;
|
Atom NET_WM_WINDOW_OPACITY;
|
||||||
Atom NET_WM_CM_Sx;
|
Atom NET_WM_CM_Sx;
|
||||||
|
Atom NET_WORKAREA;
|
||||||
|
Atom NET_CURRENT_DESKTOP;
|
||||||
Atom NET_ACTIVE_WINDOW;
|
Atom NET_ACTIVE_WINDOW;
|
||||||
Atom NET_FRAME_EXTENTS;
|
Atom NET_FRAME_EXTENTS;
|
||||||
Atom NET_REQUEST_FRAME_EXTENTS;
|
Atom NET_REQUEST_FRAME_EXTENTS;
|
||||||
@@ -283,14 +284,14 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom RESOURCE_MANAGER;
|
Atom RESOURCE_MANAGER;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
GLFWbool gammaBroken;
|
bool gammaBroken;
|
||||||
GLFWbool monitorBroken;
|
bool monitorBroken;
|
||||||
PFN_XRRAllocGamma AllocGamma;
|
PFN_XRRAllocGamma AllocGamma;
|
||||||
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
||||||
PFN_XRRFreeGamma FreeGamma;
|
PFN_XRRFreeGamma FreeGamma;
|
||||||
@@ -335,7 +336,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xcursor;
|
} xcursor;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
@@ -345,7 +346,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xinerama;
|
} xinerama;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
@@ -356,7 +357,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} vidmode;
|
} vidmode;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
@@ -368,7 +369,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xi;
|
} xi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GLFWbool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
@@ -415,11 +416,11 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
|||||||
Atom property,
|
Atom property,
|
||||||
Atom type,
|
Atom type,
|
||||||
unsigned char** value);
|
unsigned char** value);
|
||||||
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
|
bool _glfwIsVisualTransparentX11(Visual* visual);
|
||||||
|
|
||||||
void _glfwGrabErrorHandlerX11(void);
|
void _glfwGrabErrorHandlerX11(void);
|
||||||
void _glfwReleaseErrorHandlerX11(void);
|
void _glfwReleaseErrorHandlerX11(void);
|
||||||
void _glfwInputErrorX11(int error, const char* message);
|
void _glfwInputErrorX11(int error, const char* message);
|
||||||
|
|
||||||
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, GLFWbool bypass_cache);
|
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cache);
|
||||||
void _glfwPushSelectionToManagerX11(void);
|
void _glfwPushSelectionToManagerX11(void);
|
||||||
|
|||||||
408
glfw/x11_window.c
vendored
408
glfw/x11_window.c
vendored
@@ -28,6 +28,7 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
|
#include "linux_notify.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
@@ -54,32 +55,40 @@
|
|||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
// covers GLX functions
|
// covers GLX functions
|
||||||
//
|
//
|
||||||
GLFWbool _glfwDispatchX11Events(void);
|
static unsigned _glfwDispatchX11Events(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(double timeout) {
|
handleEvents(double timeout) {
|
||||||
|
EVDBG("starting handleEvents(%.2f)", timeout);
|
||||||
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout);
|
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout);
|
||||||
if (display_read_ok) _glfwDispatchX11Events();
|
EVDBG("display_read_ok: %d", display_read_ok);
|
||||||
|
if (display_read_ok) {
|
||||||
|
unsigned dispatched = _glfwDispatchX11Events();
|
||||||
|
(void)dispatched;
|
||||||
|
EVDBG("dispatched %u X11 events", dispatched);
|
||||||
|
}
|
||||||
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
||||||
|
glfw_dbus_session_bus_dispatch();
|
||||||
|
EVDBG("other dispatch done");
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool
|
static bool
|
||||||
waitForX11Event(double timeout) {
|
waitForX11Event(double timeout) {
|
||||||
// returns true iff there is X11 data waiting to be read, does not run watches and timers
|
// returns true iff there is X11 data waiting to be read, does not run watches and timers
|
||||||
double end_time = glfwGetTime() + timeout;
|
double end_time = glfwGetTime() + timeout;
|
||||||
while(GLFW_TRUE) {
|
while(true) {
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
const int result = pollWithTimeout(_glfw.x11.eventLoopData.fds, 1, timeout);
|
const int result = pollWithTimeout(_glfw.x11.eventLoopData.fds, 1, timeout);
|
||||||
if (result > 0) return GLFW_TRUE;
|
if (result > 0) return true;
|
||||||
timeout = end_time - glfwGetTime();
|
timeout = end_time - glfwGetTime();
|
||||||
if (timeout <= 0) return GLFW_FALSE;
|
if (timeout <= 0) return false;
|
||||||
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
|
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
const int result = poll(_glfw.x11.eventLoopData.fds, 1, -1);
|
const int result = poll(_glfw.x11.eventLoopData.fds, 1, -1);
|
||||||
if (result > 0) return GLFW_TRUE;
|
if (result > 0) return true;
|
||||||
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
|
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +96,7 @@ waitForX11Event(double timeout) {
|
|||||||
// Waits until a VisibilityNotify event arrives for the specified window or the
|
// Waits until a VisibilityNotify event arrives for the specified window or the
|
||||||
// timeout period elapses (ICCCM section 4.2.2)
|
// timeout period elapses (ICCCM section 4.2.2)
|
||||||
//
|
//
|
||||||
static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
static bool waitForVisibilityNotify(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
XEvent dummy;
|
XEvent dummy;
|
||||||
|
|
||||||
@@ -97,10 +106,10 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
|||||||
&dummy))
|
&dummy))
|
||||||
{
|
{
|
||||||
if (!waitForX11Event(0.1))
|
if (!waitForX11Event(0.1))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether the window is iconified
|
// Returns whether the window is iconified
|
||||||
@@ -256,6 +265,76 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
|
|||||||
XFree(hints);
|
XFree(hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
is_window_fullscreen(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
Atom* states;
|
||||||
|
unsigned long i;
|
||||||
|
bool ans = false;
|
||||||
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
|
return ans;
|
||||||
|
const unsigned long count =
|
||||||
|
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
XA_ATOM,
|
||||||
|
(unsigned char**) &states);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (states[i] == _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||||
|
{
|
||||||
|
ans = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (states)
|
||||||
|
XFree(states);
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_fullscreen(_GLFWwindow *window, bool on) {
|
||||||
|
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN) {
|
||||||
|
sendEventToWM(window,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
on ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE,
|
||||||
|
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
||||||
|
0, 1, 0);
|
||||||
|
// Enable compositor bypass
|
||||||
|
if (!window->x11.transparent)
|
||||||
|
{
|
||||||
|
if (on) {
|
||||||
|
const unsigned long value = 1;
|
||||||
|
|
||||||
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
|
||||||
|
PropModeReplace, (unsigned char*) &value, 1);
|
||||||
|
} else {
|
||||||
|
XDeleteProperty(_glfw.x11.display, window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_BYPASS_COMPOSITOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
static bool warned = false;
|
||||||
|
if (!warned) {
|
||||||
|
warned = true;
|
||||||
|
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to toggle fullscreen, the window manager does not support it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags) {
|
||||||
|
(void) flags;
|
||||||
|
bool already_fullscreen = is_window_fullscreen(window);
|
||||||
|
set_fullscreen(window, !already_fullscreen);
|
||||||
|
return !already_fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
// Updates the full screen status of the window
|
// Updates the full screen status of the window
|
||||||
//
|
//
|
||||||
static void updateWindowMode(_GLFWwindow* window)
|
static void updateWindowMode(_GLFWwindow* window)
|
||||||
@@ -274,43 +353,8 @@ static void updateWindowMode(_GLFWwindow* window)
|
|||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
set_fullscreen(window, true);
|
||||||
{
|
|
||||||
sendEventToWM(window,
|
|
||||||
_glfw.x11.NET_WM_STATE,
|
|
||||||
_NET_WM_STATE_ADD,
|
|
||||||
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
|
||||||
0, 1, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This is the butcher's way of removing window decorations
|
|
||||||
// Setting the override-redirect attribute on a window makes the
|
|
||||||
// window manager ignore the window completely (ICCCM, section 4)
|
|
||||||
// The good thing is that this makes undecorated full screen windows
|
|
||||||
// easy to do; the bad thing is that we have to do everything
|
|
||||||
// manually and some things (like iconify/restore) won't work at
|
|
||||||
// all, as those are tasks usually performed by the window manager
|
|
||||||
|
|
||||||
XSetWindowAttributes attributes;
|
|
||||||
attributes.override_redirect = True;
|
|
||||||
XChangeWindowAttributes(_glfw.x11.display,
|
|
||||||
window->x11.handle,
|
|
||||||
CWOverrideRedirect,
|
|
||||||
&attributes);
|
|
||||||
|
|
||||||
window->x11.overrideRedirect = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable compositor bypass
|
|
||||||
if (!window->x11.transparent)
|
|
||||||
{
|
|
||||||
const unsigned long value = 1;
|
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
|
|
||||||
PropModeReplace, (unsigned char*) &value, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -321,32 +365,8 @@ static void updateWindowMode(_GLFWwindow* window)
|
|||||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS);
|
_glfw.x11.NET_WM_FULLSCREEN_MONITORS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
set_fullscreen(window, false);
|
||||||
{
|
|
||||||
sendEventToWM(window,
|
|
||||||
_glfw.x11.NET_WM_STATE,
|
|
||||||
_NET_WM_STATE_REMOVE,
|
|
||||||
_glfw.x11.NET_WM_STATE_FULLSCREEN,
|
|
||||||
0, 1, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XSetWindowAttributes attributes;
|
|
||||||
attributes.override_redirect = False;
|
|
||||||
XChangeWindowAttributes(_glfw.x11.display,
|
|
||||||
window->x11.handle,
|
|
||||||
CWOverrideRedirect,
|
|
||||||
&attributes);
|
|
||||||
|
|
||||||
window->x11.overrideRedirect = GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable compositor bypass
|
|
||||||
if (!window->x11.transparent)
|
|
||||||
{
|
|
||||||
XDeleteProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.NET_WM_BYPASS_COMPOSITOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,15 +421,6 @@ static char* convertLatin1toUTF8(const char* source)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Centers the cursor over the window client area
|
|
||||||
//
|
|
||||||
static void centerCursor(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
|
||||||
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the cursor image according to its cursor mode
|
// Updates the cursor image according to its cursor mode
|
||||||
//
|
//
|
||||||
static void updateCursorImage(_GLFWwindow* window)
|
static void updateCursorImage(_GLFWwindow* window)
|
||||||
@@ -453,7 +464,7 @@ static void disableCursor(_GLFWwindow* window)
|
|||||||
&_glfw.x11.restoreCursorPosX,
|
&_glfw.x11.restoreCursorPosX,
|
||||||
&_glfw.x11.restoreCursorPosY);
|
&_glfw.x11.restoreCursorPosY);
|
||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
centerCursor(window);
|
_glfwCenterCursorInContentArea(window);
|
||||||
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
|
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
|
||||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
||||||
GrabModeAsync, GrabModeAsync,
|
GrabModeAsync, GrabModeAsync,
|
||||||
@@ -488,7 +499,7 @@ static void enableCursor(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Create the X11 window (and its colormap)
|
// Create the X11 window (and its colormap)
|
||||||
//
|
//
|
||||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
static bool createNativeWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig,
|
const _GLFWwndconfig* wndconfig,
|
||||||
Visual* visual, int depth)
|
Visual* visual, int depth)
|
||||||
{
|
{
|
||||||
@@ -540,7 +551,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Failed to create window");
|
"X11: Failed to create window");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
XSaveContext(_glfw.x11.display,
|
XSaveContext(_glfw.x11.display,
|
||||||
@@ -550,7 +561,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!wndconfig->decorated)
|
if (!wndconfig->decorated)
|
||||||
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
|
_glfwPlatformSetWindowDecorated(window, false);
|
||||||
|
|
||||||
if (_glfw.x11.NET_WM_STATE && !window->monitor)
|
if (_glfw.x11.NET_WM_STATE && !window->monitor)
|
||||||
{
|
{
|
||||||
@@ -570,7 +581,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
|
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
|
||||||
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
|
states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
|
||||||
window->x11.maximized = GLFW_TRUE;
|
window->x11.maximized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,7 +630,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||||
"X11: Failed to allocate WM hints");
|
"X11: Failed to allocate WM hints");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hints->flags = StateHint;
|
hints->flags = StateHint;
|
||||||
@@ -673,7 +684,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
|||||||
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
||||||
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
_glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the specified property to the selection converted to the requested target
|
// Set the specified property to the selection converted to the requested target
|
||||||
@@ -1016,19 +1027,6 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||||||
|
|
||||||
_glfwSetVideoModeX11(window->monitor, &window->videoMode);
|
_glfwSetVideoModeX11(window->monitor, &window->videoMode);
|
||||||
|
|
||||||
if (window->x11.overrideRedirect)
|
|
||||||
{
|
|
||||||
int xpos, ypos;
|
|
||||||
GLFWvidmode mode;
|
|
||||||
|
|
||||||
// Manually position the window over its monitor
|
|
||||||
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
|
|
||||||
_glfwPlatformGetVideoMode(window->monitor, &mode);
|
|
||||||
|
|
||||||
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
|
||||||
xpos, ypos, mode.width, mode.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputMonitorWindow(window->monitor, window);
|
_glfwInputMonitorWindow(window->monitor, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1055,10 +1053,10 @@ static void releaseMonitor(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onConfigChange()
|
static void onConfigChange(void)
|
||||||
{
|
{
|
||||||
float xscale, yscale;
|
float xscale, yscale;
|
||||||
_glfwGetSystemContentScaleX11(&xscale, &yscale, GLFW_TRUE);
|
_glfwGetSystemContentScaleX11(&xscale, &yscale, true);
|
||||||
|
|
||||||
if (xscale != _glfw.x11.contentScaleX || yscale != _glfw.x11.contentScaleY)
|
if (xscale != _glfw.x11.contentScaleX || yscale != _glfw.x11.contentScaleY)
|
||||||
{
|
{
|
||||||
@@ -1078,7 +1076,8 @@ static void onConfigChange()
|
|||||||
static void processEvent(XEvent *event)
|
static void processEvent(XEvent *event)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = NULL;
|
_GLFWwindow* window = NULL;
|
||||||
Bool filtered = False;
|
static bool keymap_dirty = false;
|
||||||
|
#define UPDATE_KEYMAP_IF_NEEDED if (keymap_dirty) { keymap_dirty = false; glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL); }
|
||||||
|
|
||||||
if (_glfw.x11.randr.available)
|
if (_glfw.x11.randr.available)
|
||||||
{
|
{
|
||||||
@@ -1154,11 +1153,12 @@ static void processEvent(XEvent *event)
|
|||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case XkbMapNotify:
|
case XkbMapNotify:
|
||||||
{
|
{
|
||||||
glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL);
|
keymap_dirty = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case XkbStateNotify:
|
case XkbStateNotify:
|
||||||
{
|
{
|
||||||
|
UPDATE_KEYMAP_IF_NEEDED;
|
||||||
XkbStateNotifyEvent *state_event = (XkbStateNotifyEvent*)kb_event;
|
XkbStateNotifyEvent *state_event = (XkbStateNotifyEvent*)kb_event;
|
||||||
glfw_xkb_update_modifiers(
|
glfw_xkb_update_modifiers(
|
||||||
&_glfw.x11.xkb, state_event->base_mods, state_event->latched_mods,
|
&_glfw.x11.xkb, state_event->base_mods, state_event->latched_mods,
|
||||||
@@ -1183,12 +1183,14 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
|
UPDATE_KEYMAP_IF_NEEDED;
|
||||||
glfw_xkb_handle_key_event(window, &_glfw.x11.xkb, event->xkey.keycode, GLFW_PRESS);
|
glfw_xkb_handle_key_event(window, &_glfw.x11.xkb, event->xkey.keycode, GLFW_PRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
{
|
{
|
||||||
|
UPDATE_KEYMAP_IF_NEEDED;
|
||||||
if (!_glfw.x11.xkb.detectable)
|
if (!_glfw.x11.xkb.detectable)
|
||||||
{
|
{
|
||||||
// HACK: Key repeat events will arrive as KeyRelease/KeyPress
|
// HACK: Key repeat events will arrive as KeyRelease/KeyPress
|
||||||
@@ -1308,7 +1310,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||||
updateCursorImage(window);
|
updateCursorImage(window);
|
||||||
|
|
||||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
_glfwInputCursorEnter(window, true);
|
||||||
_glfwInputCursorPos(window, x, y);
|
_glfwInputCursorPos(window, x, y);
|
||||||
|
|
||||||
window->x11.lastCursorPosX = x;
|
window->x11.lastCursorPosX = x;
|
||||||
@@ -1318,7 +1320,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
{
|
{
|
||||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
_glfwInputCursorEnter(window, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1375,7 +1377,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (event->xconfigure.x != window->x11.xpos ||
|
if (event->xconfigure.x != window->x11.xpos ||
|
||||||
event->xconfigure.y != window->x11.ypos)
|
event->xconfigure.y != window->x11.ypos)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect || event->xany.send_event)
|
if (event->xany.send_event)
|
||||||
{
|
{
|
||||||
_glfwInputWindowPos(window,
|
_glfwInputWindowPos(window,
|
||||||
event->xconfigure.x,
|
event->xconfigure.x,
|
||||||
@@ -1393,9 +1395,6 @@ static void processEvent(XEvent *event)
|
|||||||
{
|
{
|
||||||
// Custom client message, probably from the window manager
|
// Custom client message, probably from the window manager
|
||||||
|
|
||||||
if (filtered)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (event->xclient.message_type == None)
|
if (event->xclient.message_type == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1431,7 +1430,7 @@ static void processEvent(XEvent *event)
|
|||||||
// A drag operation has entered the window
|
// A drag operation has entered the window
|
||||||
unsigned long i, count;
|
unsigned long i, count;
|
||||||
Atom* formats = NULL;
|
Atom* formats = NULL;
|
||||||
const GLFWbool list = event->xclient.data.l[1] & 1;
|
const bool list = event->xclient.data.l[1] & 1;
|
||||||
|
|
||||||
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
||||||
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
||||||
@@ -1613,7 +1612,7 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
_glfwInputWindowFocus(window, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1633,7 +1632,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (window->monitor && window->autoIconify)
|
if (window->monitor && window->autoIconify)
|
||||||
_glfwPlatformIconifyWindow(window);
|
_glfwPlatformIconifyWindow(window);
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1654,7 +1653,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (state != IconicState && state != NormalState)
|
if (state != IconicState && state != NormalState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const GLFWbool iconified = (state == IconicState);
|
const bool iconified = (state == IconicState);
|
||||||
if (window->x11.iconified != iconified)
|
if (window->x11.iconified != iconified)
|
||||||
{
|
{
|
||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
@@ -1671,7 +1670,7 @@ static void processEvent(XEvent *event)
|
|||||||
}
|
}
|
||||||
else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
|
else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
|
||||||
{
|
{
|
||||||
const GLFWbool maximized = _glfwPlatformWindowMaximized(window);
|
const bool maximized = _glfwPlatformWindowMaximized(window);
|
||||||
if (window->x11.maximized != maximized)
|
if (window->x11.maximized != maximized)
|
||||||
{
|
{
|
||||||
window->x11.maximized = maximized;
|
window->x11.maximized = maximized;
|
||||||
@@ -1685,6 +1684,7 @@ static void processEvent(XEvent *event)
|
|||||||
case DestroyNotify:
|
case DestroyNotify:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#undef UPDATE_KEYMAP_IF_NEEDED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1720,10 +1720,10 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
|||||||
return itemCount;
|
return itemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
|
bool _glfwIsVisualTransparentX11(Visual* visual)
|
||||||
{
|
{
|
||||||
if (!_glfw.x11.xrender.available)
|
if (!_glfw.x11.xrender.available)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
|
XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
|
||||||
return pf && pf->direct.alphaMask;
|
return pf && pf->direct.alphaMask;
|
||||||
@@ -1795,21 +1795,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitGLX())
|
if (!_glfwInitGLX())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitEGL())
|
if (!_glfwInitEGL())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwInitOSMesa())
|
if (!_glfwInitOSMesa())
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1821,24 +1821,24 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!createNativeWindow(window, wndconfig, visual, depth))
|
if (!createNativeWindow(window, wndconfig, visual, depth))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
if (ctxconfig->client != GLFW_NO_API)
|
if (ctxconfig->client != GLFW_NO_API)
|
||||||
{
|
{
|
||||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||||
{
|
{
|
||||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1850,7 +1850,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||||
@@ -2123,30 +2123,12 @@ double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect)
|
|
||||||
{
|
|
||||||
// Override-redirect windows cannot be iconified or restored, as those
|
|
||||||
// tasks are performed by the window manager
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);
|
XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->x11.overrideRedirect)
|
|
||||||
{
|
|
||||||
// Override-redirect windows cannot be iconified or restored, as those
|
|
||||||
// tasks are performed by the window manager
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfwPlatformWindowIconified(window))
|
if (_glfwPlatformWindowIconified(window))
|
||||||
{
|
{
|
||||||
XMapWindow(_glfw.x11.display, window->x11.handle);
|
XMapWindow(_glfw.x11.display, window->x11.handle);
|
||||||
@@ -2212,7 +2194,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return XkbBell(_glfw.x11.display, window->x11.handle, 100, (Atom)0) ? GLFW_TRUE : GLFW_FALSE;
|
return XkbBell(_glfw.x11.display, window->x11.handle, 100, (Atom)0) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
@@ -2260,16 +2242,20 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
_glfwInputWindowMonitor(window, monitor);
|
_glfwInputWindowMonitor(window, monitor);
|
||||||
updateNormalHints(window, width, height);
|
updateNormalHints(window, width, height);
|
||||||
updateWindowMode(window);
|
|
||||||
|
|
||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
{
|
{
|
||||||
XMapRaised(_glfw.x11.display, window->x11.handle);
|
if (!_glfwPlatformWindowVisible(window))
|
||||||
if (waitForVisibilityNotify(window))
|
{
|
||||||
acquireMonitor(window);
|
XMapRaised(_glfw.x11.display, window->x11.handle);
|
||||||
|
waitForVisibilityNotify(window);
|
||||||
|
}
|
||||||
|
updateWindowMode(window);
|
||||||
|
acquireMonitor(window);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
updateWindowMode(window);
|
||||||
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
||||||
xpos, ypos, width, height);
|
xpos, ypos, width, height);
|
||||||
}
|
}
|
||||||
@@ -2286,6 +2272,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
|||||||
return window->x11.handle == focused;
|
return window->x11.handle == focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return getWindowState(window) == IconicState;
|
return getWindowState(window) == IconicState;
|
||||||
@@ -2302,7 +2293,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
Atom* states;
|
Atom* states;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
GLFWbool maximized = GLFW_FALSE;
|
bool maximized = false;
|
||||||
if (!_glfw.x11.NET_WM_STATE ||
|
if (!_glfw.x11.NET_WM_STATE ||
|
||||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||||
@@ -2318,7 +2309,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||||
{
|
{
|
||||||
maximized = GLFW_TRUE;
|
maximized = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2341,32 +2332,32 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
|||||||
if (!XQueryPointer(_glfw.x11.display, w,
|
if (!XQueryPointer(_glfw.x11.display, w,
|
||||||
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
|
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w == window->x11.handle)
|
if (w == window->x11.handle)
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (!window->x11.transparent)
|
if (!window->x11.transparent)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
|
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
updateNormalHints(window, width, height);
|
updateNormalHints(window, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
@@ -2397,7 +2388,7 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
|
||||||
return;
|
return;
|
||||||
@@ -2493,23 +2484,29 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
|||||||
PropModeReplace, (unsigned char*) &value, 1);
|
PropModeReplace, (unsigned char*) &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
static inline unsigned
|
||||||
|
dispatch_x11_queued_events(void) {
|
||||||
|
unsigned dispatched = 0;
|
||||||
|
while (XQLength(_glfw.x11.display) > 0)
|
||||||
|
{
|
||||||
|
XEvent event;
|
||||||
|
XNextEvent(_glfw.x11.display, &event);
|
||||||
|
processEvent(&event);
|
||||||
|
dispatched += 1;
|
||||||
|
}
|
||||||
|
return dispatched;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned
|
||||||
_glfwDispatchX11Events(void) {
|
_glfwDispatchX11Events(void) {
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window;
|
||||||
GLFWbool dispatched = GLFW_FALSE;
|
unsigned dispatched = 0;
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwDetectJoystickConnectionLinux();
|
_glfwDetectJoystickConnectionLinux();
|
||||||
#endif
|
#endif
|
||||||
XPending(_glfw.x11.display);
|
XPending(_glfw.x11.display);
|
||||||
|
dispatched += dispatch_x11_queued_events();
|
||||||
while (XQLength(_glfw.x11.display))
|
|
||||||
{
|
|
||||||
XEvent event;
|
|
||||||
XNextEvent(_glfw.x11.display, &event);
|
|
||||||
processEvent(&event);
|
|
||||||
dispatched = GLFW_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
window = _glfw.x11.disabledCursorWindow;
|
window = _glfw.x11.disabledCursorWindow;
|
||||||
if (window)
|
if (window)
|
||||||
@@ -2527,6 +2524,8 @@ _glfwDispatchX11Events(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
|
// XFlush can cause events to be queued
|
||||||
|
dispatched += dispatch_x11_queued_events();
|
||||||
return dispatched;
|
return dispatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2550,16 +2549,6 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
XEvent event;
|
|
||||||
|
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
event.type = ClientMessage;
|
|
||||||
event.xclient.window = _glfw.x11.helperWindowHandle;
|
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
|
||||||
event.xclient.message_type = _glfw.x11.NULL_;
|
|
||||||
|
|
||||||
XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, False, 0, &event);
|
|
||||||
XFlush(_glfw.x11.display);
|
|
||||||
while (write(_glfw.x11.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR);
|
while (write(_glfw.x11.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2623,39 +2612,40 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
|||||||
{
|
{
|
||||||
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
|
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
|
||||||
if (!cursor->x11.handle)
|
if (!cursor->x11.handle)
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape)
|
||||||
{
|
{
|
||||||
int native = 0;
|
int native = 0;
|
||||||
|
#define C(name, val) case name: native = val; break;
|
||||||
if (shape == GLFW_ARROW_CURSOR)
|
switch(shape) {
|
||||||
native = XC_left_ptr;
|
C(GLFW_ARROW_CURSOR, XC_arrow);
|
||||||
else if (shape == GLFW_IBEAM_CURSOR)
|
C(GLFW_IBEAM_CURSOR, XC_xterm);
|
||||||
native = XC_xterm;
|
C(GLFW_CROSSHAIR_CURSOR, XC_crosshair);
|
||||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
C(GLFW_HAND_CURSOR, XC_hand2);
|
||||||
native = XC_crosshair;
|
C(GLFW_HRESIZE_CURSOR, XC_sb_h_double_arrow);
|
||||||
else if (shape == GLFW_HAND_CURSOR)
|
C(GLFW_VRESIZE_CURSOR, XC_sb_v_double_arrow);
|
||||||
native = XC_hand1;
|
C(GLFW_NW_RESIZE_CURSOR, XC_top_left_corner);
|
||||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
C(GLFW_NE_RESIZE_CURSOR, XC_top_right_corner);
|
||||||
native = XC_sb_h_double_arrow;
|
C(GLFW_SW_RESIZE_CURSOR, XC_bottom_left_corner);
|
||||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
C(GLFW_SE_RESIZE_CURSOR, XC_bottom_right_corner);
|
||||||
native = XC_sb_v_double_arrow;
|
case GLFW_INVALID_CURSOR:
|
||||||
else
|
return false;
|
||||||
return GLFW_FALSE;
|
}
|
||||||
|
#undef C
|
||||||
|
|
||||||
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
|
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
|
||||||
if (!cursor->x11.handle)
|
if (!cursor->x11.handle)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Failed to create standard cursor");
|
"X11: Failed to create standard cursor");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
@@ -2757,7 +2747,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"X11: Vulkan instance missing VK_KHR_xcb_surface extension");
|
"X11: Vulkan instance missing VK_KHR_xcb_surface extension");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
|
xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
|
||||||
@@ -2765,7 +2755,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Failed to retrieve XCB connection");
|
"X11: Failed to retrieve XCB connection");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
|
return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
|
||||||
@@ -2783,7 +2773,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
|||||||
{
|
{
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"X11: Vulkan instance missing VK_KHR_xlib_surface extension");
|
"X11: Vulkan instance missing VK_KHR_xlib_surface extension");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
|
return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
|
||||||
@@ -2890,6 +2880,14 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
|
|||||||
return window->x11.handle;
|
return window->x11.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetXKBScancode(const char* keyName, GLFWbool caseSensitive) {
|
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) {
|
||||||
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, const char *action_name, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data) {
|
||||||
|
return glfw_dbus_send_user_notification(app_name, icon, summary, body, action_name, timeout, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwDBusSetUserNotificationHandler(GLFWDBusnotificationactivatedfun handler) {
|
||||||
|
glfw_dbus_set_user_notification_activated_handler(handler);
|
||||||
|
}
|
||||||
|
|||||||
43
glfw/xkb_glfw.c
vendored
43
glfw/xkb_glfw.c
vendored
@@ -47,6 +47,7 @@
|
|||||||
S(backslash, BACKSLASH); \
|
S(backslash, BACKSLASH); \
|
||||||
S(bracketright, RIGHT_BRACKET); \
|
S(bracketright, RIGHT_BRACKET); \
|
||||||
S(plus, PLUS); \
|
S(plus, PLUS); \
|
||||||
|
S(underscore, UNDERSCORE); \
|
||||||
S(grave, GRAVE_ACCENT); \
|
S(grave, GRAVE_ACCENT); \
|
||||||
S(Escape, ESCAPE); \
|
S(Escape, ESCAPE); \
|
||||||
S(Return, ENTER); \
|
S(Return, ENTER); \
|
||||||
@@ -135,30 +136,30 @@ glfw_xkb_sym_for_key(int key) {
|
|||||||
|
|
||||||
#ifdef _GLFW_X11
|
#ifdef _GLFW_X11
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_xkb_set_x11_events_mask(void) {
|
glfw_xkb_set_x11_events_mask(void) {
|
||||||
if (!XkbSelectEvents(_glfw.x11.display, XkbUseCoreKbd, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask)) {
|
if (!XkbSelectEvents(_glfw.x11.display, XkbUseCoreKbd, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask)) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set XKB events mask");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to set XKB events mask");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
|
glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
|
||||||
xkb->keyboard_device_id = -1;
|
xkb->keyboard_device_id = -1;
|
||||||
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display);
|
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve XCB connection");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve XCB connection");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
xkb->keyboard_device_id = xkb_x11_get_core_keyboard_device_id(conn);
|
xkb->keyboard_device_id = xkb_x11_get_core_keyboard_device_id(conn);
|
||||||
if (xkb->keyboard_device_id == -1) {
|
if (xkb->keyboard_device_id == -1) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve core keyboard device id");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve core keyboard device id");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define xkb_glfw_load_keymap(keymap, ...) {\
|
#define xkb_glfw_load_keymap(keymap, ...) {\
|
||||||
@@ -203,17 +204,17 @@ glfw_xkb_release(_GLFWXKBData *xkb) {
|
|||||||
glfw_ibus_terminate(&xkb->ibus);
|
glfw_ibus_terminate(&xkb->ibus);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_xkb_create_context(_GLFWXKBData *xkb) {
|
glfw_xkb_create_context(_GLFWXKBData *xkb) {
|
||||||
xkb->context = xkb_context_new(0);
|
xkb->context = xkb_context_new(0);
|
||||||
if (!xkb->context)
|
if (!xkb->context)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Failed to initialize XKB context");
|
"Failed to initialize XKB context");
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
glfw_connect_to_ibus(&xkb->ibus);
|
glfw_connect_to_ibus(&xkb->ibus);
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char*
|
static const char*
|
||||||
@@ -259,7 +260,7 @@ load_compose_tables(_GLFWXKBData *xkb) {
|
|||||||
xkb_compose_table_unref(compose_table);
|
xkb_compose_table_unref(compose_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
||||||
const char *err;
|
const char *err;
|
||||||
release_keyboard_data(xkb);
|
release_keyboard_data(xkb);
|
||||||
@@ -267,13 +268,13 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
||||||
release_keyboard_data(xkb);
|
release_keyboard_data(xkb);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
err = load_states(xkb);
|
err = load_states(xkb);
|
||||||
if (err) {
|
if (err) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
||||||
release_keyboard_data(xkb);
|
release_keyboard_data(xkb);
|
||||||
return GLFW_FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
load_compose_tables(xkb);
|
load_compose_tables(xkb);
|
||||||
#define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx;
|
#define S(a, n) xkb->a##Idx = xkb_keymap_mod_get_index(xkb->keymap, n); xkb->a##Mask = 1 << xkb->a##Idx;
|
||||||
@@ -291,7 +292,7 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
|||||||
}
|
}
|
||||||
xkb->states.modifiers = 0;
|
xkb->states.modifiers = 0;
|
||||||
xkb->states.activeUnknownModifiers = 0;
|
xkb->states.activeUnknownModifiers = 0;
|
||||||
return GLFW_TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline xkb_mod_mask_t
|
static inline xkb_mod_mask_t
|
||||||
@@ -325,7 +326,7 @@ glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_m
|
|||||||
update_modifiers(xkb, &xkb->states);
|
update_modifiers(xkb, &xkb->states);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
bool
|
||||||
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
|
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
|
||||||
#ifdef _GLFW_WAYLAND
|
#ifdef _GLFW_WAYLAND
|
||||||
scancode += 8;
|
scancode += 8;
|
||||||
@@ -365,7 +366,7 @@ glfw_xkb_keysym_name(xkb_keysym_t sym) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
glfw_xkb_keysym_from_name(const char *name, GLFWbool case_sensitive) {
|
glfw_xkb_keysym_from_name(const char *name, bool case_sensitive) {
|
||||||
return (int)xkb_keysym_from_name(name, case_sensitive ? XKB_KEYSYM_NO_FLAGS : XKB_KEYSYM_CASE_INSENSITIVE);
|
return (int)xkb_keysym_from_name(name, case_sensitive ? XKB_KEYSYM_NO_FLAGS : XKB_KEYSYM_CASE_INSENSITIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +413,7 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
|
|||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
switch(which) {
|
switch(which) {
|
||||||
case 1:
|
case 1:
|
||||||
glfw_ibus_set_focused(&xkb->ibus, a ? GLFW_TRUE : GLFW_FALSE);
|
glfw_ibus_set_focused(&xkb->ibus, a ? true : false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
_glfwPlatformGetWindowPos(w, &x, &y);
|
_glfwPlatformGetWindowPos(w, &x, &y);
|
||||||
@@ -423,7 +424,7 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_xkb_key_from_ime(KeyEvent *ev, GLFWbool handled_by_ime, GLFWbool failed) {
|
glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
|
||||||
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
|
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
|
||||||
if (failed && window && window->callbacks.keyboard) {
|
if (failed && window && window->callbacks.keyboard) {
|
||||||
// notify application to remove any existing pre-edit text
|
// notify application to remove any existing pre-edit text
|
||||||
@@ -436,7 +437,7 @@ glfw_xkb_key_from_ime(KeyEvent *ev, GLFWbool handled_by_ime, GLFWbool failed) {
|
|||||||
// you'd need to implement a ring buffer to store pending key presses.
|
// you'd need to implement a ring buffer to store pending key presses.
|
||||||
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
|
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
|
||||||
last_handled_press_keycode = 0;
|
last_handled_press_keycode = 0;
|
||||||
GLFWbool is_release = ev->action == GLFW_RELEASE;
|
bool is_release = ev->action == GLFW_RELEASE;
|
||||||
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->keycode, glfw_xkb_keysym_name(ev->keysym), is_release);
|
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->keycode, glfw_xkb_keysym_name(ev->keysym), is_release);
|
||||||
if (window && !handled_by_ime && !(is_release && ev->keycode == prev_handled_press)) {
|
if (window && !handled_by_ime && !(is_release && ev->keycode == prev_handled_press)) {
|
||||||
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
|
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
|
||||||
@@ -499,13 +500,13 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
|
|||||||
if (key_event.text[0]) { debug("%s: %s ", text_type, key_event.text); }
|
if (key_event.text[0]) { debug("%s: %s ", text_type, key_event.text); }
|
||||||
}
|
}
|
||||||
int glfw_keycode = glfw_key_for_sym(glfw_sym);
|
int glfw_keycode = glfw_key_for_sym(glfw_sym);
|
||||||
GLFWbool is_fallback = GLFW_FALSE;
|
bool is_fallback = false;
|
||||||
if (glfw_keycode == GLFW_KEY_UNKNOWN && !key_event.text[0]) {
|
if (glfw_keycode == GLFW_KEY_UNKNOWN && !key_event.text[0]) {
|
||||||
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
|
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
|
||||||
if (num_default_syms > 0) {
|
if (num_default_syms > 0) {
|
||||||
glfw_sym = default_syms[0];
|
glfw_sym = default_syms[0];
|
||||||
glfw_keycode = glfw_key_for_sym(glfw_sym);
|
glfw_keycode = glfw_key_for_sym(glfw_sym);
|
||||||
is_fallback = GLFW_TRUE;
|
is_fallback = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug(
|
debug(
|
||||||
|
|||||||
18
glfw/xkb_glfw.h
vendored
18
glfw/xkb_glfw.h
vendored
@@ -67,8 +67,8 @@ typedef struct {
|
|||||||
|
|
||||||
#ifdef _GLFW_X11
|
#ifdef _GLFW_X11
|
||||||
int32_t keyboard_device_id;
|
int32_t keyboard_device_id;
|
||||||
GLFWbool available;
|
bool available;
|
||||||
GLFWbool detectable;
|
bool detectable;
|
||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
@@ -79,18 +79,18 @@ typedef struct {
|
|||||||
} _GLFWXKBData;
|
} _GLFWXKBData;
|
||||||
|
|
||||||
#ifdef _GLFW_X11
|
#ifdef _GLFW_X11
|
||||||
GLFWbool glfw_xkb_set_x11_events_mask(void);
|
bool glfw_xkb_set_x11_events_mask(void);
|
||||||
GLFWbool glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb);
|
bool glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void glfw_xkb_release(_GLFWXKBData *xkb);
|
void glfw_xkb_release(_GLFWXKBData *xkb);
|
||||||
GLFWbool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
bool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
||||||
GLFWbool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
|
bool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
|
||||||
void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group);
|
void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group);
|
||||||
GLFWbool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode);
|
bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode);
|
||||||
const char* glfw_xkb_keysym_name(xkb_keysym_t sym);
|
const char* glfw_xkb_keysym_name(xkb_keysym_t sym);
|
||||||
xkb_keysym_t glfw_xkb_sym_for_key(int key);
|
xkb_keysym_t glfw_xkb_sym_for_key(int key);
|
||||||
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action);
|
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action);
|
||||||
int glfw_xkb_keysym_from_name(const char *name, GLFWbool case_sensitive);
|
int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive);
|
||||||
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
|
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
|
||||||
void glfw_xkb_key_from_ime(KeyEvent *ev, GLFWbool handled_by_ime, GLFWbool failed);
|
void glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
from kitty.cli import parse_args
|
from kitty.cli import parse_args
|
||||||
from kitty.constants import cache_dir
|
from kitty.constants import cache_dir
|
||||||
@@ -27,10 +28,8 @@ class HistoryCompleter:
|
|||||||
self.history_path = None
|
self.history_path = None
|
||||||
if name:
|
if name:
|
||||||
ddir = os.path.join(cache_dir(), 'ask')
|
ddir = os.path.join(cache_dir(), 'ask')
|
||||||
try:
|
with suppress(FileExistsError):
|
||||||
os.makedirs(ddir)
|
os.makedirs(ddir)
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
self.history_path = os.path.join(ddir, name)
|
self.history_path = os.path.join(ddir, name)
|
||||||
|
|
||||||
def complete(self, text, state):
|
def complete(self, text, state):
|
||||||
@@ -50,10 +49,8 @@ class HistoryCompleter:
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if self.history_path:
|
if self.history_path:
|
||||||
try:
|
with suppress(Exception):
|
||||||
readline.read_history_file(self.history_path)
|
readline.read_history_file(self.history_path)
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
readline.set_completer(self.complete)
|
readline.set_completer(self.complete)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -106,10 +103,8 @@ def main(args):
|
|||||||
print(styled(args.message, bold=True))
|
print(styled(args.message, bold=True))
|
||||||
|
|
||||||
prompt = '> '
|
prompt = '> '
|
||||||
try:
|
with suppress(KeyboardInterrupt, EOFError):
|
||||||
ans['response'] = input(prompt)
|
ans['response'] = input(prompt)
|
||||||
except (KeyboardInterrupt, EOFError):
|
|
||||||
pass
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
kittens/choose/__init__.py
Normal file
0
kittens/choose/__init__.py
Normal file
88
kittens/choose/choose-data-types.h
Normal file
88
kittens/choose/choose-data-types.h
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "data-types.h"
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define ISWINDOWS
|
||||||
|
#define STDCALL __stdcall
|
||||||
|
#ifndef ssize_t
|
||||||
|
#include <BaseTsd.h>
|
||||||
|
typedef SSIZE_T ssize_t;
|
||||||
|
#ifndef SSIZE_MAX
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define SSIZE_MAX _I64_MAX
|
||||||
|
#else
|
||||||
|
#define SSIZE_MAX LONG_MAX
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define STDCALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
typedef uint8_t len_t;
|
||||||
|
typedef uint32_t text_t;
|
||||||
|
|
||||||
|
#define LEN_MAX UINT8_MAX
|
||||||
|
#define UTF8_ACCEPT 0
|
||||||
|
#define UTF8_REJECT 1
|
||||||
|
#define IS_LOWERCASE(x) (x) >= 'a' && (x) <= 'z'
|
||||||
|
#define IS_UPPERCASE(x) (x) >= 'A' && (x) <= 'Z'
|
||||||
|
#define LOWERCASE(x) ((IS_UPPERCASE(x)) ? (x) + 32 : (x))
|
||||||
|
#define arraysz(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
text_t* src;
|
||||||
|
ssize_t src_sz;
|
||||||
|
len_t haystack_len;
|
||||||
|
len_t *positions;
|
||||||
|
double score;
|
||||||
|
ssize_t idx;
|
||||||
|
} Candidate;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Candidate *haystack;
|
||||||
|
size_t haystack_count;
|
||||||
|
text_t level1[LEN_MAX], level2[LEN_MAX], level3[LEN_MAX], needle[LEN_MAX];
|
||||||
|
len_t level1_len, level2_len, level3_len, needle_len;
|
||||||
|
size_t haystack_size;
|
||||||
|
text_t *output;
|
||||||
|
size_t output_sz, output_pos;
|
||||||
|
int oom;
|
||||||
|
} GlobalData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool output_positions;
|
||||||
|
size_t limit;
|
||||||
|
int num_threads;
|
||||||
|
text_t mark_before[128], mark_after[128], delimiter[128];
|
||||||
|
size_t mark_before_sz, mark_after_sz, delimiter_sz;
|
||||||
|
} Options;
|
||||||
|
|
||||||
|
VECTOR_OF(len_t, Positions)
|
||||||
|
VECTOR_OF(text_t, Chars)
|
||||||
|
VECTOR_OF(Candidate, Candidates)
|
||||||
|
|
||||||
|
|
||||||
|
void output_results(GlobalData *, Candidate *haystack, size_t count, Options *opts, len_t needle_len);
|
||||||
|
void* alloc_workspace(len_t max_haystack_len, GlobalData*);
|
||||||
|
void* free_workspace(void *v);
|
||||||
|
double score_item(void *v, text_t *haystack, len_t haystack_len, len_t *match_positions);
|
||||||
|
unsigned int encode_codepoint(text_t ch, char* dest);
|
||||||
|
size_t unescape(const char *src, char *dest, size_t destlen);
|
||||||
|
int cpu_count(void);
|
||||||
|
void* alloc_threads(size_t num_threads);
|
||||||
|
#ifdef ISWINDOWS
|
||||||
|
bool start_thread(void* threads, size_t i, unsigned int (STDCALL *start_routine) (void *), void *arg);
|
||||||
|
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
|
||||||
|
#else
|
||||||
|
bool start_thread(void* threads, size_t i, void *(*start_routine) (void *), void *arg);
|
||||||
|
#endif
|
||||||
|
void wait_for_thread(void *threads, size_t i);
|
||||||
|
void free_threads(void *threads);
|
||||||
244
kittens/choose/main.c
Normal file
244
kittens/choose/main.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* main.c
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "choose-data-types.h"
|
||||||
|
#include "charsets.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifndef ISWINDOWS
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t start, count;
|
||||||
|
void *workspace;
|
||||||
|
len_t max_haystack_len;
|
||||||
|
bool started;
|
||||||
|
GlobalData *global;
|
||||||
|
} JobData;
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int STDCALL
|
||||||
|
run_scoring(JobData *job_data) {
|
||||||
|
GlobalData *global = job_data->global;
|
||||||
|
for (size_t i = job_data->start; i < job_data->start + job_data->count; i++) {
|
||||||
|
global->haystack[i].score = score_item(job_data->workspace, global->haystack[i].src, global->haystack[i].haystack_len, global->haystack[i].positions);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
run_scoring_pthreads(void *job_data) {
|
||||||
|
run_scoring((JobData*)job_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#ifdef ISWINDOWS
|
||||||
|
#define START_FUNC run_scoring
|
||||||
|
#else
|
||||||
|
#define START_FUNC run_scoring_pthreads
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static JobData*
|
||||||
|
create_job(size_t i, size_t blocksz, GlobalData *global) {
|
||||||
|
JobData *ans = (JobData*)calloc(1, sizeof(JobData));
|
||||||
|
if (ans == NULL) return NULL;
|
||||||
|
ans->start = i * blocksz;
|
||||||
|
if (ans->start >= global->haystack_count) ans->count = 0;
|
||||||
|
else ans->count = global->haystack_count - ans->start;
|
||||||
|
ans->max_haystack_len = 0;
|
||||||
|
for (size_t i = ans->start; i < ans->start + ans->count; i++) ans->max_haystack_len = MAX(ans->max_haystack_len, global->haystack[i].haystack_len);
|
||||||
|
if (ans->count > 0) {
|
||||||
|
ans->workspace = alloc_workspace(ans->max_haystack_len, global);
|
||||||
|
if (!ans->workspace) { free(ans); return NULL; }
|
||||||
|
}
|
||||||
|
ans->global = global;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JobData*
|
||||||
|
free_job(JobData *job) {
|
||||||
|
if (job) {
|
||||||
|
if (job->workspace) free_workspace(job->workspace);
|
||||||
|
free(job);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
run_threaded(int num_threads_asked, GlobalData *global) {
|
||||||
|
int ret = 0;
|
||||||
|
size_t i, blocksz;
|
||||||
|
size_t num_threads = MAX(1, num_threads_asked > 0 ? num_threads_asked : cpu_count());
|
||||||
|
if (global->haystack_size < 10000) num_threads = 1;
|
||||||
|
/* printf("num_threads: %lu asked: %d sysconf: %ld\n", num_threads, num_threads_asked, sysconf(_SC_NPROCESSORS_ONLN)); */
|
||||||
|
|
||||||
|
void *threads = alloc_threads(num_threads);
|
||||||
|
JobData **job_data = calloc(num_threads, sizeof(JobData*));
|
||||||
|
if (threads == NULL || job_data == NULL) { ret = 1; goto end; }
|
||||||
|
|
||||||
|
blocksz = global->haystack_count / num_threads + global->haystack_count % num_threads;
|
||||||
|
|
||||||
|
for (i = 0; i < num_threads; i++) {
|
||||||
|
job_data[i] = create_job(i, blocksz, global);
|
||||||
|
if (job_data[i] == NULL) { ret = 1; goto end; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_threads == 1) {
|
||||||
|
run_scoring(job_data[0]);
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < num_threads; i++) {
|
||||||
|
job_data[i]->started = false;
|
||||||
|
if (job_data[i]->count > 0) {
|
||||||
|
if (!start_thread(threads, i, START_FUNC, job_data[i])) ret = 1;
|
||||||
|
else job_data[i]->started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (num_threads > 1 && job_data) {
|
||||||
|
for (i = 0; i < num_threads; i++) {
|
||||||
|
if (job_data[i] && job_data[i]->started) wait_for_thread(threads, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < num_threads; i++) job_data[i] = free_job(job_data[i]);
|
||||||
|
free(job_data);
|
||||||
|
free_threads(threads);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
run_search(Options *opts, GlobalData *global, const char * const *lines, const size_t* sizes, size_t num_lines) {
|
||||||
|
const char *linebuf = NULL;
|
||||||
|
size_t idx = 0;
|
||||||
|
ssize_t sz = 0;
|
||||||
|
int ret = 0;
|
||||||
|
Candidates candidates = {0};
|
||||||
|
Chars chars = {0};
|
||||||
|
|
||||||
|
ALLOC_VEC(text_t, chars, 8192 * 20);
|
||||||
|
if (chars.data == NULL) return 1;
|
||||||
|
ALLOC_VEC(Candidate, candidates, 8192);
|
||||||
|
if (candidates.data == NULL) { FREE_VEC(chars) return 1; }
|
||||||
|
|
||||||
|
for (size_t i = 0; i < num_lines; i++) {
|
||||||
|
sz = sizes[i];
|
||||||
|
linebuf = lines[i];
|
||||||
|
if (sz > 0) {
|
||||||
|
ENSURE_SPACE(text_t, chars, sz);
|
||||||
|
ENSURE_SPACE(Candidate, candidates, 1);
|
||||||
|
sz = decode_utf8_string(linebuf, sz, &(NEXT(chars)));
|
||||||
|
NEXT(candidates).src_sz = sz;
|
||||||
|
NEXT(candidates).haystack_len = (len_t)(MIN(LEN_MAX, sz));
|
||||||
|
global->haystack_size += NEXT(candidates).haystack_len;
|
||||||
|
NEXT(candidates).idx = idx++;
|
||||||
|
INC(candidates, 1); INC(chars, sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare the haystack allocating space for positions arrays and settings
|
||||||
|
// up the src pointers to point to the correct locations
|
||||||
|
Candidate *haystack = &ITEM(candidates, 0);
|
||||||
|
len_t *positions = (len_t*)calloc(SIZE(candidates), sizeof(len_t) * global->needle_len);
|
||||||
|
if (positions) {
|
||||||
|
text_t *cdata = &ITEM(chars, 0);
|
||||||
|
for (size_t i = 0, off = 0; i < SIZE(candidates); i++) {
|
||||||
|
haystack[i].positions = positions + (i * global->needle_len);
|
||||||
|
haystack[i].src = cdata + off;
|
||||||
|
off += haystack[i].src_sz;
|
||||||
|
}
|
||||||
|
global->haystack = haystack;
|
||||||
|
global->haystack_count = SIZE(candidates);
|
||||||
|
ret = run_threaded(opts->num_threads, global);
|
||||||
|
if (ret == 0) output_results(global, haystack, SIZE(candidates), opts, global->needle_len);
|
||||||
|
else { REPORT_OOM; }
|
||||||
|
} else { ret = 1; REPORT_OOM; }
|
||||||
|
|
||||||
|
FREE_VEC(chars); free(positions); FREE_VEC(candidates);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
copy_unicode_object(PyObject *src, text_t *dest, size_t dest_sz) {
|
||||||
|
PyUnicode_READY(src);
|
||||||
|
int kind = PyUnicode_KIND(src);
|
||||||
|
void *data = PyUnicode_DATA(src);
|
||||||
|
size_t len = PyUnicode_GetLength(src);
|
||||||
|
for (size_t i = 0; i < len && i < dest_sz; i++) {
|
||||||
|
dest[i] = PyUnicode_READ(kind, data, i);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
match(PyObject *self, PyObject *args) {
|
||||||
|
(void)(self);
|
||||||
|
int output_positions;
|
||||||
|
unsigned long limit;
|
||||||
|
PyObject *lines, *levels, *needle, *mark_before, *mark_after, *delimiter;
|
||||||
|
Options opts = {0};
|
||||||
|
GlobalData global = {0};
|
||||||
|
if (!PyArg_ParseTuple(args, "O!O!UpkiUUU",
|
||||||
|
&PyList_Type, &lines, &PyTuple_Type, &levels, &needle,
|
||||||
|
&output_positions, &limit, &opts.num_threads,
|
||||||
|
&mark_before, &mark_after, &delimiter
|
||||||
|
)) return NULL;
|
||||||
|
opts.output_positions = output_positions ? true : false;
|
||||||
|
opts.limit = limit;
|
||||||
|
global.level1_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 0), global.level1, arraysz(global.level1));
|
||||||
|
global.level2_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 1), global.level2, arraysz(global.level2));
|
||||||
|
global.level3_len = copy_unicode_object(PyTuple_GET_ITEM(levels, 2), global.level3, arraysz(global.level3));
|
||||||
|
global.needle_len = copy_unicode_object(needle, global.needle, arraysz(global.needle));
|
||||||
|
opts.mark_before_sz = copy_unicode_object(mark_before, opts.mark_before, arraysz(opts.mark_before));
|
||||||
|
opts.mark_after_sz = copy_unicode_object(mark_after, opts.mark_after, arraysz(opts.mark_after));
|
||||||
|
opts.delimiter_sz = copy_unicode_object(delimiter, opts.delimiter, arraysz(opts.delimiter));
|
||||||
|
size_t num_lines = PyList_GET_SIZE(lines);
|
||||||
|
char **clines = malloc(sizeof(char*) * num_lines);
|
||||||
|
if (!clines) { return PyErr_NoMemory(); }
|
||||||
|
size_t *sizes = malloc(sizeof(size_t) * num_lines);
|
||||||
|
if (!sizes) { free(clines); clines = NULL; return PyErr_NoMemory(); }
|
||||||
|
for (size_t i = 0; i < num_lines; i++) {
|
||||||
|
clines[i] = PyBytes_AS_STRING(PyList_GET_ITEM(lines, i));
|
||||||
|
sizes[i] = PyBytes_GET_SIZE(PyList_GET_ITEM(lines, i));
|
||||||
|
}
|
||||||
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
run_search(&opts, &global, (const char* const *)clines, sizes, num_lines);
|
||||||
|
Py_END_ALLOW_THREADS;
|
||||||
|
free(clines); free(sizes);
|
||||||
|
if (global.oom) { free(global.output); return PyErr_NoMemory(); }
|
||||||
|
if (global.output) {
|
||||||
|
PyObject *ans = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, global.output, global.output_pos);
|
||||||
|
free(global.output);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef module_methods[] = {
|
||||||
|
{"match", match, METH_VARARGS, ""},
|
||||||
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct PyModuleDef module = {
|
||||||
|
.m_base = PyModuleDef_HEAD_INIT,
|
||||||
|
.m_name = "subseq_matcher", /* name of module */
|
||||||
|
.m_doc = NULL,
|
||||||
|
.m_size = -1,
|
||||||
|
.m_methods = module_methods
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPORTED PyMODINIT_FUNC
|
||||||
|
PyInit_subseq_matcher(void) {
|
||||||
|
return PyModule_Create(&module);
|
||||||
|
}
|
||||||
72
kittens/choose/main.py
Normal file
72
kittens/choose/main.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
from ..tui.handler import Handler
|
||||||
|
from ..tui.loop import Loop
|
||||||
|
|
||||||
|
from . import subseq_matcher
|
||||||
|
|
||||||
|
|
||||||
|
def match(
|
||||||
|
input_data,
|
||||||
|
query,
|
||||||
|
threads=0,
|
||||||
|
positions=False,
|
||||||
|
level1='/',
|
||||||
|
level2='-_0123456789',
|
||||||
|
level3='.',
|
||||||
|
limit=0,
|
||||||
|
mark_before='',
|
||||||
|
mark_after='',
|
||||||
|
delimiter='\n'
|
||||||
|
):
|
||||||
|
if isinstance(input_data, str):
|
||||||
|
input_data = input_data.encode('utf-8')
|
||||||
|
if isinstance(input_data, bytes):
|
||||||
|
input_data = input_data.split(delimiter.encode('utf-8'))
|
||||||
|
else:
|
||||||
|
input_data = [x.encode('utf-8') if isinstance(x, str) else x for x in input_data]
|
||||||
|
query = query.lower()
|
||||||
|
level1 = level1.lower()
|
||||||
|
level2 = level2.lower()
|
||||||
|
level3 = level3.lower()
|
||||||
|
data = subseq_matcher.match(
|
||||||
|
input_data, (level1, level2, level3), query,
|
||||||
|
positions, limit, threads,
|
||||||
|
mark_before, mark_after, delimiter)
|
||||||
|
if data is None:
|
||||||
|
return []
|
||||||
|
return list(filter(None, data.split(delimiter or '\n')))
|
||||||
|
|
||||||
|
|
||||||
|
class ChooseHandler(Handler):
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_text(self, text, in_bracketed_paste=False):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_key(self, key_event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_interrupt(self):
|
||||||
|
self.quit_loop(1)
|
||||||
|
|
||||||
|
def on_eot(self):
|
||||||
|
self.quit_loop(1)
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
loop = Loop()
|
||||||
|
handler = ChooseHandler()
|
||||||
|
loop.loop(handler)
|
||||||
|
raise SystemExit(loop.return_code)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv)
|
||||||
105
kittens/choose/output.c
Normal file
105
kittens/choose/output.c
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* output.c
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "choose-data-types.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef ISWINDOWS
|
||||||
|
#include <io.h>
|
||||||
|
#define STDOUT_FILENO 1
|
||||||
|
static inline ssize_t ms_write(int fd, const void* buf, size_t count) { return _write(fd, buf, (unsigned int)count); }
|
||||||
|
#define write ms_write
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define FIELD(x, which) (((Candidate*)(x))->which)
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
ensure_space(GlobalData *global, size_t sz) {
|
||||||
|
if (global->output_sz < sz + global->output_pos) {
|
||||||
|
size_t before = global->output_sz;
|
||||||
|
global->output_sz += MAX(sz, (64 * 1024));
|
||||||
|
global->output = realloc(global->output, sizeof(text_t) * global->output_sz);
|
||||||
|
if (!global->output) {
|
||||||
|
global->output_sz = before;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
output_text(GlobalData *global, const text_t *data, size_t sz) {
|
||||||
|
if (ensure_space(global, sz)) {
|
||||||
|
memcpy(global->output + global->output_pos, data, sizeof(text_t) * sz);
|
||||||
|
global->output_pos += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmpscore(const void *a, const void *b) {
|
||||||
|
double sa = FIELD(a, score), sb = FIELD(b, score);
|
||||||
|
// Sort descending
|
||||||
|
return (sa > sb) ? -1 : ((sa == sb) ? ((int)FIELD(a, idx) - (int)FIELD(b, idx)) : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_with_marks(GlobalData *global, Options *opts, text_t *src, size_t src_sz, len_t *positions, len_t poslen) {
|
||||||
|
size_t pos, i = 0;
|
||||||
|
for (pos = 0; pos < poslen; pos++, i++) {
|
||||||
|
output_text(global, src + i, MIN(src_sz, positions[pos]) - i);
|
||||||
|
i = positions[pos];
|
||||||
|
if (i < src_sz) {
|
||||||
|
if (opts->mark_before_sz > 0) output_text(global, opts->mark_before, opts->mark_before_sz);
|
||||||
|
output_text(global, src + i, 1);
|
||||||
|
if (opts->mark_after_sz > 0) output_text(global, opts->mark_after, opts->mark_after_sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = positions[poslen - 1];
|
||||||
|
if (i + 1 < src_sz) output_text(global, src + i + 1, src_sz - i - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_positions(GlobalData *global, len_t *positions, len_t num) {
|
||||||
|
wchar_t buf[128];
|
||||||
|
for (len_t i = 0; i < num; i++) {
|
||||||
|
int num = swprintf(buf, sizeof(buf)/sizeof(buf[0]), L"%u", positions[i]);
|
||||||
|
if (num > 0 && ensure_space(global, num + 1)) {
|
||||||
|
for (int i = 0; i < num; i++) global->output[global->output_pos++] = buf[i];
|
||||||
|
global->output[global->output_pos++] = (i == num - 1) ? ',' : ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
output_result(GlobalData *global, Candidate *c, Options *opts, len_t needle_len) {
|
||||||
|
if (opts->output_positions) output_positions(global, c->positions, needle_len);
|
||||||
|
if (opts->mark_before_sz > 0 || opts->mark_after_sz > 0) {
|
||||||
|
output_with_marks(global, opts, c->src, c->src_sz, c->positions, needle_len);
|
||||||
|
} else {
|
||||||
|
output_text(global, c->src, c->src_sz);
|
||||||
|
}
|
||||||
|
output_text(global, opts->delimiter, opts->delimiter_sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
output_results(GlobalData *global, Candidate *haystack, size_t count, Options *opts, len_t needle_len) {
|
||||||
|
Candidate *c;
|
||||||
|
qsort(haystack, count, sizeof(*haystack), cmpscore);
|
||||||
|
size_t left = opts->limit > 0 ? opts->limit : count;
|
||||||
|
for (size_t i = 0; i < left; i++) {
|
||||||
|
c = haystack + i;
|
||||||
|
if (c->score > 0) output_result(global, c, opts, needle_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
182
kittens/choose/score.c
Normal file
182
kittens/choose/score.c
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* score.c
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "choose-data-types.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
len_t *positions_buf; // buffer to store positions for every char in needle
|
||||||
|
len_t **positions; // Array of pointers into positions_buf
|
||||||
|
len_t *positions_count; // Array of counts for positions
|
||||||
|
len_t needle_len; // Length of the needle
|
||||||
|
len_t max_haystack_len; // Max length of a string in the haystack
|
||||||
|
len_t haystack_len; // Length of the current string in the haystack
|
||||||
|
len_t *address; // Array of offsets into the positions array
|
||||||
|
double max_score_per_char;
|
||||||
|
uint8_t *level_factors; // Array of score factors for every character in the current haystack that matches a character in the needle
|
||||||
|
text_t *level1, *level2, *level3; // The characters in the levels
|
||||||
|
len_t level1_len, level2_len, level3_len;
|
||||||
|
text_t *needle; // The current needle
|
||||||
|
text_t *haystack; //The current haystack
|
||||||
|
} WorkSpace;
|
||||||
|
|
||||||
|
void*
|
||||||
|
alloc_workspace(len_t max_haystack_len, GlobalData *global) {
|
||||||
|
WorkSpace *ans = calloc(1, sizeof(WorkSpace));
|
||||||
|
if (ans == NULL) return NULL;
|
||||||
|
ans->positions_buf = (len_t*) calloc(global->needle_len, sizeof(len_t) * max_haystack_len);
|
||||||
|
ans->positions = (len_t**)calloc(global->needle_len, sizeof(len_t*));
|
||||||
|
ans->positions_count = (len_t*)calloc(2*global->needle_len, sizeof(len_t));
|
||||||
|
ans->level_factors = (uint8_t*)calloc(max_haystack_len, sizeof(uint8_t));
|
||||||
|
if (ans->positions == NULL || ans->positions_buf == NULL || ans->positions_count == NULL || ans->level_factors == NULL) { free_workspace(ans); return NULL; }
|
||||||
|
ans->needle = global->needle;
|
||||||
|
ans->needle_len = global->needle_len;
|
||||||
|
ans->max_haystack_len = max_haystack_len;
|
||||||
|
ans->level1 = global->level1; ans->level2 = global->level2; ans->level3 = global->level3;
|
||||||
|
ans->level1_len = global->level1_len; ans->level2_len = global->level2_len; ans->level3_len = global->level3_len;
|
||||||
|
ans->address = ans->positions_count + sizeof(len_t) * global->needle_len;
|
||||||
|
for (len_t i = 0; i < global->needle_len; i++) ans->positions[i] = ans->positions_buf + i * max_haystack_len;
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NUKE(x) free(x); x = NULL;
|
||||||
|
|
||||||
|
void*
|
||||||
|
free_workspace(void *v) {
|
||||||
|
WorkSpace *w = (WorkSpace*)v;
|
||||||
|
NUKE(w->positions_buf);
|
||||||
|
NUKE(w->positions);
|
||||||
|
NUKE(w->positions_count);
|
||||||
|
NUKE(w->level_factors);
|
||||||
|
free(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
has_char(text_t *text, len_t sz, text_t ch) {
|
||||||
|
for(len_t i = 0; i < sz; i++) {
|
||||||
|
if(text[i] == ch) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint8_t
|
||||||
|
level_factor_for(text_t current, text_t last, WorkSpace *w) {
|
||||||
|
text_t lch = LOWERCASE(last);
|
||||||
|
if (has_char(w->level1, w->level1_len, lch)) return 90;
|
||||||
|
if (has_char(w->level2, w->level2_len, lch)) return 80;
|
||||||
|
if (IS_LOWERCASE(last) && IS_UPPERCASE(current)) return 80; // CamelCase
|
||||||
|
if (has_char(w->level3, w->level3_len, lch)) return 70;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_workspace(WorkSpace *w, text_t *haystack, len_t haystack_len) {
|
||||||
|
// Calculate the positions and level_factors arrays for the specified haystack
|
||||||
|
bool level_factor_calculated = false;
|
||||||
|
memset(w->positions_count, 0, sizeof(*(w->positions_count)) * 2 * w->needle_len);
|
||||||
|
memset(w->level_factors, 0, sizeof(*(w->level_factors)) * w->max_haystack_len);
|
||||||
|
for (len_t i = 0; i < haystack_len; i++) {
|
||||||
|
level_factor_calculated = false;
|
||||||
|
for (len_t j = 0; j < w->needle_len; j++) {
|
||||||
|
if (w->needle[j] == LOWERCASE(haystack[i])) {
|
||||||
|
if (!level_factor_calculated) {
|
||||||
|
level_factor_calculated = true;
|
||||||
|
w->level_factors[i] = i > 0 ? level_factor_for(haystack[i], haystack[i-1], w) : 0;
|
||||||
|
}
|
||||||
|
w->positions[j][w->positions_count[j]++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w->haystack = haystack;
|
||||||
|
w->haystack_len = haystack_len;
|
||||||
|
w->max_score_per_char = (1.0 / haystack_len + 1.0 / w->needle_len) / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
has_atleast_one_match(WorkSpace *w) {
|
||||||
|
int p = -1;
|
||||||
|
bool found;
|
||||||
|
for (len_t i = 0; i < w->needle_len; i++) {
|
||||||
|
if (w->positions_count[i] == 0) return false; // All characters of the needle are not present in the haystack
|
||||||
|
found = false;
|
||||||
|
for (len_t j = 0; j < w->positions_count[i]; j++) {
|
||||||
|
if (w->positions[i][j] > p) { p = w->positions[i][j]; found = true; break; }
|
||||||
|
}
|
||||||
|
if (!found) return false; // Characters of needle not present in sequence in haystack
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define POSITION(x) w->positions[x][w->address[x]]
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
increment_address(WorkSpace *w) {
|
||||||
|
len_t pos = w->needle_len - 1;
|
||||||
|
while(true) {
|
||||||
|
w->address[pos]++;
|
||||||
|
if (w->address[pos] < w->positions_count[pos]) return true;
|
||||||
|
if (pos == 0) break;
|
||||||
|
w->address[pos--] = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
address_is_monotonic(WorkSpace *w) {
|
||||||
|
// Check if the character positions pointed to by the current address are monotonic
|
||||||
|
for (len_t i = 1; i < w->needle_len; i++) {
|
||||||
|
if (POSITION(i) <= POSITION(i-1)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
calc_score(WorkSpace *w) {
|
||||||
|
double ans = 0;
|
||||||
|
len_t distance, pos;
|
||||||
|
for (len_t i = 0; i < w->needle_len; i++) {
|
||||||
|
pos = POSITION(i);
|
||||||
|
if (i == 0) distance = pos < LEN_MAX ? pos + 1 : LEN_MAX;
|
||||||
|
else {
|
||||||
|
distance = pos - POSITION(i-1);
|
||||||
|
if (distance < 2) {
|
||||||
|
ans += w->max_score_per_char; // consecutive characters
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (w->level_factors[pos]) ans += (100 * w->max_score_per_char) / w->level_factors[pos]; // at a special location
|
||||||
|
else ans += (0.75 * w->max_score_per_char) / distance;
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
process_item(WorkSpace *w, len_t *match_positions) {
|
||||||
|
double highscore = 0, score;
|
||||||
|
do {
|
||||||
|
if (!address_is_monotonic(w)) continue;
|
||||||
|
score = calc_score(w);
|
||||||
|
if (score > highscore) {
|
||||||
|
highscore = score;
|
||||||
|
for (len_t i = 0; i < w->needle_len; i++) match_positions[i] = POSITION(i);
|
||||||
|
}
|
||||||
|
} while(increment_address(w));
|
||||||
|
return highscore;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
score_item(void *v, text_t *haystack, len_t haystack_len, len_t *match_positions) {
|
||||||
|
WorkSpace *w = (WorkSpace*)v;
|
||||||
|
init_workspace(w, haystack, haystack_len);
|
||||||
|
if (!has_atleast_one_match(w)) return 0;
|
||||||
|
return process_item(w, match_positions);
|
||||||
|
}
|
||||||
50
kittens/choose/unix_compat.c
Normal file
50
kittens/choose/unix_compat.c
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* unix_compat.c
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "choose-data-types.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#ifndef _SC_NPROCESSORS_ONLN
|
||||||
|
#define _SC_NPROCESSORS_ONLN 58
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
cpu_count() {
|
||||||
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
alloc_threads(size_t num_threads) {
|
||||||
|
return calloc(num_threads, sizeof(pthread_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
start_thread(void* threads, size_t i, void *(*start_routine) (void *), void *arg) {
|
||||||
|
int rc;
|
||||||
|
if ((rc = pthread_create(((pthread_t*)threads) + i, NULL, start_routine, arg))) {
|
||||||
|
fprintf(stderr, "Failed to create thread, with error: %s\n", strerror(rc));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wait_for_thread(void *threads, size_t i) {
|
||||||
|
pthread_join(((pthread_t*)(threads))[i], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_threads(void *threads) {
|
||||||
|
free(threads);
|
||||||
|
}
|
||||||
41
kittens/choose/vector.h
Normal file
41
kittens/choose/vector.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "data-types.h"
|
||||||
|
|
||||||
|
#define REPORT_OOM global->oom = 1;
|
||||||
|
|
||||||
|
#define VECTOR_OF(TYPE, NAME) typedef struct { \
|
||||||
|
TYPE *data; \
|
||||||
|
size_t size; \
|
||||||
|
size_t capacity; \
|
||||||
|
} NAME;
|
||||||
|
|
||||||
|
#define ALLOC_VEC(TYPE, vec, cap) \
|
||||||
|
vec.size = 0; vec.capacity = cap; \
|
||||||
|
vec.data = (TYPE*)malloc(vec.capacity * sizeof(TYPE)); \
|
||||||
|
if (vec.data == NULL) { REPORT_OOM; }
|
||||||
|
|
||||||
|
#define FREE_VEC(vec) \
|
||||||
|
if (vec.data) { free(vec.data); vec.data = NULL; } \
|
||||||
|
vec.size = 0; vec.capacity = 0;
|
||||||
|
|
||||||
|
#define ENSURE_SPACE(TYPE, vec, amt) \
|
||||||
|
if (vec.size + amt >= vec.capacity) { \
|
||||||
|
vec.capacity = MAX(vec.capacity * 2, vec.size + amt); \
|
||||||
|
vec.data = (TYPE*)realloc(vec.data, sizeof(TYPE) * vec.capacity); \
|
||||||
|
if (vec.data == NULL) { REPORT_OOM; ret = 1; break; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NEXT(vec) (vec.data[vec.size])
|
||||||
|
|
||||||
|
#define INC(vec, amt) vec.size += amt;
|
||||||
|
|
||||||
|
#define SIZE(vec) (vec.size)
|
||||||
|
|
||||||
|
#define ITEM(vec, n) (vec.data[n])
|
||||||
107
kittens/choose/windows_compat.c
Normal file
107
kittens/choose/windows_compat.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* windows_compat.c
|
||||||
|
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "choose-data-types.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <process.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
cpu_count() {
|
||||||
|
SYSTEM_INFO sysinfo;
|
||||||
|
GetSystemInfo(&sysinfo);
|
||||||
|
return sysinfo.dwNumberOfProcessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
alloc_threads(size_t num_threads) {
|
||||||
|
return calloc(num_threads, sizeof(uintptr_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
start_thread(void* vt, size_t i, unsigned int (STDCALL *start_routine) (void *), void *arg) {
|
||||||
|
uintptr_t *threads = (uintptr_t*)vt;
|
||||||
|
errno = 0;
|
||||||
|
threads[i] = _beginthreadex(NULL, 0, start_routine, arg, 0, NULL);
|
||||||
|
if (threads[i] == 0) {
|
||||||
|
perror("Failed to create thread, with error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wait_for_thread(void *vt, size_t i) {
|
||||||
|
uintptr_t *threads = vt;
|
||||||
|
WaitForSingleObject((HANDLE)threads[i], INFINITE);
|
||||||
|
CloseHandle((HANDLE)threads[i]);
|
||||||
|
threads[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
free_threads(void *threads) {
|
||||||
|
free(threads);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
getdelim(char **lineptr, size_t *n, int delim, FILE *stream) {
|
||||||
|
char c, *cur_pos, *new_lineptr;
|
||||||
|
size_t new_lineptr_len;
|
||||||
|
|
||||||
|
if (lineptr == NULL || n == NULL || stream == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*lineptr == NULL) {
|
||||||
|
*n = 8192; /* init len */
|
||||||
|
if ((*lineptr = (char *)malloc(*n)) == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_pos = *lineptr;
|
||||||
|
for (;;) {
|
||||||
|
c = getc(stream);
|
||||||
|
|
||||||
|
if (ferror(stream) || (c == EOF && cur_pos == *lineptr))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (c == EOF)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ((*lineptr + *n - cur_pos) < 2) {
|
||||||
|
if (SSIZE_MAX / 2 < *n) {
|
||||||
|
#ifdef EOVERFLOW
|
||||||
|
errno = EOVERFLOW;
|
||||||
|
#else
|
||||||
|
errno = ERANGE; /* no EOVERFLOW defined */
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
new_lineptr_len = *n * 2;
|
||||||
|
|
||||||
|
if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*lineptr = new_lineptr;
|
||||||
|
*n = new_lineptr_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cur_pos++ = c;
|
||||||
|
|
||||||
|
if (c == delim)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cur_pos = '\0';
|
||||||
|
return (ssize_t)(cur_pos - *lineptr);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
@@ -22,6 +22,12 @@ class Clipboard(Handler):
|
|||||||
if self.data_to_send is not None:
|
if self.data_to_send is not None:
|
||||||
self.cmd.write_to_clipboard(self.data_to_send, self.args.use_primary)
|
self.cmd.write_to_clipboard(self.data_to_send, self.args.use_primary)
|
||||||
if not self.args.get_clipboard:
|
if not self.args.get_clipboard:
|
||||||
|
if self.args.wait_for_completion:
|
||||||
|
# ask kitty for the TN terminfo capability and
|
||||||
|
# only quit after a response is received
|
||||||
|
self.print('\x1bP+q544e\x1b\\', end='')
|
||||||
|
self.print('Waiting for completion...')
|
||||||
|
return
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
return
|
return
|
||||||
self.cmd.request_from_clipboard(self.args.use_primary)
|
self.cmd.request_from_clipboard(self.args.use_primary)
|
||||||
@@ -30,6 +36,15 @@ class Clipboard(Handler):
|
|||||||
self.clipboard_contents = text
|
self.clipboard_contents = text
|
||||||
self.quit_loop(0)
|
self.quit_loop(0)
|
||||||
|
|
||||||
|
def on_capability_response(self, name, val):
|
||||||
|
self.quit_loop(0)
|
||||||
|
|
||||||
|
def on_interrupt(self):
|
||||||
|
self.quit_loop(1)
|
||||||
|
|
||||||
|
def on_eot(self):
|
||||||
|
self.quit_loop(1)
|
||||||
|
|
||||||
|
|
||||||
OPTIONS = r'''
|
OPTIONS = r'''
|
||||||
--get-clipboard
|
--get-clipboard
|
||||||
@@ -45,6 +60,13 @@ default=False
|
|||||||
type=bool-set
|
type=bool-set
|
||||||
Use the primary selection rather than the clipboard on systems that support it,
|
Use the primary selection rather than the clipboard on systems that support it,
|
||||||
such as X11.
|
such as X11.
|
||||||
|
|
||||||
|
|
||||||
|
--wait-for-completion
|
||||||
|
default=False
|
||||||
|
type=bool-set
|
||||||
|
Wait till the copy to clipboard is complete before exiting. Useful if running
|
||||||
|
the kitten in a dedicated, ephemeral window.
|
||||||
'''.format
|
'''.format
|
||||||
help_text = '''\
|
help_text = '''\
|
||||||
Read or write to the system clipboard.
|
Read or write to the system clipboard.
|
||||||
@@ -54,6 +76,7 @@ To set the clipboard text, pipe in the new text on stdin. Use the
|
|||||||
:file:`stdout`. Note that you must enable reading of clipboard in
|
:file:`stdout`. Note that you must enable reading of clipboard in
|
||||||
:file:`kitty.conf` first.
|
:file:`kitty.conf` first.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
usage = ''
|
usage = ''
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user