Compare commits
810 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 | ||
|
|
fbccfb9d0d | ||
|
|
9fdd8e4ae4 | ||
|
|
6b6dea5190 | ||
|
|
5af551c96d | ||
|
|
6761fdca1a | ||
|
|
725da39ecb | ||
|
|
9005fc359d | ||
|
|
33e4a44008 | ||
|
|
3bddb9d95b | ||
|
|
fa01e0b76f | ||
|
|
f8f188ecff | ||
|
|
07935d9bd3 | ||
|
|
a827f4190c | ||
|
|
18c108ed03 | ||
|
|
2d70059f47 | ||
|
|
63ff3cfb9f | ||
|
|
ca70f22d46 | ||
|
|
c247a6c0cc | ||
|
|
7421a0b9e3 | ||
|
|
30b5e8bf8f | ||
|
|
96475ce3ee | ||
|
|
24669fb6af | ||
|
|
851885568f | ||
|
|
8efbc479e1 | ||
|
|
2167bfd5b5 | ||
|
|
490d4455af | ||
|
|
c94e06ccd2 | ||
|
|
ea37799fb0 | ||
|
|
d00fbd73fc | ||
|
|
361b23e3f1 | ||
|
|
8feccdf63f | ||
|
|
ed905fcf6d | ||
|
|
50a6abaac1 | ||
|
|
718f7e77a1 | ||
|
|
c4aeb1adba | ||
|
|
d9c69f0a54 | ||
|
|
5afdbbe6f1 | ||
|
|
4273cb35bf | ||
|
|
89be7a031d | ||
|
|
06c5127856 | ||
|
|
fd298256d7 | ||
|
|
e0246044b7 | ||
|
|
2f677990b2 | ||
|
|
da2e4c8503 | ||
|
|
a1eb236616 | ||
|
|
11186735c2 | ||
|
|
a038f62a5b | ||
|
|
f45acc055e | ||
|
|
43a25c49c4 | ||
|
|
e47e2b2560 | ||
|
|
7652065134 | ||
|
|
d0da418e49 | ||
|
|
77e72cfd9a | ||
|
|
7b2ecb0498 | ||
|
|
318c5bca67 | ||
|
|
d52da934ca | ||
|
|
21951e3668 | ||
|
|
64bef38813 | ||
|
|
fe67e3dde7 | ||
|
|
fc5e74e457 | ||
|
|
fdbd8df7b2 | ||
|
|
246972b59f | ||
|
|
6057296499 | ||
|
|
b4b2207b93 | ||
|
|
b881364c50 | ||
|
|
76059882c4 | ||
|
|
be71f5f1f4 | ||
|
|
021dfcad39 | ||
|
|
4e7498b854 | ||
|
|
494035c94b | ||
|
|
9c4230ad9c | ||
|
|
056c2c12bb | ||
|
|
a97c440872 | ||
|
|
653d823175 | ||
|
|
c2a2dbc88c | ||
|
|
77492d31cf | ||
|
|
aaa609109e | ||
|
|
2367fad90b | ||
|
|
aaa521bd24 | ||
|
|
d22686da10 | ||
|
|
48b93ab28f | ||
|
|
703a1b83a8 | ||
|
|
c9441bd3e2 | ||
|
|
9de6d619ee | ||
|
|
9aae31ef2f | ||
|
|
dca04c549b | ||
|
|
69e76d6eeb | ||
|
|
b4a93c67c9 | ||
|
|
f098e6c973 | ||
|
|
f8ebba3954 | ||
|
|
37ee693de2 | ||
|
|
f77ad2b41d | ||
|
|
e99eb2e72b | ||
|
|
86b89072f3 | ||
|
|
022bee0560 | ||
|
|
204ea44946 | ||
|
|
3f2489b306 | ||
|
|
291a2d6295 | ||
|
|
b244d13e8a | ||
|
|
b33324d07c | ||
|
|
ae2a641db5 | ||
|
|
1cac757365 | ||
|
|
992de77040 | ||
|
|
f6b5e54890 | ||
|
|
d20c65ef80 | ||
|
|
4a8562a85f | ||
|
|
1ba7b5f5a3 | ||
|
|
f895b7f8cb | ||
|
|
16542e96bf | ||
|
|
3005b8b9d6 | ||
|
|
35653ef4b4 | ||
|
|
36b3582825 | ||
|
|
c17c801a31 | ||
|
|
460c353898 | ||
|
|
3fa7007e91 | ||
|
|
4cf6373203 | ||
|
|
e0b3bb1830 | ||
|
|
47ec372c30 | ||
|
|
d5366a421f | ||
|
|
3d5977669e | ||
|
|
36da668e6f | ||
|
|
052913c656 | ||
|
|
0ef055a2b2 | ||
|
|
a7bd6922e5 | ||
|
|
8d9ba4a772 | ||
|
|
222beedc2a | ||
|
|
8ba8320189 | ||
|
|
3501a2a1da | ||
|
|
819ee94a70 | ||
|
|
7e7dbc5ecf | ||
|
|
3a6bc94d25 | ||
|
|
07a4cec616 | ||
|
|
60de840d69 | ||
|
|
928167c0b2 | ||
|
|
2aac220cdb | ||
|
|
d8a74e8a3c | ||
|
|
019e6efeda | ||
|
|
a7a7216b30 | ||
|
|
ae8ca5272b | ||
|
|
06c1236cc6 | ||
|
|
4d3982c5cf | ||
|
|
a0ff625f61 | ||
|
|
b44345d78e | ||
|
|
96229becd1 | ||
|
|
b269cab0b8 | ||
|
|
0b3c8210f3 | ||
|
|
074614bc8e | ||
|
|
4ceb4cfc22 | ||
|
|
0bb08d8bdd | ||
|
|
b9e6557f72 | ||
|
|
7ed268ea2f | ||
|
|
a91b3b9487 | ||
|
|
cdf236d01b | ||
|
|
f54efb7886 | ||
|
|
0ffee56170 | ||
|
|
ab97646576 | ||
|
|
33b62dcabc | ||
|
|
39e6e91d69 | ||
|
|
dedd80c6b5 | ||
|
|
df11da74e9 | ||
|
|
9991dd6ce4 | ||
|
|
e777364f91 | ||
|
|
a32ed5ae5f | ||
|
|
db1e48848d | ||
|
|
c02fa79591 | ||
|
|
6f0a59c696 | ||
|
|
bc715d4348 | ||
|
|
55e4761302 | ||
|
|
18fe2e8dfa | ||
|
|
18a07a78b5 | ||
|
|
aa7024b264 | ||
|
|
c67ab2a6ff | ||
|
|
d15eab31da | ||
|
|
a6900443d5 | ||
|
|
235bcacc7b | ||
|
|
3e26f96744 | ||
|
|
718111582a | ||
|
|
f5cdbe53ea | ||
|
|
bf761a7189 | ||
|
|
05ee01b4dd | ||
|
|
53166d659e | ||
|
|
34aea3bca1 | ||
|
|
f26519863f | ||
|
|
a57e96500a | ||
|
|
5e27c21856 | ||
|
|
4601cd13dc | ||
|
|
ad92541ff3 | ||
|
|
3f77a2044e | ||
|
|
75e57a48e0 | ||
|
|
160fbd2071 | ||
|
|
f5743f4610 | ||
|
|
82f9aecacb | ||
|
|
be6556c884 | ||
|
|
f941ffb1fe | ||
|
|
cbdba0b6aa | ||
|
|
ce04f102a7 | ||
|
|
fc3bd2d15f | ||
|
|
a958cabf01 | ||
|
|
d0a2eab79e | ||
|
|
b835afefee | ||
|
|
d0a7be90f9 | ||
|
|
1f3550b84c | ||
|
|
939212e1d4 | ||
|
|
7db6318806 | ||
|
|
e5d9182606 | ||
|
|
d519553581 | ||
|
|
e99b1be023 | ||
|
|
e460866ebc | ||
|
|
23aea68e32 | ||
|
|
65c2cbe93a | ||
|
|
ee31ba0c76 | ||
|
|
3ed9d9a069 | ||
|
|
721e51c117 | ||
|
|
09daaf1ec3 | ||
|
|
b2d62f10d2 | ||
|
|
0d542b2f60 | ||
|
|
04fd058e0f | ||
|
|
31a0a9427e | ||
|
|
04f10ba570 | ||
|
|
34b7b2e4e8 | ||
|
|
09183772d3 | ||
|
|
3e4eca5816 | ||
|
|
30c6c4697f | ||
|
|
b650275d45 | ||
|
|
174bd5c57f | ||
|
|
ec51a219a7 | ||
|
|
cca2fb967c | ||
|
|
5b547d9b06 | ||
|
|
facb2df3f6 | ||
|
|
8395076da5 | ||
|
|
e113e0cba7 | ||
|
|
407d19c2dc | ||
|
|
382367506a | ||
|
|
bd5a85a4e7 | ||
|
|
631f97eb26 | ||
|
|
0c0ce4844c | ||
|
|
6bf290149e | ||
|
|
60fa812b60 | ||
|
|
61f3a39aa0 | ||
|
|
a6949df727 | ||
|
|
d839a31d7f | ||
|
|
1de510f46f | ||
|
|
0359bbe4be | ||
|
|
40b355e593 | ||
|
|
adf9c4fc5f | ||
|
|
ae9d049011 | ||
|
|
d24977d164 | ||
|
|
3035d64127 | ||
|
|
70c9c058e2 | ||
|
|
1d9f73adec | ||
|
|
fca95af49b | ||
|
|
62fe392041 | ||
|
|
097d11819b | ||
|
|
691286f376 | ||
|
|
c910f6c832 | ||
|
|
65f9ac32ef | ||
|
|
27f2a2e3d5 | ||
|
|
88aab20376 | ||
|
|
a045ac3bd7 | ||
|
|
722b605407 | ||
|
|
7f53745077 | ||
|
|
7f902c4c03 | ||
|
|
1205c2055f | ||
|
|
f08f0f9dbd | ||
|
|
093c05e16a | ||
|
|
787100a4dc | ||
|
|
c493583f25 | ||
|
|
b4afbe47b3 | ||
|
|
6c4aeeeadd | ||
|
|
5b01519367 | ||
|
|
c494759606 | ||
|
|
2102c48b87 | ||
|
|
c498f4e8ab | ||
|
|
05a0166ebd | ||
|
|
0484365de6 | ||
|
|
cbab3b56de | ||
|
|
715f7985c7 | ||
|
|
2637018b53 | ||
|
|
1fa66ca45d | ||
|
|
13b10f691d | ||
|
|
3fe7d91713 | ||
|
|
98864091ff | ||
|
|
7750a461aa | ||
|
|
ac98b85157 | ||
|
|
21f6c6a5a8 | ||
|
|
b8d1491b99 | ||
|
|
d9c168d824 | ||
|
|
ee7f4ee1a4 | ||
|
|
ee3ce3c7d8 | ||
|
|
a57f38dbd5 | ||
|
|
3c4cb3c35b | ||
|
|
12cfe6d1d1 | ||
|
|
c64e8fc434 | ||
|
|
15f534a8f9 | ||
|
|
8e09e809aa | ||
|
|
fec5a80b89 | ||
|
|
1d50a188c4 | ||
|
|
d52434c0aa | ||
|
|
efc0b830cf | ||
|
|
618b486fd5 | ||
|
|
1986403e42 | ||
|
|
cf51f80b79 | ||
|
|
2fe17aa889 | ||
|
|
f76c8ad30b | ||
|
|
c421d3bb59 | ||
|
|
3d862da2be | ||
|
|
10b15caad9 | ||
|
|
e08238d5a0 | ||
|
|
d0104660c8 | ||
|
|
a4c2a9ef0d | ||
|
|
ee39d7ba14 |
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)
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,6 +9,7 @@ logo/*.iconset
|
||||
compile_commands.json
|
||||
glad/out
|
||||
asan-launcher
|
||||
asan-launcher.dSYM
|
||||
kitty-profile
|
||||
dev
|
||||
__pycache__
|
||||
|
||||
170
.travis.yml
170
.travis.yml
@@ -1,170 +0,0 @@
|
||||
git:
|
||||
depth: false
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
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:
|
||||
- libxi-dev
|
||||
- libxrandr-dev
|
||||
- libxinerama-dev
|
||||
- libxcursor-dev
|
||||
- libxcb-xkb-dev
|
||||
- libdbus-1-dev
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- CC=gcc CFLAGS=-funsigned-char SANITIZE_ARG=--sanitize
|
||||
language: python
|
||||
python: "3.5"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- 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: trusty
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- CC=clang SANITIZE_ARG=--sanitize
|
||||
language: python
|
||||
python: "3.5"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- 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: trusty
|
||||
group: beta
|
||||
sudo: false
|
||||
env:
|
||||
- RUN_FLAKE=1 BUILD_PKG=linux-package
|
||||
language: python
|
||||
python: "3.6"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- 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
|
||||
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
|
||||
brew update;
|
||||
brew upgrade python;
|
||||
brew install harfbuzz --without-graphite2 --without-icu4c --without-freetype;
|
||||
brew install imagemagick
|
||||
brew install optipng
|
||||
brew install librsvg
|
||||
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
|
||||
6
Brewfile
Normal file
6
Brewfile
Normal file
@@ -0,0 +1,6 @@
|
||||
brew 'pkg-config'
|
||||
brew 'imagemagick'
|
||||
brew 'optipng'
|
||||
brew 'librsvg'
|
||||
brew 'harfbuzz'
|
||||
brew 'python'
|
||||
8
LICENSE
8
LICENSE
@@ -1,7 +1,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
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
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
@@ -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,
|
||||
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
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
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
|
||||
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:
|
||||
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
|
||||
asan:
|
||||
python3 setup.py build $(VVAL) --debug --sanitize
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
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
|
||||
# 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
|
||||
# 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
|
||||
# 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 os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
||||
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>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
|
||||
@@ -1,24 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import shutil
|
||||
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:
|
||||
f.write(generate_terminfo())
|
||||
tfile = tfiles[0]
|
||||
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'])
|
||||
# On OS X tic puts the compiled database into a different directory
|
||||
try:
|
||||
os.mkdir('terminfo/78')
|
||||
except FileExistsError:
|
||||
pass
|
||||
shutil.copy2('terminfo/x/xterm-kitty', 'terminfo/78')
|
||||
|
||||
def generate_terminfo():
|
||||
base = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(base)
|
||||
sys.path.insert(0, base)
|
||||
|
||||
from kitty.terminfo import generate_terminfo
|
||||
|
||||
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
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS = -T $(FAIL_WARN)
|
||||
SPHINXBUILD = python3 .. +launch :sphinx-build
|
||||
SPHINXOPTS = -j auto -T $(FAIL_WARN)
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = kitty
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
9
docs/_templates/layout.html
vendored
9
docs/_templates/layout.html
vendored
@@ -1,13 +1,6 @@
|
||||
{% extends "!layout.html" %}
|
||||
|
||||
{%- block extrahead %}
|
||||
<!-- Google Analytics -->
|
||||
<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 -->
|
||||
<!-- kitty analytics placeholder -->
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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
|
||||
: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
|
||||
@@ -28,7 +28,7 @@ Build-time dependencies:
|
||||
* gcc or clang
|
||||
* pkg-config
|
||||
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
|
||||
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev`` and ``libxkbcommon-x11-dev``,
|
||||
``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev`` and ``libpython-dev``.
|
||||
if they are not already installed by your distro.
|
||||
|
||||
Install and run from source
|
||||
@@ -107,7 +107,13 @@ without needing to install all of |kitty|.
|
||||
development package of :file:`ncurses`. Also, if you are building from
|
||||
a git checkout instead of the released source code tarball, you will
|
||||
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
|
||||
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,409 @@ Changelog
|
||||
==============
|
||||
|
||||
|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]
|
||||
------------------------------
|
||||
|
||||
- icat kitten: Add a ``--stdin`` option to control if image data is read from
|
||||
STDIN (:iss:`1308`)
|
||||
|
||||
- hints kitten: Start hints numbering at one instead of zero by default. Added
|
||||
an option ``--hints-offset`` to control it. (:iss:`1289`)
|
||||
|
||||
- Fix a regression in the previous release that broke using ``background`` for
|
||||
:opt:`cursor_text_color` (:iss:`1288`)
|
||||
|
||||
- macOS: Fix dragging kitty window tabs in traditional full screen mode causing
|
||||
crashes (:iss:`1296`)
|
||||
|
||||
- macOS: Ensure that when running from a bundle, the bundle kitty exe is
|
||||
preferred over any kitty in PATH (:iss:`1280`)
|
||||
|
||||
- macOS: Fix a regression that broke mapping of :kbd:`ctrl+tab` (:iss:`1304`)
|
||||
|
||||
- Add a list of user-created kittens to the docs
|
||||
|
||||
- Fix a regression that broke changing mouse wheel scroll direction with
|
||||
negative :opt:`wheel_scroll_multiplier` values in full-screen applications
|
||||
like vim (:iss:`1299`)
|
||||
|
||||
- Fix :opt:`background_opacity` not working with pure white backgrounds
|
||||
(:iss:`1285`)
|
||||
|
||||
- macOS: Fix "New OS Window" dock action not working when kitty is not focused
|
||||
(:iss:`1312`)
|
||||
|
||||
- macOS: Add aliases for close window and new tab actions that conform to common
|
||||
Apple shortcuts for these actions (:iss:`1313`)
|
||||
|
||||
- macOS: Fix some kittens causing 100% CPU usage
|
||||
|
||||
|
||||
0.13.2 [2019-01-04]
|
||||
------------------------------
|
||||
|
||||
- Add a new option :opt:`tab_title_template` to control how tab titles
|
||||
are formatted. In particular the template can be used to display
|
||||
the tab number next to the title (:iss:`1223`)
|
||||
|
||||
- Report the current foreground processes as well as the original child process,
|
||||
when using `kitty @ ls`
|
||||
|
||||
- Use the current working directory of the foreground process for the
|
||||
`*_with_cwd` actions that open a new window with the current working
|
||||
directory.
|
||||
|
||||
- Add a new ``copy_or_interrupt`` action that can be mapped to kbd:`ctrl+c`. It
|
||||
will copy if there is a selection and interrupt otherwise (:iss:`1286`)
|
||||
|
||||
- Fix setting :opt:`background_opacity` causing window margins/padding to be slightly
|
||||
different shade from background (:iss:`1221`)
|
||||
|
||||
- Handle keyboards with a "+" key (:iss:`1224`)
|
||||
|
||||
- Fix Private use Unicode area characters followed by spaces at the end of text
|
||||
not being rendered correctly (:iss:`1210`)
|
||||
|
||||
- macOS: Add an entry to the dock menu to open a new OS window (:iss:`1242`)
|
||||
|
||||
- macOS: Fix scrolling very slowly with wheel mice not working (:iss:`1238`)
|
||||
|
||||
- Fix changing :opt:`cursor_text_color` via remote control not working
|
||||
(:iss:`1229`)
|
||||
|
||||
- Add an action to resize windows that can be mapped to shortcuts in :file:`kitty.conf`
|
||||
(:pull:`1245`)
|
||||
|
||||
- Fix using the ``new_tab !neighbor`` action changing the order of the
|
||||
non-neighboring tabs (:iss:`1256`)
|
||||
|
||||
- macOS: Fix momentum scrolling continuing when changing the active window/tab
|
||||
(:iss:`1267`)
|
||||
|
||||
|
||||
0.13.1 [2018-12-06]
|
||||
------------------------------
|
||||
|
||||
- Fix passing input via the pipe action to a program without a window not
|
||||
working.
|
||||
|
||||
- Linux: Fix a regression in the previous release that caused automatic
|
||||
selection of bold/italic fonts when using aliases such as "monospace" to not
|
||||
work (:iss:`1209`)
|
||||
|
||||
- Fix resizing window smaller and then restoring causing some wrapped lines to not
|
||||
be properly unwrapped (:iss:`1206`)
|
||||
|
||||
0.13.0 [2018-12-05]
|
||||
------------------------------
|
||||
|
||||
- Add an option :opt:`scrollback_pager_history_size` to tell kitty to store
|
||||
extended scrollback to use when viewing the scrollback buffer in a pager
|
||||
(:iss:`970`)
|
||||
|
||||
- Modify the kittens sub-system to allow creating custom kittens without any
|
||||
user interface. This is useful for creating more complex actions that can
|
||||
be bound to key presses in :file:`kitty.conf`. See
|
||||
doc:`kittens/custom`. (:iss:`870`)
|
||||
|
||||
- Add a new ``nth_window`` action that can be used to go to the nth window and
|
||||
also previously active windows, using negative numbers. Similarly,
|
||||
``goto_tab`` now accepts negative numbers to go to previously active tabs
|
||||
(:iss:`1040`)
|
||||
|
||||
- Allow hiding the tab bar completely, by setting :opt:`tab_bar_style` to
|
||||
``hidden``. (:iss:`1014`)
|
||||
|
||||
- Allow private use unicode characters to stretch over more than a single
|
||||
neighboring space (:pull:`1036`)
|
||||
|
||||
- Add a new :opt:`touch_scroll_multiplier` option to modify the amount
|
||||
scrolled by high precision scrolling devices such as touchpads (:pull:`1129`)
|
||||
|
||||
- icat kitten: Implement reading image data from STDIN, if STDIN is not
|
||||
connected to a terminal (:iss:`1130`)
|
||||
|
||||
- hints kitten: Insert trailing spaces after matches when using the
|
||||
``--multiple`` option. Also add a separate ``--add-trailing-space``
|
||||
option to control this behavior (:pull:`1132`)
|
||||
|
||||
- Fix the ``*_with_cwd`` actions using the cwd of the overlay window rather
|
||||
than the underlying window's cwd (:iss:`1045`)
|
||||
|
||||
- Fix incorrect key repeat rate on wayland (:pull:`1055`)
|
||||
|
||||
- macOS: Fix drag and drop of files not working on Mojave (:iss:`1058`)
|
||||
|
||||
- macOS: Fix IME input for East Asian languages (:iss:`910`)
|
||||
|
||||
- macOS: Fix rendering frames-per-second very low when processing
|
||||
large amounts of input in small chunks (:pull:`1082`)
|
||||
|
||||
- macOS: Fix incorrect text sizes calculated when using an external display
|
||||
that is set to mirror the main display (:iss:`1056`)
|
||||
|
||||
- macOS: Use the system default double click interval (:pull:`1090`)
|
||||
|
||||
- macOS: Fix touch scrolling sensitivity low on retina screens (:iss:`1112`)
|
||||
|
||||
- Linux: Fix incorrect rendering of some fonts when hinting is disabled at
|
||||
small sizes (:iss:`1173`)
|
||||
|
||||
- Linux: Fix match rules used as aliases in Fontconfig configuration not being
|
||||
respected (:iss:`1085`)
|
||||
|
||||
- Linux: Fix a crash when using the GNU Unifont as a fallback font
|
||||
(:iss:`1087`)
|
||||
|
||||
- Wayland: Fix copying from hidden kitty windows hanging (:iss:`1051`)
|
||||
|
||||
- Wayland: Add support for the primary selection protocol
|
||||
implemented by some compositors (:pull:`1095`)
|
||||
|
||||
- Fix expansion of env vars not working in the :opt:`env` directive
|
||||
(:iss:`1075`)
|
||||
|
||||
- Fix :opt:`mouse_hide_wait` only taking effect after an event such as cursor
|
||||
blink or key press (:iss:`1073`)
|
||||
|
||||
- Fix the ``set_background_opacity`` action not working correctly
|
||||
(:pull:`1147`)
|
||||
|
||||
- Fix second cell of emoji created using variation selectors not having
|
||||
the same attributes as the first cell (:iss:`1109`)
|
||||
|
||||
- Fix focusing neighboring windows in the grid layout with less than 4 windows
|
||||
not working (:iss:`1115`)
|
||||
|
||||
- Fix :kbd:`ctrl+shift+special` key not working in normal and application keyboard
|
||||
modes (:iss:`1114`)
|
||||
|
||||
- Add a terminfo entry for full keyboard mode.
|
||||
|
||||
- Fix incorrect text-antialiasing when using very low background opacity
|
||||
(:iss:`1005`)
|
||||
|
||||
- When double or triple clicking ignore clicks if they are "far" from each
|
||||
other (:iss:`1093`)
|
||||
|
||||
- Follow xterm's behavior for the menu key (:iss:`597`)
|
||||
|
||||
- Fix hover detection of URLs not working when hovering over the first colon
|
||||
and slash characters in short URLs (:iss:`1201`)
|
||||
|
||||
0.12.3 [2018-09-29]
|
||||
------------------------------
|
||||
@@ -142,6 +545,9 @@ Changelog
|
||||
- Add an option :opt:`env` to set environment variables in child processes
|
||||
from kitty.conf
|
||||
|
||||
- Add an action to the ``clear_terminal`` function to scroll the screen
|
||||
contents into the scrollback buffer (:iss:`1113`)
|
||||
|
||||
- Implement high precision scrolling with the trackpad on platforms such as
|
||||
macOS and Wayland that implement it. (:pull:`819`)
|
||||
|
||||
@@ -351,7 +757,7 @@ Changelog
|
||||
|
||||
- Add a config option (:opt:`editor`) to set the EDITOR kitty uses (:iss:`580`)
|
||||
|
||||
- Add a config option (:opt:`x11_hide_window_decorations`) to hide window
|
||||
- Add a config option (``x11_hide_window_decorations``) to hide window
|
||||
decorations under X11/Wayland (:iss:`607`)
|
||||
|
||||
- Add an option to @set-window-title to make the title change non-permanent
|
||||
|
||||
18
docs/conf.py
18
docs/conf.py
@@ -1,15 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# 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 re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from functools import partial
|
||||
|
||||
from docutils import nodes
|
||||
@@ -19,15 +22,19 @@ from pygments.token import (
|
||||
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
||||
)
|
||||
from sphinx import addnodes
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
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 {{{
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'kitty'
|
||||
copyright = '2018, Kovid Goyal'
|
||||
copyright = time.strftime('%Y, Kovid Goyal')
|
||||
author = 'Kovid Goyal'
|
||||
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=[]):
|
||||
' Link to a github issue '
|
||||
@@ -214,7 +221,8 @@ def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
|
||||
# Sidebar ToC {{{
|
||||
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:
|
||||
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
||||
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``
|
||||
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 use a relative path for include, it is resolved with respect to the
|
||||
location of the current config file. Note that environment variables are
|
||||
|
||||
46
docs/faq.rst
46
docs/faq.rst
@@ -6,7 +6,7 @@ Frequently Asked Questions
|
||||
.. contents::
|
||||
|
||||
Some special symbols are rendered small/truncated in kitty?
|
||||
-----------------------------------------------------------------
|
||||
-----------------------------------------------------------
|
||||
|
||||
The number of cells a unicode character takes up are controlled by the unicode
|
||||
standard. All characters are rendered in a single cell unless the unicode
|
||||
@@ -48,25 +48,61 @@ terminfo files to the server::
|
||||
kitty +kitten ssh myserver
|
||||
|
||||
If for some reason that does not work (typically because the server is using a
|
||||
a non POSIX compliant shell), you can use the following one-liner instead (it
|
||||
non POSIX compliant shell), you can use the following one-liner instead (it
|
||||
is slower as it needs to ssh into the server twice, but will work with most
|
||||
servers)::
|
||||
|
||||
infocmp xterm-kitty | ssh myserver tic -x -o \~/.terminfo /dev/stdin
|
||||
|
||||
If you are behind a proxy (like Balabit) that prevents this, you must redirect the
|
||||
1st command to a file, copy that to the server and run ``tic`` manually. If you
|
||||
connect to a server, embedded or Android system that doesn't have ``tic``, copy over
|
||||
your local file terminfo to the other system as :file:`~/.terminfo/x/xterm-kitty`.
|
||||
|
||||
Really, the correct solution for this is to convince the OpenSSH maintainers to
|
||||
have ssh do this automatically when connecting to a server, so that all
|
||||
terminals work transparently.
|
||||
have ssh do this automatically, if possible, when connecting to a server, so that
|
||||
all terminals work transparently.
|
||||
|
||||
|
||||
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
Make sure the TERM environment variable, is ``xterm-kitty``. And either the
|
||||
TERMINFO environment variable points to a directory containing :file:`x/xterm-kitty`
|
||||
or that file is under :file:`~/.terminfo/x/`.
|
||||
|
||||
Note that ``sudo`` might remove TERMINFO. Then setting it at the shell prompt can
|
||||
be too late, because command line editing may not be reinitialized. In that case
|
||||
you can either ask ``sudo`` to set it or if that is not supported, insert an ``env``
|
||||
command before starting the shell, or, if not possible, after sudo start another
|
||||
Shell providing the right terminfo path::
|
||||
|
||||
sudo … TERMINFO=$HOME/.terminfo bash -i
|
||||
sudo … env TERMINFO=$HOME/.terminfo 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
|
||||
explicitly set a UTF-8 locale, like::
|
||||
|
||||
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
|
||||
|
||||
|
||||
How do I change the colors in a running kitty instance?
|
||||
------------------------------------------------------------
|
||||
|
||||
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>`
|
||||
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?
|
||||
---------------------------------------------------------------
|
||||
|
||||
@@ -75,6 +75,47 @@ You can also use the *CSI t* escape code to get the screen size. Send
|
||||
``<ESC>[4;<height>;<width>t`` where *height* and *width* are the window size in
|
||||
pixels. This escape code is supported in many terminals, not just kitty.
|
||||
|
||||
A minimal example
|
||||
------------------
|
||||
|
||||
Some minimal python code to display PNG images in kitty, using the most basic
|
||||
features of the graphics protocol:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
from base64 import standard_b64encode
|
||||
|
||||
def serialize_gr_command(cmd, payload=None):
|
||||
cmd = ','.join('{}={}'.format(k, v) for k, v in cmd.items())
|
||||
ans = []
|
||||
w = ans.append
|
||||
w(b'\033_G'), w(cmd.encode('ascii'))
|
||||
if payload:
|
||||
w(b';')
|
||||
w(payload)
|
||||
w(b'\033\\')
|
||||
return b''.join(ans)
|
||||
|
||||
def write_chunked(cmd, data):
|
||||
data = standard_b64encode(data)
|
||||
while data:
|
||||
chunk, data = data[:4096], data[4096:]
|
||||
m = 1 if data else 0
|
||||
cmd['m'] = m
|
||||
sys.stdout.buffer.write(serialize_gr_command(cmd, chunk))
|
||||
sys.stdout.flush()
|
||||
cmd.clear()
|
||||
|
||||
write_chunked({'a': 'T', 'f': 100}, open(sys.argv[-1], 'rb').read())
|
||||
|
||||
|
||||
Save this script as :file:`png.py`, then you can use it to display any PNG
|
||||
file in kitty as::
|
||||
|
||||
python png.py file.png
|
||||
|
||||
|
||||
The graphics escape code
|
||||
---------------------------
|
||||
|
||||
@@ -160,7 +201,11 @@ Value of `t` Meaning
|
||||
================== ============
|
||||
``d`` Direct (the data is transmitted within the escape code itself)
|
||||
``f`` A simple file
|
||||
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data
|
||||
``t`` A temporary file, the terminal emulator will delete the file after reading the pixel data. For security reasons
|
||||
the terminal emulator should only delete the file if it
|
||||
is in a known temporary directory, such as :file:`/tmp`,
|
||||
:file:`/dev/shm`, :file:`TMPDIR env var if present` and any platform
|
||||
specific temporary directories.
|
||||
``s`` A `POSIX shared memory object <http://man7.org/linux/man-pages/man7/shm_overview.7.html>`_.
|
||||
The terminal emulator will delete it after reading the pixel data
|
||||
================== ============
|
||||
|
||||
109
docs/index.rst
109
docs/index.rst
@@ -36,6 +36,8 @@ kitty - the fast, featureful, GPU based terminal emulator
|
||||
separate window using arbitrary programs of your choice. This is useful for
|
||||
browsing the history comfortably in a pager or editor.
|
||||
|
||||
* Has :ref:`multiple copy/paste buffers <cpbuf>`, like vim.
|
||||
|
||||
|
||||
.. figure:: screenshots/screenshot.png
|
||||
: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
|
||||
: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:
|
||||
`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>`_,
|
||||
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/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>`_,
|
||||
`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
|
||||
: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
|
||||
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
|
||||
relatively less effort.
|
||||
relatively little effort.
|
||||
|
||||
Tabs and Windows
|
||||
-------------------
|
||||
@@ -108,12 +113,12 @@ Scrolling
|
||||
======================== =======================
|
||||
Action Shortcut
|
||||
======================== =======================
|
||||
Scroll line up :sc:`scroll_line_up`
|
||||
Scroll line down :sc:`scroll_line_down`
|
||||
Scroll page up :sc:`scroll_page_up`
|
||||
Scroll page down :sc:`scroll_page_down`
|
||||
Scroll to top :sc:`scroll_home`
|
||||
Scroll to bottom :sc:`scroll_end`
|
||||
Scroll line up :sc:`scroll_line_up` (also :kbd:`⌥+⌘+⇞` and :kbd:`⌘+↑` on macOS)
|
||||
Scroll line down :sc:`scroll_line_down` (also :kbd:`⌥+⌘+⇟` and :kbd:`⌘+↓` on macOS)
|
||||
Scroll page up :sc:`scroll_page_up` (also :kbd:`⌘+⇞` on macOS)
|
||||
Scroll page down :sc:`scroll_page_down` (also :kbd:`⌘+⇟` on macOS)
|
||||
Scroll to top :sc:`scroll_home` (also :kbd:`⌘+↖` on macOS)
|
||||
Scroll to bottom :sc:`scroll_end` (also :kbd:`⌘+↘` on macOS)
|
||||
======================== =======================
|
||||
|
||||
Tabs
|
||||
@@ -122,14 +127,14 @@ Tabs
|
||||
======================== =======================
|
||||
Action Shortcut
|
||||
======================== =======================
|
||||
New tab :sc:`new_tab`
|
||||
Close tab :sc:`close_tab`
|
||||
Next tab :sc:`next_tab` (also :kbd:`control+tab` on macOS)
|
||||
Previous tab :sc:`previous_tab` (also :kbd:`control+shift+tab` on macOS)
|
||||
New tab :sc:`new_tab` (also :kbd:`⌘+t` on macOS)
|
||||
Close tab :sc:`close_tab` (also :kbd:`⌘+w` on macOS)
|
||||
Next tab :sc:`next_tab` (also :kbd:`^+⇥` and :kbd:`⇧+⌘+]` on macOS)
|
||||
Previous tab :sc:`previous_tab` (also :kbd:`⇧+^+⇥` and :kbd:`⇧+⌘+[` on macOS)
|
||||
Next layout :sc:`next_layout`
|
||||
Move tab forward :sc:`move_tab_forward`
|
||||
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
|
||||
======================== =======================
|
||||
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)
|
||||
Close window :sc:`close_window`
|
||||
Close window :sc:`close_window` (also :kbd:`⇧+⌘+d` on macOS)
|
||||
Next window :sc:`next_window`
|
||||
Previous window :sc:`previous_window`
|
||||
Move window forward :sc:`move_window_forward`
|
||||
Move window backward :sc:`move_window_backward`
|
||||
Move window to top :sc:`move_window_to_top`
|
||||
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)
|
||||
======================== =======================
|
||||
|
||||
@@ -160,6 +166,13 @@ windows and move windows around (similar to window movement in vim)::
|
||||
map shift+down move_window up
|
||||
...
|
||||
|
||||
You can also define a shortcut to switch to the previously active window::
|
||||
|
||||
map ctrl+p nth_window -1
|
||||
|
||||
``nth_window`` will focus the nth window for positive numbers and the
|
||||
previously active windows for negative numbers.
|
||||
|
||||
|
||||
Other keyboard shortcuts
|
||||
----------------------------------
|
||||
@@ -170,11 +183,11 @@ Action Shortcut
|
||||
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 selection :sc:`paste_from_selection`
|
||||
Increase font size :sc:`increase_font_size`
|
||||
Decrease font size :sc:`decrease_font_size`
|
||||
Restore font size :sc:`reset_font_size`
|
||||
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`^⌘+f` on macOS)
|
||||
on
|
||||
Increase font size :sc:`increase_font_size` (also :kbd:`⌘++` on macOS)
|
||||
Decrease font size :sc:`decrease_font_size` (also :kbd:`⌘+-` on macOS)
|
||||
Restore font size :sc:`reset_font_size` (also :kbd:`⌘+0` on macOS)
|
||||
Toggle fullscreen :sc:`toggle_fullscreen` (also :kbd:`^+⌘+f` on macOS)
|
||||
Toggle maximized :sc:`toggle_maximized`
|
||||
Input unicode character :sc:`input_unicode_character`
|
||||
Click URL using the keyboard :sc:`open_url`
|
||||
Reset the terminal :sc:`reset_terminal`
|
||||
@@ -209,13 +222,26 @@ You can switch between layouts using the :sc:`next_layout` key combination. You
|
||||
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 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
|
||||
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
|
||||
not taller/shorter. Note that what you are resizing is actually not a window,
|
||||
but a row/column in the layout, all windows in that row/column will be resized.
|
||||
|
||||
You can also define shortcuts in :file:`kitty.conf` to make the active window
|
||||
wider, narrower, taller, or shorter by mapping to the ``resize_window``
|
||||
action, for example::
|
||||
|
||||
map ctrl+left resize_window narrower
|
||||
map ctrl+right resize_window wider
|
||||
map ctrl+up resize_window taller
|
||||
map ctrl+down resize_window shorter 3
|
||||
|
||||
The ``resize_window`` action has a second, optional argument to control
|
||||
the resizing increment (a positive integer that defaults to 1).
|
||||
|
||||
|
||||
Some layouts take options to control their behavior. For example, the ``fat``
|
||||
and ``tall`` layouts accept the ``bias`` option to control how the available
|
||||
space is split up. To specify the option, in :opt:`kitty.conf <enabled_layouts>` use::
|
||||
@@ -320,6 +346,12 @@ For example:
|
||||
# Set the current layout
|
||||
layout stack
|
||||
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
|
||||
focus
|
||||
launch emacs
|
||||
@@ -328,11 +360,14 @@ For example:
|
||||
Mouse features
|
||||
-------------------
|
||||
|
||||
* You can also 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 right click to extend a previous selection
|
||||
* 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 then drag to select more words.
|
||||
* 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
|
||||
columns
|
||||
columns.
|
||||
* Selecting text automatically copies it to the primary clipboard (on
|
||||
platforms with a primary clipboard).
|
||||
|
||||
|
||||
Font control
|
||||
@@ -370,6 +405,26 @@ arbitrary, command running in a new window, tab or overlay, for example::
|
||||
Would open the scrollback buffer in a new window when you press the :kbd:`F1`
|
||||
key. See :sc:`show_scrollback` for details.
|
||||
|
||||
If you wish to store very large amounts of scrollback to view using the piping or
|
||||
:sc:`show_scrollback` features, you can use the :opt:`scrollback_pager_history_size`
|
||||
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
|
||||
---------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
@@ -72,7 +72,10 @@ class Reporter: # {{{
|
||||
def get_latest_release_data():
|
||||
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'})
|
||||
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)
|
||||
html_url = data['html_url'].replace('/tag/', '/download/').rstrip('/')
|
||||
for asset in data.get('assets', ()):
|
||||
|
||||
@@ -43,6 +43,8 @@ Now in :file:`kitty.conf` add the lines::
|
||||
Start kitty and press :kbd:`ctrl+k` and you should see the kitten running.
|
||||
The best way to develop your own kittens is to modify one of the built in
|
||||
kittens. Look in the kittens sub-directory of the kitty source code for those.
|
||||
Or see below for a list of :ref:`third-party kittens <external_kittens>`,
|
||||
that other kitty users have created.
|
||||
|
||||
|
||||
Passing arguments to kittens
|
||||
@@ -68,7 +70,14 @@ function, telling kitty what kind of input your kitten would like. For example:
|
||||
|
||||
.. code-block:: py
|
||||
|
||||
def handle_result(...):
|
||||
# in main, STDIN is for the kitten process and will contain
|
||||
# the contents of the screen
|
||||
def main(args):
|
||||
return sys.stdin.read()
|
||||
|
||||
# in handle_result, STDIN is for the kitty process itself, rather
|
||||
# than the kitten process and should not be read from.
|
||||
def handle_result(args, stdin_data, target_window_id, boss):
|
||||
pass
|
||||
|
||||
handle_result.type_of_input = 'text'
|
||||
@@ -78,3 +87,60 @@ This will send the plain text of the active window to the kitten's
|
||||
instead. If you want line wrap markers as well, use ``screen-ansi``
|
||||
or just ``screen``. For the scrollback buffer as well, use
|
||||
``history``, ``ansi-history`` or ``screen-history``.
|
||||
|
||||
|
||||
Using kittens to script kitty, without any terminal UI
|
||||
-----------------------------------------------------------
|
||||
|
||||
If you would like your kitten to script kitty, without bothering to write a
|
||||
terminal program, you can tell the kittens system to run the
|
||||
``handle_result()`` function without first running the ``main()`` function.
|
||||
|
||||
For example, here is a kitten that "zooms/unzooms" the current terminal window
|
||||
by switching to the stack layout or back to the previous layout.
|
||||
|
||||
Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
||||
|
||||
.. code-block:: py
|
||||
|
||||
def main(args):
|
||||
pass
|
||||
|
||||
def handle_result(args, answer, target_window_id, boss):
|
||||
tab = boss.active_tab
|
||||
if tab is not None:
|
||||
if tab.current_layout.name == 'stack':
|
||||
tab.last_used_layout()
|
||||
else:
|
||||
tab.goto_layout('stack')
|
||||
|
||||
handle_result.no_ui = True
|
||||
|
||||
|
||||
Now in kitty.conf add::
|
||||
|
||||
map f11 kitten zoom_toggle.py
|
||||
|
||||
Pressing :kbd:`F11` will now act as a zoom toggle function. You can get even
|
||||
more fancy, switching the kitty OS window to fullscreen as well as changing the
|
||||
layout, by simply adding the line::
|
||||
|
||||
boss.toggle_fullscreen()
|
||||
|
||||
|
||||
to the ``handle_result()`` function, above.
|
||||
|
||||
.. _external_kittens:
|
||||
|
||||
Kittens created by kitty users
|
||||
---------------------------------------------
|
||||
|
||||
`vim-kitty-navigator <https://github.com/knubie/vim-kitty-navigator>`_
|
||||
Allows you to navigate seamlessly between vim and kitty splits using a consistent set of hotkeys.
|
||||
|
||||
`smart-scroll <https://github.com/yurikhan/kitty-smart-scroll>`_
|
||||
Makes the kitty scroll bindings work in full screen applications
|
||||
|
||||
`insert password <https://github.com/kovidgoyal/kitty/issues/1222>`_
|
||||
Insert a password from a CLI password manager, taking care to only do it at
|
||||
a password prompt.
|
||||
|
||||
@@ -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
|
||||
✖. 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.
|
||||
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
|
||||
keys/tab to select the character from the displayed matches. You can also type
|
||||
|
||||
92
docs/pipe.rst
Normal file
92
docs/pipe.rst
Normal file
@@ -0,0 +1,92 @@
|
||||
Working with the screen and history buffer contents
|
||||
======================================================
|
||||
|
||||
|
||||
You can pipe the contents of the current screen and history buffer as
|
||||
:file:`STDIN` to an arbitrary program using the ``pipe`` function. The program
|
||||
can be displayed in a kitty window or overlay.
|
||||
|
||||
For example, the following in :file:`kitty.conf` will open the scrollback
|
||||
buffer in less in an overlay window, when you press :kbd:`F1`::
|
||||
|
||||
map f1 pipe @ansi overlay less +G -R
|
||||
|
||||
The syntax of the ``pipe`` function is::
|
||||
|
||||
pipe <input placeholder> <destination window type> <command line to run>
|
||||
|
||||
|
||||
The piping environment
|
||||
--------------------------
|
||||
|
||||
The program to which the data is piped has a special environment variable
|
||||
declared, ``KITTY_PIPE_DATA`` whose contents are::
|
||||
|
||||
KITTY_PIPE_DATA={scrolled_by}:{cursor_x},{cursor_y}:{lines},{columns}
|
||||
|
||||
where ``scrolled_by`` is the number of lines kitty is currently scrolled by,
|
||||
``cursor_(x|y)`` is the position of the cursor on the screen with ``(1,1)``
|
||||
being the top left corner and ``{lines},{columns}`` being the number of rows
|
||||
and columns of the screen.
|
||||
|
||||
You can choose where to run the pipe program:
|
||||
|
||||
``overlay``
|
||||
An overlay window over the current kitty window
|
||||
|
||||
``window``
|
||||
A new kitty window
|
||||
|
||||
``os_window``
|
||||
A new top-level window
|
||||
|
||||
``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``
|
||||
Run it in the background
|
||||
|
||||
|
||||
Input placeholders
|
||||
--------------------
|
||||
|
||||
There are various different kinds of placeholders
|
||||
|
||||
``@text``
|
||||
Plain text, current screen + scrollback buffer
|
||||
|
||||
``@ansi``
|
||||
Text with formatting, current screen + scrollback buffer
|
||||
|
||||
``@screen``
|
||||
Plain text, only current screen
|
||||
|
||||
``@ansi_screen``
|
||||
Text with formatting, only current screen
|
||||
|
||||
``@alternate``
|
||||
Plain text, secondary screen. The secondary screen is the screen not currently displayed. For
|
||||
example if you run a fullscreen terminal application, the secondary screen will
|
||||
be the screen you return to when quitting the application.
|
||||
|
||||
``@ansi_alternate``
|
||||
Text with formatting, secondary screen.
|
||||
|
||||
``@alternate_scrollback``
|
||||
Plain text, secondary screen + scrollback, if any.
|
||||
|
||||
``@ansi_alternate_scrollback``
|
||||
Text with formatting, secondary screen + scrollback, if any.
|
||||
|
||||
``none``
|
||||
No input
|
||||
|
||||
|
||||
You can also add the suffix ``_wrap`` to the placeholder, in which case kitty
|
||||
will insert the carriage return at every line wrap location (where long lines
|
||||
are wrapped at screen edges). This is useful if you want to pipe to program
|
||||
that wants to duplicate the screen layout of the screen.
|
||||
@@ -6,7 +6,7 @@ These are typically in the form of new or re-purposed escape codes. While these
|
||||
extensions are currently |kitty| specific, it would be nice to get some of them
|
||||
adopted more broadly, to push the state of terminal emulators forward.
|
||||
|
||||
The goal of these extensions is to be as small an unobtrusive as possible,
|
||||
The goal of these extensions is to be as small and unobtrusive as possible,
|
||||
while filling in some gaps in the existing xterm protocol. In particular, one
|
||||
of the goals of this specification is explicitly not to "re-imagine" the tty.
|
||||
The tty should remain what it is -- a device for efficiently processing text
|
||||
@@ -51,6 +51,9 @@ To reset the underline color (also previously reserved and unused)::
|
||||
|
||||
<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
|
||||
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
|
||||
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::
|
||||
|
||||
<ESC>_KpGp<ESC>\ is <Ctrl>+<Alt>+x (press)
|
||||
@@ -141,6 +148,12 @@ For example::
|
||||
This encoding means each key event is represented by 8 or 9 printable ascii
|
||||
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
|
||||
in the terminfo database, in case querying for it via DECQRM is inconvenient.
|
||||
|
||||
.. _ext_styles:
|
||||
|
||||
@@ -158,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
|
||||
(bce)* capability. See
|
||||
`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 example, to set the background color to blue in a
|
||||
@@ -206,3 +219,7 @@ first, for example::
|
||||
<ESC>]52;c;!<ESC>\
|
||||
|
||||
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
|
||||
# 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)
|
||||
if payload_allowed:
|
||||
payload_after_value = "case ';': state = PAYLOAD; break;"
|
||||
payload = payload = ', PAYLOAD'
|
||||
payload = ', PAYLOAD'
|
||||
parr = 'static uint8_t payload[4096];'
|
||||
payload_case = f'''
|
||||
case PAYLOAD: {{
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
@@ -87,6 +88,11 @@ def parse_ucd():
|
||||
if category.startswith('M'):
|
||||
marks.add(codepoint)
|
||||
|
||||
# Some common synonyms
|
||||
word_search_map['bee'] |= word_search_map['honeybee']
|
||||
word_search_map['lambda'] |= word_search_map['lamda']
|
||||
word_search_map['lamda'] |= word_search_map['lambda']
|
||||
|
||||
|
||||
def split_two(line):
|
||||
spec, rest = line.split(';', 1)
|
||||
@@ -276,7 +282,8 @@ def gen_ucd():
|
||||
p('combining_type mark_for_codepoint(char_type c) {')
|
||||
rmap = codepoint_to_mark_map(p, mark_map)
|
||||
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(
|
||||
rmap[0xfe0e], rmap[0xfe0f]
|
||||
))
|
||||
@@ -360,16 +367,15 @@ def gen_names():
|
||||
root = TrieNode()
|
||||
all_trie_nodes.append(root)
|
||||
|
||||
def add_word(word_idx):
|
||||
word = word_map[word_idx]
|
||||
def add_word(word_idx, word):
|
||||
parent = root
|
||||
for letter in map(ord, word):
|
||||
idx = parent.add_letter(letter)
|
||||
parent = all_trie_nodes[idx]
|
||||
parent.match_offset = offsets_array[word_idx]
|
||||
|
||||
for i in range(len(word_map)):
|
||||
add_word(i)
|
||||
for i, word in enumerate(word_map):
|
||||
add_word(i, word)
|
||||
children_array = [0]
|
||||
for node in all_trie_nodes:
|
||||
if node.children:
|
||||
|
||||
35
glfw/backend_utils.c
vendored
35
glfw/backend_utils.c
vendored
@@ -21,16 +21,16 @@
|
||||
#endif
|
||||
|
||||
static inline double
|
||||
monotonic() {
|
||||
monotonic(void) {
|
||||
struct timespec ts = {0};
|
||||
#ifdef CLOCK_HIGHRES
|
||||
clock_gettime(CLOCK_HIGHRES, &ts);
|
||||
clock_gettime(CLOCK_HIGHRES, &ts);
|
||||
#elif CLOCK_MONOTONIC_RAW
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
|
||||
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
|
||||
}
|
||||
|
||||
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->callback = cb;
|
||||
w->callback_data = cb_data;
|
||||
w->free = NULL;
|
||||
w->id = ++watch_counter;
|
||||
update_fds(eld);
|
||||
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++) { \
|
||||
if (eld->which[i].id == item_id) { \
|
||||
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) { \
|
||||
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
|
||||
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])) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
||||
return 0;
|
||||
@@ -111,11 +116,13 @@ addTimer(EventLoopData *eld, const char *name, double interval, int enabled, tim
|
||||
t->interval = interval;
|
||||
t->name = name;
|
||||
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
||||
t->repeats = repeats;
|
||||
t->callback = cb;
|
||||
t->callback_data = cb_data;
|
||||
t->free = free;
|
||||
t->id = ++timer_counter;
|
||||
update_timers(eld);
|
||||
return t->id;
|
||||
return timer_counter;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -123,6 +130,14 @@ removeTimer(EventLoopData *eld, id_type timer_id) {
|
||||
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
|
||||
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
||||
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||
@@ -182,7 +197,7 @@ dispatchEvents(EventLoopData *eld) {
|
||||
unsigned
|
||||
dispatchTimers(EventLoopData *eld) {
|
||||
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;
|
||||
double now = monotonic();
|
||||
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].id = eld->timers[i].id;
|
||||
dispatches[num_dispatches].data = eld->timers[i].callback_data;
|
||||
dispatches[num_dispatches].repeats = eld->timers[i].repeats;
|
||||
num_dispatches++;
|
||||
}
|
||||
// we dispatch separately so that the callbacks can modify timers
|
||||
for (unsigned i = 0; i < num_dispatches; i++) {
|
||||
dispatches[i].func(dispatches[i].id, dispatches[i].data);
|
||||
if (!dispatches[i].repeats) {
|
||||
removeTimer(eld, dispatches[i].id);
|
||||
}
|
||||
}
|
||||
if (num_dispatches) update_timers(eld);
|
||||
return num_dispatches;
|
||||
|
||||
8
glfw/backend_utils.h
vendored
8
glfw/backend_utils.h
vendored
@@ -27,15 +27,18 @@
|
||||
#pragma once
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef unsigned long long id_type;
|
||||
typedef void(*watch_callback_func)(int, int, void*);
|
||||
typedef void(*timer_callback_func)(id_type, void*);
|
||||
typedef void (* GLFWuserdatafreefun)(id_type, void*);
|
||||
|
||||
typedef struct {
|
||||
int fd, events, enabled, ready;
|
||||
watch_callback_func callback;
|
||||
void *callback_data;
|
||||
GLFWuserdatafreefun free;
|
||||
id_type id;
|
||||
const char *name;
|
||||
} Watch;
|
||||
@@ -45,7 +48,9 @@ typedef struct {
|
||||
double interval, trigger_at;
|
||||
timer_callback_func callback;
|
||||
void *callback_data;
|
||||
GLFWuserdatafreefun free;
|
||||
const char *name;
|
||||
bool repeats;
|
||||
} 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);
|
||||
void removeWatch(EventLoopData *eld, id_type watch_id);
|
||||
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 removeAllTimers(EventLoopData *eld);
|
||||
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
|
||||
void changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval);
|
||||
double prepareForPoll(EventLoopData *eld, double timeout);
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "internal.h"
|
||||
#include <sys/param.h> // For MAXPATHLEN
|
||||
|
||||
|
||||
// Change to our application bundle's resources directory, if present
|
||||
//
|
||||
static void changeToResourcesDirectory(void)
|
||||
@@ -198,7 +197,7 @@ static void createKeyTables(void)
|
||||
|
||||
// Retrieve Unicode data for the current keyboard layout
|
||||
//
|
||||
static GLFWbool updateUnicodeDataNS(void)
|
||||
static bool updateUnicodeDataNS(void)
|
||||
{
|
||||
if (_glfw.ns.inputSource)
|
||||
{
|
||||
@@ -215,7 +214,7 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to retrieve keyboard layout input source");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.ns.unicodeData =
|
||||
@@ -225,15 +224,15 @@ static GLFWbool updateUnicodeDataNS(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"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
|
||||
//
|
||||
static GLFWbool initializeTIS(void)
|
||||
static bool initializeTIS(void)
|
||||
{
|
||||
// This works only because Cocoa has already loaded it properly
|
||||
_glfw.ns.tis.bundle =
|
||||
@@ -242,7 +241,7 @@ static GLFWbool initializeTIS(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to load HIToolbox.framework");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||
@@ -265,7 +264,7 @@ static GLFWbool initializeTIS(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Cocoa: Failed to load TIS API symbols");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
|
||||
@@ -274,33 +273,112 @@ static GLFWbool initializeTIS(void)
|
||||
return updateUnicodeDataNS();
|
||||
}
|
||||
|
||||
@interface GLFWLayoutListener : NSObject
|
||||
@interface GLFWHelper : NSObject
|
||||
@end
|
||||
|
||||
@implementation GLFWLayoutListener
|
||||
@implementation GLFWHelper
|
||||
|
||||
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||
{
|
||||
updateUnicodeDataNS();
|
||||
}
|
||||
|
||||
- (void)doNothing:(id)object
|
||||
{
|
||||
}
|
||||
|
||||
@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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline bool
|
||||
is_ctrl_tab(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
||||
if (
|
||||
(modifierFlags == NSEventModifierFlagControl &&
|
||||
[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)
|
||||
{
|
||||
_glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
@autoreleasepool {
|
||||
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
||||
|
||||
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
||||
toTarget:_glfw.ns.helper
|
||||
withObject:nil];
|
||||
|
||||
[GLFWApplication sharedApplication];
|
||||
|
||||
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* 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
|
||||
[[NSApp keyWindow].contentView keyDown:event];
|
||||
}
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
NSEvent* (^keyup_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||
{
|
||||
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
if (modifierFlags & NSEventModifierFlagCommand) {
|
||||
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
|
||||
// This works around an AppKit bug, where key up events while holding
|
||||
// down the command key don't get sent to the key window.
|
||||
[[NSApp keyWindow] sendEvent:event];
|
||||
}
|
||||
if (is_ctrl_tab(event, modifierFlags) || is_cmd_period(event, modifierFlags)) {
|
||||
// Cocoa swallows Ctrl+Tab to cycle between views
|
||||
[[NSApp keyWindow].contentView keyUp:event];
|
||||
}
|
||||
|
||||
return event;
|
||||
};
|
||||
|
||||
_glfw.ns.keyUpMonitor =
|
||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
|
||||
handler:keyup_block];
|
||||
_glfw.ns.keyDownMonitor =
|
||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
|
||||
handler:keydown_block];
|
||||
if (_glfw.hints.init.ns.chdir)
|
||||
changeToResourcesDirectory();
|
||||
|
||||
_glfw.ns.listener = [[GLFWLayoutListener alloc] init];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:_glfw.ns.listener
|
||||
addObserver:_glfw.ns.helper
|
||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
@@ -309,22 +387,32 @@ int _glfwPlatformInit(void)
|
||||
|
||||
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
|
||||
if (!_glfw.ns.eventSource)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
|
||||
|
||||
if (!initializeTIS())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
_glfw.ns.displayLinks.lock = [NSLock new];
|
||||
_glfwInitTimerNS();
|
||||
_glfwInitJoysticksNS();
|
||||
|
||||
_glfwPollMonitorsNS();
|
||||
return GLFW_TRUE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
if (_glfw.ns.displayLinks.lock) {
|
||||
_glfwClearDisplayLinks();
|
||||
[_glfw.ns.displayLinks.lock release];
|
||||
_glfw.ns.displayLinks.lock = nil;
|
||||
}
|
||||
|
||||
if (_glfw.ns.inputSource)
|
||||
{
|
||||
CFRelease(_glfw.ns.inputSource);
|
||||
@@ -345,32 +433,139 @@ void _glfwPlatformTerminate(void)
|
||||
_glfw.ns.delegate = nil;
|
||||
}
|
||||
|
||||
if (_glfw.ns.listener)
|
||||
if (_glfw.ns.helper)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener
|
||||
removeObserver:_glfw.ns.helper
|
||||
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
removeObserver:_glfw.ns.listener];
|
||||
[_glfw.ns.listener release];
|
||||
_glfw.ns.listener = nil;
|
||||
removeObserver:_glfw.ns.helper];
|
||||
[_glfw.ns.helper release];
|
||||
_glfw.ns.helper = nil;
|
||||
}
|
||||
if (_glfw.ns.keyUpMonitor)
|
||||
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
||||
if (_glfw.ns.keyDownMonitor)
|
||||
[NSEvent removeMonitor:_glfw.ns.keyDownMonitor];
|
||||
|
||||
free(_glfw.ns.clipboardString);
|
||||
|
||||
_glfwTerminateNSGL();
|
||||
_glfwTerminateJoysticksNS();
|
||||
|
||||
[_glfw.ns.autoreleasePool release];
|
||||
_glfw.ns.autoreleasePool = nil;
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetVersionString(void)
|
||||
{
|
||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL"
|
||||
return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
|
||||
#if defined(_GLFW_BUILD_DLL)
|
||||
" dynamic"
|
||||
#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:
|
||||
target = hats;
|
||||
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;
|
||||
|
||||
if (target)
|
||||
@@ -397,12 +406,12 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
if (raw > axis->maximum)
|
||||
axis->maximum = raw;
|
||||
|
||||
const long delta = axis->maximum - axis->minimum;
|
||||
if (delta == 0)
|
||||
const long size = axis->maximum - axis->minimum;
|
||||
if (size == 0)
|
||||
_glfwInputJoystickAxis(js, (int) i, 0.f);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -417,7 +426,8 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
_GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
|
||||
CFArrayGetValueAtIndex(js->ns.buttons, i);
|
||||
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++)
|
||||
@@ -454,9 +464,8 @@ void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
(strncmp(guid + 20, "000000000000", 12) == 0))
|
||||
{
|
||||
char original[33];
|
||||
strcpy(original, guid);
|
||||
strncpy(original, guid, sizeof(original) - 1);
|
||||
sprintf(guid, "03000000%.4s0000%.4s000000000000",
|
||||
original, original + 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <IOKit/graphics/IOGraphicsLib.h>
|
||||
#include <CoreVideo/CVBase.h>
|
||||
@@ -115,16 +116,16 @@ static char* getDisplayName(CGDirectDisplayID displayID)
|
||||
|
||||
// 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);
|
||||
|
||||
if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (flags & kDisplayModeInterlacedFlag)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (flags & kDisplayModeStretchedFlag)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||
@@ -132,12 +133,12 @@ static GLFWbool modeIsGood(CGDisplayModeRef mode)
|
||||
CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
|
||||
{
|
||||
CFRelease(format);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
CFRelease(format);
|
||||
#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert Core Graphics display mode to GLFW video mode
|
||||
@@ -148,7 +149,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||
GLFWvidmode result;
|
||||
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||
result.height = (int) CGDisplayModeGetHeight(mode);
|
||||
result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode);
|
||||
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
||||
|
||||
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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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
|
||||
//
|
||||
void _glfwPollMonitorsNS(void)
|
||||
@@ -228,6 +309,7 @@ void _glfwPollMonitorsNS(void)
|
||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||
_glfwClearDisplayLinks();
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; i++)
|
||||
_glfw.monitors[i]->ns.screen = nil;
|
||||
@@ -269,6 +351,7 @@ void _glfwPollMonitorsNS(void)
|
||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
||||
monitor->ns.displayID = displays[i];
|
||||
monitor->ns.unitNumber = unitNumber;
|
||||
createDisplayLink(monitor->ns.displayID);
|
||||
|
||||
free(name);
|
||||
|
||||
@@ -283,6 +366,7 @@ void _glfwPollMonitorsNS(void)
|
||||
|
||||
free(disconnected);
|
||||
free(displays);
|
||||
_glfwRestartDisplayLinks();
|
||||
}
|
||||
|
||||
// Change the current video mode
|
||||
@@ -372,35 +456,8 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale)
|
||||
{
|
||||
if (!monitor->ns.screen)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!refreshMonitorScreen(monitor))
|
||||
return;
|
||||
|
||||
const NSRect points = [monitor->ns.screen frame];
|
||||
const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
|
||||
@@ -411,6 +468,24 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
*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)
|
||||
{
|
||||
CFArrayRef modes;
|
||||
@@ -467,7 +542,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
||||
CVDisplayLinkRelease(link);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
||||
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
||||
@@ -489,6 +564,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
}
|
||||
|
||||
free(values);
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
@@ -523,4 +599,3 @@ GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
|
||||
return monitor->ns.displayID;
|
||||
}
|
||||
|
||||
|
||||
72
glfw/cocoa_platform.h
vendored
72
glfw/cocoa_platform.h
vendored
@@ -27,19 +27,46 @@
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if defined(__OBJC__)
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <CoreVideo/CoreVideo.h>
|
||||
#else
|
||||
typedef void* id;
|
||||
typedef void* CVDisplayLinkRef;
|
||||
#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 int (* GLFWcocoatextinputfilterfun)(int,int,int);
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||
|
||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||
{
|
||||
@@ -89,7 +116,8 @@ typedef struct _GLFWwindowNS
|
||||
id view;
|
||||
id layer;
|
||||
|
||||
GLFWbool maximized;
|
||||
bool maximized;
|
||||
bool retina;
|
||||
|
||||
// Cached window properties to filter out duplicate events
|
||||
int width, height;
|
||||
@@ -107,20 +135,32 @@ typedef struct _GLFWwindowNS
|
||||
GLFWcocoatogglefullscreenfun toggleFullscreenCallback;
|
||||
// Dead key state
|
||||
UInt32 deadKeyState;
|
||||
// Whether a render frame has been requested for this window
|
||||
bool renderFrameRequested;
|
||||
GLFWcocoarenderframefun renderFrameCallback;
|
||||
} _GLFWwindowNS;
|
||||
|
||||
typedef struct _GLFWDisplayLinkNS
|
||||
{
|
||||
CVDisplayLinkRef displayLink;
|
||||
CGDirectDisplayID displayID;
|
||||
bool displayLinkStarted;
|
||||
bool renderFrameRequested;
|
||||
} _GLFWDisplayLinkNS;
|
||||
|
||||
// Cocoa-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryNS
|
||||
{
|
||||
CGEventSourceRef eventSource;
|
||||
id delegate;
|
||||
id autoreleasePool;
|
||||
GLFWbool cursorHidden;
|
||||
bool cursorHidden;
|
||||
TISInputSourceRef inputSource;
|
||||
IOHIDManagerRef hidManager;
|
||||
id unicodeData;
|
||||
id listener;
|
||||
id helper;
|
||||
id keyUpMonitor;
|
||||
id keyDownMonitor;
|
||||
|
||||
char keyName[64];
|
||||
char text[256];
|
||||
@@ -141,6 +181,12 @@ typedef struct _GLFWlibraryNS
|
||||
CFStringRef kPropertyUnicodeKeyLayoutData;
|
||||
} tis;
|
||||
|
||||
struct {
|
||||
_GLFWDisplayLinkNS entries[256];
|
||||
size_t count;
|
||||
id lock;
|
||||
} displayLinks;
|
||||
|
||||
} _GLFWlibraryNS;
|
||||
|
||||
// Cocoa-specific per-monitor data
|
||||
@@ -176,3 +222,9 @@ void _glfwInitTimerNS(void);
|
||||
void _glfwPollMonitorsNS(void);
|
||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||
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
|
||||
// values
|
||||
//
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
if (ctxconfig->share)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
ctxconfig->share->context.client == GLFW_NO_API)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context creation API 0x%08X",
|
||||
ctxconfig->source);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API &&
|
||||
@@ -73,7 +73,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid client API 0x%08X",
|
||||
ctxconfig->client);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
@@ -92,7 +92,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"Invalid OpenGL version %i.%i",
|
||||
ctxconfig->major, ctxconfig->minor);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->profile)
|
||||
@@ -103,7 +103,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid OpenGL profile 0x%08X",
|
||||
ctxconfig->profile);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->major <= 2 ||
|
||||
@@ -114,7 +114,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"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
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"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)
|
||||
@@ -140,7 +140,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_VALUE,
|
||||
"Invalid OpenGL ES version %i.%i",
|
||||
ctxconfig->major, ctxconfig->minor);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context robustness mode 0x%08X",
|
||||
ctxconfig->robustness);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,11 +164,11 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
|
||||
_glfwInputError(GLFW_INVALID_ENUM,
|
||||
"Invalid context release behavior 0x%08X",
|
||||
ctxconfig->release);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig)
|
||||
{
|
||||
int i;
|
||||
@@ -358,7 +358,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
window->context.source = ctxconfig->source;
|
||||
window->context.client = GLFW_OPENGL_API;
|
||||
|
||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);;
|
||||
previous = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
glfwMakeContextCurrent((GLFWwindow*) window);
|
||||
|
||||
window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
|
||||
@@ -369,7 +369,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
version = (const char*) window->context.GetString(GL_VERSION);
|
||||
@@ -387,7 +387,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; prefixes[i]; i++)
|
||||
@@ -419,7 +419,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window->context.major < ctxconfig->major ||
|
||||
@@ -449,7 +449,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window->context.major >= 3)
|
||||
@@ -465,7 +465,7 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Entry point retrieval is broken");
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,21 +478,21 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||
|
||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||
window->context.forward = GLFW_TRUE;
|
||||
window->context.forward = true;
|
||||
|
||||
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
|
||||
window->context.debug = GLFW_TRUE;
|
||||
window->context.debug = true;
|
||||
else if (glfwExtensionSupported("GL_ARB_debug_output") &&
|
||||
ctxconfig->debug)
|
||||
{
|
||||
// HACK: This is a workaround for older drivers (pre KHR_debug)
|
||||
// not setting the debug bit in the context flags for
|
||||
// debug contexts
|
||||
window->context.debug = GLFW_TRUE;
|
||||
window->context.debug = true;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -572,12 +572,12 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent((GLFWwindow*) previous);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -588,7 +588,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
||||
|
||||
where = strstr(start, string);
|
||||
if (!where)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
terminator = where + strlen(string);
|
||||
if (where == start || *(where - 1) == ' ')
|
||||
@@ -600,7 +600,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions
|
||||
start = terminator;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -677,20 +677,20 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
_GLFWwindow* window;
|
||||
assert(extension != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
|
||||
window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
if (!window)
|
||||
{
|
||||
_glfwInputError(GLFW_NO_CURRENT_CONTEXT,
|
||||
"Cannot query extension without a current OpenGL or OpenGL ES context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*extension == '\0')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window->context.major >= 3)
|
||||
@@ -710,11 +710,11 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Extension string retrieval is broken");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(en, extension) == 0)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -727,11 +727,11 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Extension string retrieval is broken");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if extension is in the platform-specific string
|
||||
@@ -755,4 +755,3 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* 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 DBusConnection *session_bus = NULL;
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) {
|
||||
dbus->eld = eld;
|
||||
dbus_data = dbus;
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -108,7 +109,7 @@ add_dbus_timeout(DBusTimeout *timeout, void *data) {
|
||||
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
|
||||
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
|
||||
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;
|
||||
id_type *idp = malloc(sizeof(id_type));
|
||||
if (!idp) {
|
||||
@@ -135,7 +136,7 @@ toggle_dbus_timeout(DBusTimeout *timeout, void *data) {
|
||||
|
||||
|
||||
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;
|
||||
dbus_error_init(&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);
|
||||
}
|
||||
|
||||
void
|
||||
glfw_dbus_session_bus_dispatch() {
|
||||
if (session_bus) glfw_dbus_dispatch(session_bus);
|
||||
}
|
||||
|
||||
void
|
||||
glfw_dbus_terminate(_GLFWDBUSData *dbus) {
|
||||
if (dbus_data) {
|
||||
dbus_data->eld = NULL;
|
||||
dbus_data = NULL;
|
||||
}
|
||||
if (session_bus) {
|
||||
dbus_connection_unref(session_bus);
|
||||
session_bus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -185,14 +195,14 @@ glfw_dbus_close_connection(DBusConnection *conn) {
|
||||
dbus_connection_unref(conn);
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...) {
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
va_list ap;
|
||||
va_start(ap, failmsg);
|
||||
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);
|
||||
if (!ret) report_error(&err, failmsg);
|
||||
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) {
|
||||
if (!conn) return GLFW_FALSE;
|
||||
if (!conn) return false;
|
||||
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
||||
if (!msg) return GLFW_FALSE;
|
||||
GLFWbool retval = GLFW_FALSE;
|
||||
MethodResponse *res = malloc(sizeof(MethodResponse));
|
||||
if (!res) { dbus_message_unref(msg); return GLFW_FALSE; }
|
||||
res->callback = callback;
|
||||
res->user_data = user_data;
|
||||
if (!msg) return false;
|
||||
bool retval = false;
|
||||
|
||||
int firstarg = va_arg(ap, int);
|
||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
|
||||
if (callback) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
retval = call_method_with_msg(conn, msg, timeout, callback, user_data);
|
||||
} else {
|
||||
_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;
|
||||
}
|
||||
|
||||
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, ...) {
|
||||
GLFWbool retval;
|
||||
bool retval;
|
||||
va_list ap;
|
||||
va_start(ap, user_data);
|
||||
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;
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
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_start(ap, method);
|
||||
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);
|
||||
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;
|
||||
|
||||
|
||||
GLFWbool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld);
|
||||
bool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld);
|
||||
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);
|
||||
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, ...);
|
||||
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, ...);
|
||||
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, ...);
|
||||
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
|
||||
//
|
||||
static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* desired,
|
||||
EGLConfig* result)
|
||||
{
|
||||
@@ -98,7 +98,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
if (!nativeCount)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
|
||||
@@ -170,7 +170,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
||||
u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
|
||||
|
||||
u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
u->doublebuffer = true;
|
||||
|
||||
u->handle = (uintptr_t) n;
|
||||
usableCount++;
|
||||
@@ -241,10 +241,10 @@ static int extensionSupportedEGL(const char* extension)
|
||||
if (extensions)
|
||||
{
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressEGL(const char* procname)
|
||||
@@ -297,7 +297,7 @@ static void destroyContextEGL(_GLFWwindow* window)
|
||||
|
||||
// Initialize EGL
|
||||
//
|
||||
GLFWbool _glfwInitEGL(void)
|
||||
bool _glfwInitEGL(void)
|
||||
{
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
@@ -318,7 +318,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
};
|
||||
|
||||
if (_glfw.egl.handle)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
@@ -330,7 +330,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
if (!_glfw.egl.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||
@@ -389,7 +389,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
"EGL: Failed to load required entry points");
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
|
||||
@@ -400,7 +400,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
getEGLErrorString(eglGetError()));
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
|
||||
@@ -410,7 +410,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
getEGLErrorString(eglGetError()));
|
||||
|
||||
_glfwTerminateEGL();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.egl.KHR_create_context =
|
||||
@@ -424,7 +424,7 @@ GLFWbool _glfwInitEGL(void)
|
||||
_glfw.egl.KHR_context_flush_control =
|
||||
extensionSupportedEGL("EGL_KHR_context_flush_control");
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Terminate EGL
|
||||
@@ -453,7 +453,7 @@ void _glfwTerminateEGL(void)
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
//
|
||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@@ -465,7 +465,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (!_glfw.egl.display)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->share)
|
||||
@@ -475,7 +475,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
@@ -485,7 +485,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to bind OpenGL ES: %s",
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -495,7 +495,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"EGL: Failed to bind OpenGL: %s",
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
if (ctxconfig->noerror)
|
||||
{
|
||||
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)
|
||||
@@ -581,7 +581,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"EGL: Failed to create context: %s",
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up attributes for surface creation
|
||||
@@ -607,11 +607,20 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to create window surface: %s",
|
||||
getEGLErrorString(eglGetError()));
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
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
|
||||
if (!_glfw.egl.KHR_get_all_proc_addresses)
|
||||
{
|
||||
@@ -686,7 +695,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"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.destroy = destroyContextEGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
@@ -705,7 +714,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
// Returns the Visual and depth of the chosen EGLConfig
|
||||
//
|
||||
#if defined(_GLFW_X11)
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth)
|
||||
@@ -720,7 +729,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"EGL: Failed to find a suitable EGLConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
eglGetConfigAttrib(_glfw.egl.display, native,
|
||||
@@ -734,14 +743,14 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"EGL: Failed to retrieve Visual for EGLConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
*visual = result->visual;
|
||||
*depth = result->depth;
|
||||
|
||||
XFree(result);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
#endif // _GLFW_X11
|
||||
|
||||
@@ -783,4 +792,3 @@ GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle)
|
||||
|
||||
return window->context.egl.surface;
|
||||
}
|
||||
|
||||
|
||||
41
glfw/egl_context.h
vendored
41
glfw/egl_context.h
vendored
@@ -43,34 +43,30 @@ typedef Window EGLNativeWindowType;
|
||||
#define EGLAPIENTRY
|
||||
typedef struct wl_display* EGLNativeDisplayType;
|
||||
typedef struct wl_egl_window* EGLNativeWindowType;
|
||||
#elif defined(_GLFW_MIR)
|
||||
#define EGLAPIENTRY
|
||||
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
|
||||
typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#else
|
||||
#error "No supported EGL platform selected"
|
||||
#endif
|
||||
|
||||
#define EGL_SUCCESS 0x3000
|
||||
#define EGL_NOT_INITIALIZED 0x3001
|
||||
#define EGL_SUCCESS 0x3000
|
||||
#define EGL_NOT_INITIALIZED 0x3001
|
||||
#define EGL_BAD_ACCESS 0x3002
|
||||
#define EGL_BAD_ALLOC 0x3003
|
||||
#define EGL_BAD_ATTRIBUTE 0x3004
|
||||
#define EGL_BAD_CONFIG 0x3005
|
||||
#define EGL_BAD_CONTEXT 0x3006
|
||||
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||
#define EGL_BAD_DISPLAY 0x3008
|
||||
#define EGL_BAD_CONTEXT 0x3006
|
||||
#define EGL_BAD_CURRENT_SURFACE 0x3007
|
||||
#define EGL_BAD_DISPLAY 0x3008
|
||||
#define EGL_BAD_MATCH 0x3009
|
||||
#define EGL_BAD_NATIVE_PIXMAP 0x300a
|
||||
#define EGL_BAD_NATIVE_WINDOW 0x300b
|
||||
#define EGL_BAD_PARAMETER 0x300c
|
||||
#define EGL_BAD_SURFACE 0x300d
|
||||
#define EGL_BAD_SURFACE 0x300d
|
||||
#define EGL_CONTEXT_LOST 0x300e
|
||||
#define EGL_COLOR_BUFFER_TYPE 0x303f
|
||||
#define EGL_RGB_BUFFER 0x308e
|
||||
#define EGL_SURFACE_TYPE 0x3033
|
||||
#define EGL_WINDOW_BIT 0x0004
|
||||
#define EGL_RENDERABLE_TYPE 0x3040
|
||||
#define EGL_RENDERABLE_TYPE 0x3040
|
||||
#define EGL_OPENGL_ES_BIT 0x0001
|
||||
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||
#define EGL_OPENGL_BIT 0x0008
|
||||
@@ -80,7 +76,7 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_RED_SIZE 0x3024
|
||||
#define EGL_DEPTH_SIZE 0x3025
|
||||
#define EGL_STENCIL_SIZE 0x3026
|
||||
#define EGL_SAMPLES 0x3031
|
||||
#define EGL_SAMPLES 0x3031
|
||||
#define EGL_OPENGL_ES_API 0x30a0
|
||||
#define EGL_OPENGL_API 0x30a2
|
||||
#define EGL_NONE 0x3038
|
||||
@@ -91,6 +87,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
|
||||
#define EGL_NO_DISPLAY ((EGLDisplay) 0)
|
||||
#define EGL_NO_CONTEXT ((EGLContext) 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_CORE_PROFILE_BIT_KHR 0x00000001
|
||||
@@ -175,13 +173,13 @@ typedef struct _GLFWlibraryEGL
|
||||
{
|
||||
EGLDisplay display;
|
||||
EGLint major, minor;
|
||||
GLFWbool prefix;
|
||||
bool prefix;
|
||||
|
||||
GLFWbool KHR_create_context;
|
||||
GLFWbool KHR_create_context_no_error;
|
||||
GLFWbool KHR_gl_colorspace;
|
||||
GLFWbool KHR_get_all_proc_addresses;
|
||||
GLFWbool KHR_context_flush_control;
|
||||
bool KHR_create_context;
|
||||
bool KHR_create_context_no_error;
|
||||
bool KHR_gl_colorspace;
|
||||
bool KHR_get_all_proc_addresses;
|
||||
bool KHR_context_flush_control;
|
||||
|
||||
void* handle;
|
||||
|
||||
@@ -205,15 +203,14 @@ typedef struct _GLFWlibraryEGL
|
||||
} _GLFWlibraryEGL;
|
||||
|
||||
|
||||
GLFWbool _glfwInitEGL(void);
|
||||
bool _glfwInitEGL(void);
|
||||
void _glfwTerminateEGL(void);
|
||||
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextEGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
#if defined(_GLFW_X11)
|
||||
GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth);
|
||||
#endif /*_GLFW_X11*/
|
||||
|
||||
|
||||
122
glfw/glfw.py
122
glfw/glfw.py
@@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
_plat = sys.platform.lower()
|
||||
@@ -22,7 +21,7 @@ def wayland_protocol_file_name(base, ext='c'):
|
||||
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
||||
|
||||
|
||||
def init_env(env, pkg_config, at_least_version, module='x11'):
|
||||
def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
|
||||
ans = env.copy()
|
||||
ans.cflags = [
|
||||
x for x in ans.cflags
|
||||
@@ -32,10 +31,11 @@ def init_env(env, pkg_config, at_least_version, module='x11'):
|
||||
ans.cflags.append('-pthread')
|
||||
ans.ldpaths.append('-pthread')
|
||||
ans.cflags.append('-fpic')
|
||||
ans.cflags.append('-D_GLFW_' + module.upper())
|
||||
ans.cflags.append('-D_GLFW_BUILD_DLL')
|
||||
ans.cppflags.append('-D_GLFW_' + module.upper())
|
||||
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
||||
|
||||
if is_macos:
|
||||
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
|
||||
ans.ldpaths.extend(
|
||||
"-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo".
|
||||
split()
|
||||
@@ -76,6 +76,14 @@ def init_env(env, pkg_config, at_least_version, module='x11'):
|
||||
for dep in 'wayland-egl wayland-client wayland-cursor xkbcommon dbus-1'.split():
|
||||
ans.cflags.extend(pkg_config(dep, '--cflags-only-I'))
|
||||
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
||||
has_memfd_create = test_compile(env.cc, '-Werror', src='''#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
int main(void) {
|
||||
return syscall(__NR_memfd_create, "test", 0);
|
||||
}''')
|
||||
if has_memfd_create:
|
||||
ans.cppflags.append('-DHAS_MEMFD_CREATE')
|
||||
|
||||
return ans
|
||||
|
||||
@@ -94,40 +102,6 @@ def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir):
|
||||
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:
|
||||
|
||||
def __init__(self, decl):
|
||||
@@ -160,6 +134,8 @@ class Function:
|
||||
if a == 'void':
|
||||
continue
|
||||
self.args.append(Arg(a))
|
||||
if not self.args:
|
||||
self.args = [Arg('void v')]
|
||||
|
||||
def declaration(self):
|
||||
return 'typedef {restype} (*{name}_func)({args});\n{name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
||||
@@ -179,7 +155,7 @@ class Function:
|
||||
return ans
|
||||
|
||||
|
||||
def generate_wrappers(glfw_header, glfw_native_header):
|
||||
def generate_wrappers(glfw_header):
|
||||
src = open(glfw_header).read()
|
||||
functions = []
|
||||
first = None
|
||||
@@ -198,11 +174,16 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
||||
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
||||
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
||||
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
|
||||
void* glfwGetX11Display(void)
|
||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||
void glfwSetX11SelectionString(const char* string)
|
||||
const char* glfwGetX11SelectionString(void)
|
||||
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
||||
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
||||
int glfwGetXKBScancode(const char* key_name, int case_sensitive)
|
||||
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():
|
||||
if line:
|
||||
functions.append(Function(line.strip(), check_fail=False))
|
||||
@@ -218,10 +199,13 @@ def generate_wrappers(glfw_header, glfw_native_header):
|
||||
|
||||
{}
|
||||
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int);
|
||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||
|
||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||
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);
|
||||
@@ -251,7 +235,7 @@ load_glfw(const char* path) {
|
||||
}
|
||||
|
||||
void
|
||||
unload_glfw() {
|
||||
unload_glfw(void) {
|
||||
if (handle) { dlclose(handle); handle = NULL; }
|
||||
}
|
||||
'''.replace('LOAD', '\n\n '.join(f.load() for f in functions))
|
||||
@@ -259,53 +243,9 @@ unload_glfw() {
|
||||
f.write(code)
|
||||
|
||||
|
||||
def from_glfw(glfw_dir):
|
||||
os.chdir(glfw_dir)
|
||||
sinfo = collect_source_information()
|
||||
files_to_copy = set()
|
||||
for x in sinfo.values():
|
||||
if isinstance(x, dict):
|
||||
headers, sources = x['headers'], x['sources']
|
||||
for name in headers + sources:
|
||||
files_to_copy.add(os.path.abspath(os.path.join('src', name)))
|
||||
glfw_header = os.path.abspath('include/GLFW/glfw3.h')
|
||||
glfw_native_header = os.path.abspath('include/GLFW/glfw3native.h')
|
||||
os.chdir(base)
|
||||
for x in os.listdir('.'):
|
||||
if x.rpartition('.') in ('c', 'h'):
|
||||
os.unlink(x)
|
||||
for src in files_to_copy:
|
||||
shutil.copy2(src, '.')
|
||||
shutil.copy2(glfw_header, '.')
|
||||
json.dump(
|
||||
sinfo,
|
||||
open('source-info.json', 'w'),
|
||||
indent=2,
|
||||
ensure_ascii=False,
|
||||
sort_keys=True
|
||||
)
|
||||
generate_wrappers(glfw_header, glfw_native_header)
|
||||
|
||||
|
||||
def to_glfw(glfw_dir):
|
||||
src = base
|
||||
for x in os.listdir(src):
|
||||
if x in ('glfw.py', 'glfw3.h', '__pycache__', 'source-info.json') or x.startswith('wayland-'):
|
||||
continue
|
||||
xp = os.path.join(src, x)
|
||||
shutil.copyfile(xp, os.path.join(glfw_dir, 'src', x))
|
||||
shutil.copyfile(os.path.join(src, 'glfw3.h'), os.path.join(glfw_dir, 'include/GLFW/glfw3.h'))
|
||||
|
||||
|
||||
def main():
|
||||
glfw_dir = os.path.abspath(os.path.join(base, '../../glfw'))
|
||||
q = sys.argv[1].lower().replace('_', '-')
|
||||
if q == 'from-glfw':
|
||||
from_glfw(glfw_dir)
|
||||
elif q == 'to-glfw':
|
||||
to_glfw(glfw_dir)
|
||||
else:
|
||||
raise SystemExit('First argument must be one of to-glfw or from-glfw')
|
||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||
generate_wrappers('glfw3.h')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
509
glfw/glfw3.h
vendored
509
glfw/glfw3.h
vendored
@@ -133,6 +133,8 @@ extern "C" {
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Include the chosen OpenGL or OpenGL ES headers.
|
||||
*/
|
||||
#if defined(GLFW_INCLUDE_ES1)
|
||||
@@ -269,24 +271,6 @@ extern "C" {
|
||||
#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
|
||||
* @{ */
|
||||
/*! @brief The key or mouse button was released.
|
||||
@@ -407,6 +391,8 @@ extern "C" {
|
||||
#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
|
||||
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */
|
||||
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */
|
||||
#define GLFW_KEY_PLUS 163
|
||||
#define GLFW_KEY_UNDERSCORE 164
|
||||
|
||||
/* Function keys */
|
||||
#define GLFW_KEY_ESCAPE 256
|
||||
@@ -825,7 +811,11 @@ extern "C" {
|
||||
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
|
||||
*/
|
||||
#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.
|
||||
*
|
||||
* Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
|
||||
@@ -1025,36 +1015,19 @@ extern "C" {
|
||||
* @ingroup input
|
||||
* @{ */
|
||||
|
||||
/*! @brief The regular arrow cursor shape.
|
||||
*
|
||||
* The regular arrow cursor.
|
||||
*/
|
||||
#define GLFW_ARROW_CURSOR 0x00036001
|
||||
/*! @brief The text input I-beam cursor shape.
|
||||
*
|
||||
* The text input I-beam cursor shape.
|
||||
*/
|
||||
#define GLFW_IBEAM_CURSOR 0x00036002
|
||||
/*! @brief The crosshair shape.
|
||||
*
|
||||
* The crosshair shape.
|
||||
*/
|
||||
#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
|
||||
typedef enum {
|
||||
GLFW_ARROW_CURSOR,
|
||||
GLFW_IBEAM_CURSOR,
|
||||
GLFW_CROSSHAIR_CURSOR,
|
||||
GLFW_HAND_CURSOR,
|
||||
GLFW_HRESIZE_CURSOR,
|
||||
GLFW_VRESIZE_CURSOR,
|
||||
GLFW_NW_RESIZE_CURSOR,
|
||||
GLFW_NE_RESIZE_CURSOR,
|
||||
GLFW_SW_RESIZE_CURSOR,
|
||||
GLFW_SE_RESIZE_CURSOR,
|
||||
GLFW_INVALID_CURSOR
|
||||
} GLFWCursorShape;
|
||||
/*! @} */
|
||||
|
||||
#define GLFW_CONNECTED 0x00040001
|
||||
@@ -1163,9 +1136,9 @@ typedef void (* GLFWerrorfun)(int,const char*);
|
||||
*
|
||||
* @param[in] window The window that was moved.
|
||||
* @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
|
||||
* 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 glfwSetWindowPosCallback
|
||||
@@ -1231,8 +1204,8 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
|
||||
* This is the function signature for window focus callback functions.
|
||||
*
|
||||
* @param[in] window The window that gained or lost input focus.
|
||||
* @param[in] focused `GLFW_TRUE` if the window was given input focus, or
|
||||
* `GLFW_FALSE` if it lost it.
|
||||
* @param[in] focused `true` if the window was given input focus, or
|
||||
* `false` if it lost it.
|
||||
*
|
||||
* @sa @ref window_focus
|
||||
* @sa @ref glfwSetWindowFocusCallback
|
||||
@@ -1243,14 +1216,32 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This is the function signature for window iconify/restore callback
|
||||
* functions.
|
||||
*
|
||||
* @param[in] window The window that was iconified or restored.
|
||||
* @param[in] iconified `GLFW_TRUE` if the window was iconified, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
* @param[in] iconified `true` if the window was iconified, or
|
||||
* `false` if it was restored.
|
||||
*
|
||||
* @sa @ref window_iconify
|
||||
* @sa @ref glfwSetWindowIconifyCallback
|
||||
@@ -1267,8 +1258,8 @@ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
|
||||
* functions.
|
||||
*
|
||||
* @param[in] window The window that was maximized or restored.
|
||||
* @param[in] iconified `GLFW_TRUE` if the window was maximized, or
|
||||
* `GLFW_FALSE` if it was restored.
|
||||
* @param[in] iconified `true` if the window was maximized, or
|
||||
* `false` if it was restored.
|
||||
*
|
||||
* @sa @ref window_maximize
|
||||
* @sa glfwSetWindowMaximizeCallback
|
||||
@@ -1342,9 +1333,9 @@ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);
|
||||
*
|
||||
* @param[in] window The window that received the event.
|
||||
* @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
|
||||
* client area.
|
||||
* content area.
|
||||
*
|
||||
* @sa @ref cursor_pos
|
||||
* @sa @ref glfwSetCursorPosCallback
|
||||
@@ -1360,8 +1351,8 @@ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
|
||||
* This is the function signature for cursor enter/leave callback functions.
|
||||
*
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] entered `GLFW_TRUE` if the cursor entered the window's client
|
||||
* area, or `GLFW_FALSE` if it left it.
|
||||
* @param[in] entered `true` if the cursor entered the window's client
|
||||
* area, or `false` if it left it.
|
||||
*
|
||||
* @sa @ref cursor_enter
|
||||
* @sa @ref glfwSetCursorEnterCallback
|
||||
@@ -1379,7 +1370,13 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
||||
* @param[in] window The window that received the event.
|
||||
* @param[in] xoffset The scroll offset along the x-axis.
|
||||
* @param[in] yoffset The scroll offset along the y-axis.
|
||||
* @param[in] flags A bit-mask providing extra data about the event. flags & 1 will be true if and only if the offset values are "high-precision". Typically pixel values. Otherwise the offset values are number of lines.
|
||||
* @param[in] flags A bit-mask providing extra data about the event.
|
||||
* flags & 1 will be true if and only if the offset values are "high-precision".
|
||||
* Typically pixel values. Otherwise the offset values are number of lines.
|
||||
* (flags >> 1) & 7 will have value 1 for the start of momentum scrolling,
|
||||
* value 2 for stationary momentum scrolling, value 3 for momentum scrolling
|
||||
* in progress, value 4 for momentum scrolling ended, value 5 for momentum
|
||||
* scrolling cancelled and value 6 if scrolling may begin soon.
|
||||
*
|
||||
* @sa @ref scrolling
|
||||
* @sa @ref glfwSetScrollCallback
|
||||
@@ -1443,6 +1440,8 @@ typedef void (* GLFWkeyboardfun)(GLFWwindow*, int, int, int, int, const char*, i
|
||||
*/
|
||||
typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);
|
||||
|
||||
typedef void (* GLFWliveresizefun)(GLFWwindow*, bool);
|
||||
|
||||
/*! @brief The function signature for monitor configuration callbacks.
|
||||
*
|
||||
* This is the function signature for monitor configuration callback functions.
|
||||
@@ -1478,6 +1477,9 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
|
||||
*/
|
||||
typedef void (* GLFWjoystickfun)(int,int);
|
||||
|
||||
typedef void (* GLFWuserdatafun)(unsigned long long, void*);
|
||||
typedef void (* GLFWtickcallback)(void*);
|
||||
|
||||
/*! @brief Video mode type.
|
||||
*
|
||||
* This describes a single video mode.
|
||||
@@ -1602,9 +1604,9 @@ typedef struct GLFWgamepadstate
|
||||
* succeeds, you should call @ref glfwTerminate before the application exits.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_PLATFORM_ERROR.
|
||||
@@ -1624,6 +1626,12 @@ typedef struct GLFWgamepadstate
|
||||
* @ingroup init
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -1895,6 +1903,35 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This function returns the size, in millimetres, of the display area of the
|
||||
@@ -2121,9 +2158,9 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
|
||||
|
||||
/*! @brief Generates a gamma ramp and sets it for the specified monitor.
|
||||
*
|
||||
* This function generates a 256-element gamma ramp from the specified exponent
|
||||
* and then calls @ref glfwSetGammaRamp with it. The value must be a finite
|
||||
* number greater than zero.
|
||||
* This function generates an appropriately sized gamma ramp from the
|
||||
* specified exponent and then calls @ref glfwSetGammaRamp with it. The value
|
||||
* must be a finite number greater than zero.
|
||||
*
|
||||
* The software controlled gamma ramp is applied _in addition_ to the hardware
|
||||
* gamma correction, which today is usually an approximation of sRGB gamma.
|
||||
@@ -2202,8 +2239,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark Gamma ramp sizes other than 256 are not supported by all platforms
|
||||
* or graphics hardware.
|
||||
* @remark The size of the specified gamma ramp should match the size of the
|
||||
* current ramp for that monitor.
|
||||
*
|
||||
* @remark @win32 The gamma ramp size must be 256.
|
||||
*
|
||||
@@ -2417,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
|
||||
* at full resolution on Retina displays unless the
|
||||
* [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
|
||||
* [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
|
||||
@@ -2443,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
|
||||
* this.
|
||||
*
|
||||
* @remark @wayland The window frame is currently very simple, only allowing
|
||||
* window resize or move. A compositor can still emit close, maximize or
|
||||
* fullscreen events, using for example a keybind mechanism. Additionally,
|
||||
* the wp_viewporter protocol is required for this feature, otherwise the
|
||||
* window will not be decorated.
|
||||
* @remark @wayland Compositors should implement the xdg-decoration protocol
|
||||
* for GLFW to decorate the window properly. If this protocol isn't
|
||||
* supported, or if the compositor prefers client-side decorations, a very
|
||||
* simple fallback frame will be drawn using the wp_viewporter protocol. A
|
||||
* 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,
|
||||
* no matter what the requested size or refresh rate.
|
||||
@@ -2465,6 +2504,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
|
||||
* @ingroup window
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -2609,19 +2649,19 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);
|
||||
*/
|
||||
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
|
||||
* 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
|
||||
* non-`NULL` position arguments will be set to zero.
|
||||
*
|
||||
* @param[in] window The window to query.
|
||||
* @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
|
||||
* the client area, or `NULL`.
|
||||
* the content area, or `NULL`.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -2641,10 +2681,10 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
*
|
||||
* __Do not use this function__ to move an already visible window unless you
|
||||
@@ -2654,8 +2694,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
|
||||
* cannot and should not override these limits.
|
||||
*
|
||||
* @param[in] window The window to query.
|
||||
* @param[in] xpos The x-coordinate of the upper-left corner of the client area.
|
||||
* @param[in] ypos The y-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 content area.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -2676,9 +2716,9 @@ GLFWAPI void glfwGetWindowPos(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
|
||||
* framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.
|
||||
*
|
||||
@@ -2687,9 +2727,9 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
|
||||
*
|
||||
* @param[in] window The window whose size to retrieve.
|
||||
* @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
|
||||
* client area, or `NULL`.
|
||||
* content area, or `NULL`.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -2708,7 +2748,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
|
||||
|
||||
/*! @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
|
||||
* once it is made windowed. If the window is not resizable, this function
|
||||
* does nothing.
|
||||
@@ -2723,11 +2763,11 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
|
||||
* @param[in] minwidth The minimum width, in screen coordinates, of the client
|
||||
* area, or `GLFW_DONT_CARE`.
|
||||
* @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
|
||||
* area, or `GLFW_DONT_CARE`.
|
||||
* @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
|
||||
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
@@ -2751,7 +2791,7 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
|
||||
|
||||
/*! @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
|
||||
* effect once it is made windowed. If the window is not resizable, this
|
||||
* function does nothing.
|
||||
@@ -2792,9 +2832,9 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* For full screen windows, this function updates the resolution of its desired
|
||||
@@ -2810,9 +2850,9 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
|
||||
*
|
||||
* @param[in] window The window to resize.
|
||||
* @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
|
||||
* client area.
|
||||
* content area.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -2930,6 +2970,32 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int
|
||||
*/
|
||||
GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
|
||||
|
||||
/*! @brief Returns the double click time interval.
|
||||
*
|
||||
* This function returns the maximum time between clicks to count as a
|
||||
* double click.
|
||||
*
|
||||
* The double click interval is a positive finite number greater than zero,
|
||||
* where zero means that no click is ever recognized as a double click. If the
|
||||
* system does not support a double click interval, this function always returns one half.
|
||||
*
|
||||
* @return The double click interval.
|
||||
*
|
||||
* @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 double_click
|
||||
* @sa @ref click_interval
|
||||
* @sa @ref double_click_interval
|
||||
*
|
||||
* @since Added in version 3.3.
|
||||
*
|
||||
* @ingroup window
|
||||
*/
|
||||
GLFWAPI double glfwGetDoubleClickInterval(GLFWwindow* window);
|
||||
|
||||
/*! @brief Returns the opacity of the whole window.
|
||||
*
|
||||
* This function returns the opacity of the window, including any decorations.
|
||||
@@ -3000,9 +3066,8 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
* @remark @wayland There is no concept of iconification in wl_shell, this
|
||||
* function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
|
||||
* protocol.
|
||||
* @remark @wayland Once a window is iconified it cannot be restored
|
||||
* except by the compositor, this is a design decision of xdg-shell.
|
||||
*
|
||||
* @thread_safety This function must only be called from the main thread.
|
||||
*
|
||||
@@ -3190,7 +3255,7 @@ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
|
||||
* supported. Currently (macOS, Windows, X11 and Wayland).
|
||||
*
|
||||
* @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
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -3239,7 +3304,7 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
||||
* The window position is ignored when setting a monitor.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* If you only wish to update the resolution of a full screen window or the
|
||||
@@ -3252,10 +3317,10 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
|
||||
* @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] 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
|
||||
* client area.
|
||||
* @param[in] width The desired with, in screen coordinates, of the client area
|
||||
* content area.
|
||||
* @param[in] width The desired with, in screen coordinates, of the content area
|
||||
* or video mode.
|
||||
* @param[in] height The desired height, in screen coordinates, of the client
|
||||
* area or video mode.
|
||||
@@ -3340,7 +3405,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
|
||||
*
|
||||
* @param[in] window The window to set the attribute for.
|
||||
* @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
|
||||
* GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
|
||||
@@ -3407,7 +3472,7 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
|
||||
*
|
||||
* This function sets the position callback of the specified window, which is
|
||||
* 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.
|
||||
*
|
||||
* @param[in] window The window whose callback to set.
|
||||
@@ -3435,7 +3500,7 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindow
|
||||
*
|
||||
* 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,
|
||||
* 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] cbfun The new callback, or `NULL` to remove the currently set
|
||||
@@ -3492,7 +3557,7 @@ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwi
|
||||
/*! @brief Sets the refresh callback for the specified window.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* On compositing window systems such as Aero, Compiz, Aqua or Wayland, where
|
||||
@@ -3546,6 +3611,31 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GL
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This function sets the iconification callback of the specified window, which
|
||||
@@ -3559,9 +3649,6 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @sa @ref window_iconify
|
||||
@@ -3642,152 +3729,11 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* This function posts an empty event from the current thread to the event
|
||||
* 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
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
*
|
||||
@@ -3841,23 +3787,23 @@ GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);
|
||||
* and unlimited cursor movement. This is useful for implementing for
|
||||
* example 3D camera controls.
|
||||
*
|
||||
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to
|
||||
* enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are
|
||||
* If the mode is `GLFW_STICKY_KEYS`, the value must be either `true` to
|
||||
* enable sticky keys, or `false` to disable it. If sticky keys are
|
||||
* 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
|
||||
* call. This is useful when you are only interested in whether keys have been
|
||||
* pressed but not when or in which order.
|
||||
*
|
||||
* 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
|
||||
* @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
|
||||
* you are only interested in whether mouse buttons have been pressed but not
|
||||
* when or in which order.
|
||||
*
|
||||
* If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
|
||||
* enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled,
|
||||
* If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `true` to
|
||||
* enable lock key modifier bits, or `false` to disable them. If enabled,
|
||||
* 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,
|
||||
* and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
|
||||
@@ -4039,11 +3985,11 @@ GLFWAPI int glfwGetKey(GLFWwindow* window, int key);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor
|
||||
@@ -4059,9 +4005,9 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
||||
*
|
||||
* @param[in] window The desired window.
|
||||
* @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
|
||||
* 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
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -4077,11 +4023,11 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* 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
|
||||
* input focus when this function is called, it fails silently.
|
||||
*
|
||||
@@ -4096,9 +4042,9 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
|
||||
*
|
||||
* @param[in] window The desired window.
|
||||
* @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
|
||||
* client area.
|
||||
* content area.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_PLATFORM_ERROR.
|
||||
@@ -4177,7 +4123,7 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot,
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
|
||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape);
|
||||
|
||||
/*! @brief Destroys a cursor.
|
||||
*
|
||||
@@ -4209,7 +4155,7 @@ GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);
|
||||
/*! @brief Sets the cursor for the window.
|
||||
*
|
||||
* 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
|
||||
* `GLFW_CURSOR_NORMAL`.
|
||||
*
|
||||
@@ -4291,7 +4237,7 @@ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmo
|
||||
* 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
|
||||
* 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] cbfun The new callback, or `NULL` to remove the currently set
|
||||
@@ -4314,7 +4260,7 @@ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursor
|
||||
/*! @brief Sets the cursor enter/exit callback.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @param[in] window The window whose callback to set.
|
||||
@@ -4391,6 +4337,7 @@ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cb
|
||||
* @ingroup input
|
||||
*/
|
||||
GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||
GLFWAPI GLFWliveresizefun glfwSetLiveResizeCallback(GLFWwindow* window, GLFWliveresizefun cbfun);
|
||||
|
||||
/*! @brief Returns whether the specified joystick is present.
|
||||
*
|
||||
@@ -4401,7 +4348,7 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);
|
||||
* work.
|
||||
*
|
||||
* @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
|
||||
* GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
|
||||
@@ -4675,13 +4622,13 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid);
|
||||
* 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
|
||||
* whether it has a mapping.
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
|
||||
* or `GLFW_FALSE` otherwise.
|
||||
* @return `true` if a joystick is both present and has a gamepad mapping,
|
||||
* or `false` otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
* GLFW_INVALID_ENUM.
|
||||
@@ -4742,7 +4689,7 @@ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);
|
||||
* default.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||
@@ -4796,7 +4743,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
||||
* an Xbox-like gamepad.
|
||||
*
|
||||
* 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
|
||||
* whether it has a mapping.
|
||||
*
|
||||
@@ -4809,7 +4756,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
||||
*
|
||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||
* @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)
|
||||
* occurred.
|
||||
*
|
||||
@@ -5142,7 +5089,7 @@ GLFWAPI void glfwSwapInterval(int interval);
|
||||
* and `vkEnumerateDeviceExtensionProperties` instead.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
@@ -5215,7 +5162,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
|
||||
* and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue
|
||||
* 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.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
|
||||
@@ -5327,7 +5274,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
||||
*
|
||||
* If Vulkan or the required window surface creation instance extensions are
|
||||
* 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
|
||||
* to check whether Vulkan is at least minimally available and @ref
|
||||
* glfwGetRequiredInstanceExtensions to check what instance extensions are
|
||||
@@ -5336,13 +5283,13 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* p
|
||||
* @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] queuefamily The index of the queue family to query.
|
||||
* @return `GLFW_TRUE` if the queue family supports presentation, or
|
||||
* `GLFW_FALSE` otherwise.
|
||||
* @return `true` if the queue family supports presentation, or
|
||||
* `false` otherwise.
|
||||
*
|
||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||
* 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
|
||||
* 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
|
||||
//
|
||||
static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||
static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||
GLXFBConfig* result)
|
||||
{
|
||||
GLXFBConfig* nativeConfigs;
|
||||
@@ -55,20 +55,20 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||
const _GLFWfbconfig* closest;
|
||||
int i, nativeCount, usableCount;
|
||||
const char* vendor;
|
||||
GLFWbool trustWindowBit = GLFW_TRUE;
|
||||
bool trustWindowBit = true;
|
||||
|
||||
// HACK: This is a (hopefully temporary) workaround for Chromium
|
||||
// (VirtualBox GL) not setting the window bit on any GLXFBConfigs
|
||||
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
|
||||
if (vendor && strcmp(vendor, "Chromium") == 0)
|
||||
trustWindowBit = GLFW_FALSE;
|
||||
trustWindowBit = false;
|
||||
|
||||
nativeConfigs =
|
||||
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
|
||||
if (!nativeConfigs || !nativeCount)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
||||
@@ -116,9 +116,9 @@ static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
||||
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
|
||||
|
||||
if (getGLXFBConfigAttrib(n, GLX_STEREO))
|
||||
u->stereo = GLFW_TRUE;
|
||||
u->stereo = true;
|
||||
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
u->doublebuffer = true;
|
||||
|
||||
if (_glfw.glx.ARB_multisample)
|
||||
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
|
||||
@@ -210,10 +210,10 @@ static int extensionSupportedGLX(const char* extension)
|
||||
if (extensions)
|
||||
{
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressGLX(const char* procname)
|
||||
@@ -226,8 +226,6 @@ static GLFWglproc getProcAddressGLX(const char* procname)
|
||||
return _glfw_dlsym(_glfw.glx.handle, procname);
|
||||
}
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContextGLX(_GLFWwindow* window)
|
||||
{
|
||||
if (window->context.glx.window)
|
||||
@@ -250,7 +248,7 @@ static void destroyContextGLX(_GLFWwindow* window)
|
||||
|
||||
// Initialize GLX
|
||||
//
|
||||
GLFWbool _glfwInitGLX(void)
|
||||
bool _glfwInitGLX(void)
|
||||
{
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
@@ -267,7 +265,7 @@ GLFWbool _glfwInitGLX(void)
|
||||
};
|
||||
|
||||
if (_glfw.glx.handle)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
@@ -279,7 +277,7 @@ GLFWbool _glfwInitGLX(void)
|
||||
if (!_glfw.glx.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.glx.GetFBConfigs =
|
||||
@@ -331,7 +329,7 @@ GLFWbool _glfwInitGLX(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"GLX: Failed to load required entry points");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!glXQueryExtension(_glfw.x11.display,
|
||||
@@ -339,21 +337,21 @@ GLFWbool _glfwInitGLX(void)
|
||||
&_glfw.glx.eventBase))
|
||||
{
|
||||
_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))
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"GLX: Failed to query GLX version");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"GLX: GLX version 1.3 is required");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (extensionSupportedGLX("GLX_EXT_swap_control"))
|
||||
@@ -362,7 +360,7 @@ GLFWbool _glfwInitGLX(void)
|
||||
getProcAddressGLX("glXSwapIntervalEXT");
|
||||
|
||||
if (_glfw.glx.SwapIntervalEXT)
|
||||
_glfw.glx.EXT_swap_control = GLFW_TRUE;
|
||||
_glfw.glx.EXT_swap_control = true;
|
||||
}
|
||||
|
||||
if (extensionSupportedGLX("GLX_SGI_swap_control"))
|
||||
@@ -371,7 +369,7 @@ GLFWbool _glfwInitGLX(void)
|
||||
getProcAddressGLX("glXSwapIntervalSGI");
|
||||
|
||||
if (_glfw.glx.SwapIntervalSGI)
|
||||
_glfw.glx.SGI_swap_control = GLFW_TRUE;
|
||||
_glfw.glx.SGI_swap_control = true;
|
||||
}
|
||||
|
||||
if (extensionSupportedGLX("GLX_MESA_swap_control"))
|
||||
@@ -380,17 +378,17 @@ GLFWbool _glfwInitGLX(void)
|
||||
getProcAddressGLX("glXSwapIntervalMESA");
|
||||
|
||||
if (_glfw.glx.SwapIntervalMESA)
|
||||
_glfw.glx.MESA_swap_control = GLFW_TRUE;
|
||||
_glfw.glx.MESA_swap_control = true;
|
||||
}
|
||||
|
||||
if (extensionSupportedGLX("GLX_ARB_multisample"))
|
||||
_glfw.glx.ARB_multisample = GLFW_TRUE;
|
||||
_glfw.glx.ARB_multisample = true;
|
||||
|
||||
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"))
|
||||
_glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
|
||||
_glfw.glx.EXT_framebuffer_sRGB = true;
|
||||
|
||||
if (extensionSupportedGLX("GLX_ARB_create_context"))
|
||||
{
|
||||
@@ -398,25 +396,25 @@ GLFWbool _glfwInitGLX(void)
|
||||
getProcAddressGLX("glXCreateContextAttribsARB");
|
||||
|
||||
if (_glfw.glx.CreateContextAttribsARB)
|
||||
_glfw.glx.ARB_create_context = GLFW_TRUE;
|
||||
_glfw.glx.ARB_create_context = true;
|
||||
}
|
||||
|
||||
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"))
|
||||
_glfw.glx.ARB_create_context_profile = GLFW_TRUE;
|
||||
_glfw.glx.ARB_create_context_profile = true;
|
||||
|
||||
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"))
|
||||
_glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
|
||||
_glfw.glx.ARB_create_context_no_error = true;
|
||||
|
||||
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
|
||||
@@ -442,7 +440,7 @@ void _glfwTerminateGLX(void)
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
//
|
||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
bool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@@ -457,7 +455,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"GLX: Failed to find a suitable GLXFBConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_ES_API)
|
||||
@@ -468,7 +466,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_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,
|
||||
"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,
|
||||
"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 (_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
|
||||
@@ -590,7 +588,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
|
||||
ctxconfig->client == GLFW_OPENGL_API &&
|
||||
ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
|
||||
ctxconfig->forward == GLFW_FALSE)
|
||||
ctxconfig->forward == false)
|
||||
{
|
||||
window->context.glx.handle =
|
||||
createLegacyContextGLX(window, native, share);
|
||||
@@ -608,7 +606,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
if (!window->context.glx.handle)
|
||||
{
|
||||
_glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
window->context.glx.window =
|
||||
@@ -616,7 +614,7 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
if (!window->context.glx.window)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentGLX;
|
||||
@@ -626,14 +624,14 @@ GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
window->context.getProcAddress = getProcAddressGLX;
|
||||
window->context.destroy = destroyContextGLX;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
|
||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||
//
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
Visual** visual, int* depth)
|
||||
@@ -645,7 +643,7 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"GLX: Failed to find a suitable GLXFBConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
|
||||
@@ -653,14 +651,14 @@ GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"GLX: Failed to retrieve Visual for GLXFBConfig");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
*visual = result->visual;
|
||||
*depth = result->depth;
|
||||
|
||||
XFree(result);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -695,4 +693,3 @@ GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
|
||||
|
||||
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_WINDOW_BIT 0x00000001
|
||||
#define GLX_DRAWABLE_TYPE 0x8010
|
||||
#define GLX_RENDER_TYPE 0x8011
|
||||
#define GLX_RENDER_TYPE 0x8011
|
||||
#define GLX_RGBA_TYPE 0x8014
|
||||
#define GLX_DOUBLEBUFFER 5
|
||||
#define GLX_STEREO 6
|
||||
#define GLX_AUX_BUFFERS 7
|
||||
#define GLX_AUX_BUFFERS 7
|
||||
#define GLX_RED_SIZE 8
|
||||
#define GLX_GREEN_SIZE 9
|
||||
#define GLX_BLUE_SIZE 10
|
||||
@@ -42,7 +42,7 @@
|
||||
#define GLX_STENCIL_SIZE 13
|
||||
#define GLX_ACCUM_RED_SIZE 14
|
||||
#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_SAMPLES 0x186a1
|
||||
#define GLX_VISUAL_ID 0x800b
|
||||
@@ -153,28 +153,28 @@ typedef struct _GLFWlibraryGLX
|
||||
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||
GLFWbool SGI_swap_control;
|
||||
GLFWbool EXT_swap_control;
|
||||
GLFWbool MESA_swap_control;
|
||||
GLFWbool ARB_multisample;
|
||||
GLFWbool ARB_framebuffer_sRGB;
|
||||
GLFWbool EXT_framebuffer_sRGB;
|
||||
GLFWbool ARB_create_context;
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
bool SGI_swap_control;
|
||||
bool EXT_swap_control;
|
||||
bool MESA_swap_control;
|
||||
bool ARB_multisample;
|
||||
bool ARB_framebuffer_sRGB;
|
||||
bool EXT_framebuffer_sRGB;
|
||||
bool ARB_create_context;
|
||||
bool ARB_create_context_profile;
|
||||
bool ARB_create_context_robustness;
|
||||
bool EXT_create_context_es2_profile;
|
||||
bool ARB_create_context_no_error;
|
||||
bool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryGLX;
|
||||
|
||||
GLFWbool _glfwInitGLX(void);
|
||||
bool _glfwInitGLX(void);
|
||||
void _glfwTerminateGLX(void);
|
||||
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
bool _glfwCreateContextGLX(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyContextGLX(_GLFWwindow* window);
|
||||
GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig,
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
static char buf[1024];
|
||||
struct stat s;
|
||||
FILE *addr_file = fopen(ibus->address_file_name, "r");
|
||||
if (!addr_file) {
|
||||
_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);
|
||||
GLFWbool found = GLFW_FALSE;
|
||||
bool found = false;
|
||||
while (fgets(buf, sizeof(buf), addr_file)) {
|
||||
if (strncmp(buf, "IBUS_ADDRESS=", sizeof("IBUS_ADDRESS=")-1) == 0) {
|
||||
size_t sz = strlen(buf);
|
||||
if (buf[sz-1] == '\n') buf[sz-1] = 0;
|
||||
if (buf[sz-2] == '\r') buf[sz-2] = 0;
|
||||
found = GLFW_TRUE;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(addr_file); addr_file = NULL;
|
||||
if (stat_result != 0) {
|
||||
_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;
|
||||
if (found) {
|
||||
free((void*)ibus->address);
|
||||
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);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
ibus->ok = GLFW_TRUE;
|
||||
glfw_ibus_set_focused(ibus, GLFW_FALSE);
|
||||
ibus->ok = true;
|
||||
glfw_ibus_set_focused(ibus, false);
|
||||
glfw_ibus_set_cursor_geometry(ibus, 0, 0, 0, 0);
|
||||
debug("Connected to IBUS daemon for IME input management\n");
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
setup_connection(_GLFWIBUSData *ibus) {
|
||||
const char *client_name = "GLFW_Application";
|
||||
const char *address_file_name = get_ibus_address_file_name();
|
||||
ibus->ok = GLFW_FALSE;
|
||||
if (!address_file_name) return GLFW_FALSE;
|
||||
ibus->ok = false;
|
||||
if (!address_file_name) return false;
|
||||
free((void*)ibus->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) {
|
||||
glfw_dbus_close_connection(ibus->conn);
|
||||
ibus->conn = NULL;
|
||||
}
|
||||
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);
|
||||
if (!ibus->conn) return 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 false;
|
||||
free((void*)ibus->input_ctx_path); ibus->input_ctx_path = NULL;
|
||||
if (!glfw_dbus_call_method_with_reply(
|
||||
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)) {
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ void
|
||||
glfw_connect_to_ibus(_GLFWIBUSData *ibus) {
|
||||
if (ibus->inited) return;
|
||||
if (!test_env_var("GLFW_IM_MODULE", "ibus")) return;
|
||||
ibus->inited = GLFW_TRUE;
|
||||
ibus->inited = true;
|
||||
setup_connection(ibus);
|
||||
}
|
||||
|
||||
@@ -297,21 +297,21 @@ glfw_ibus_terminate(_GLFWIBUSData *ibus) {
|
||||
F(address_file_name);
|
||||
#undef F
|
||||
|
||||
ibus->ok = GLFW_FALSE;
|
||||
ibus->ok = false;
|
||||
}
|
||||
|
||||
static GLFWbool
|
||||
static bool
|
||||
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)) {
|
||||
return ibus->ok;
|
||||
}
|
||||
struct stat s;
|
||||
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);
|
||||
}
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -329,7 +329,7 @@ simple_message(_GLFWIBUSData *ibus, const char *method) {
|
||||
}
|
||||
|
||||
void
|
||||
glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused) {
|
||||
glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused) {
|
||||
simple_message(ibus, focused ? "FocusIn" : "FocusOut");
|
||||
}
|
||||
|
||||
@@ -394,24 +394,24 @@ void
|
||||
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
|
||||
uint32_t handled = 0;
|
||||
KeyEvent *ev = (KeyEvent*)data;
|
||||
GLFWbool is_release = ev->action == GLFW_RELEASE;
|
||||
GLFWbool failed = GLFW_FALSE;
|
||||
bool is_release = ev->action == GLFW_RELEASE;
|
||||
bool failed = false;
|
||||
if (errmsg) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
|
||||
failed = GLFW_TRUE;
|
||||
failed = true;
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
glfw_xkb_key_from_ime(ev, handled ? GLFW_TRUE : GLFW_FALSE, failed);
|
||||
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
|
||||
free(ev);
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
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));
|
||||
if (!ev) return GLFW_FALSE;
|
||||
if (!ev) return false;
|
||||
memcpy(ev, ev_, sizeof(KeyEvent));
|
||||
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
|
||||
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,
|
||||
&state, DBUS_TYPE_INVALID)) {
|
||||
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>
|
||||
|
||||
typedef struct {
|
||||
GLFWbool ok, inited;
|
||||
bool ok, inited;
|
||||
time_t address_file_mtime;
|
||||
DBusConnection *conn;
|
||||
const char *input_ctx_path, *address_file_name, *address;
|
||||
@@ -49,7 +49,7 @@ typedef struct {
|
||||
|
||||
void glfw_connect_to_ibus(_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);
|
||||
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);
|
||||
|
||||
71
glfw/init.c
vendored
71
glfw/init.c
vendored
@@ -41,7 +41,7 @@
|
||||
|
||||
// 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
|
||||
// after termination
|
||||
@@ -50,12 +50,12 @@ static _GLFWerror _glfwMainThreadError;
|
||||
static GLFWerrorfun _glfwErrorCallback;
|
||||
static _GLFWinitconfig _glfwInitHints =
|
||||
{
|
||||
GLFW_TRUE, // hat buttons
|
||||
GLFW_FALSE, // debug keyboard
|
||||
GLFW_TRUE, // enable joystick
|
||||
true, // hat buttons
|
||||
false, // debug keyboard
|
||||
true, // enable joystick
|
||||
{
|
||||
GLFW_TRUE, // macOS menu bar
|
||||
GLFW_TRUE // macOS bundle chdir
|
||||
true, // macOS menu bar
|
||||
true // macOS bundle chdir
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ static void terminate(void)
|
||||
_glfwTerminateVulkan();
|
||||
_glfwPlatformTerminate();
|
||||
|
||||
_glfw.initialized = GLFW_FALSE;
|
||||
_glfw.initialized = false;
|
||||
|
||||
while (_glfw.errorListHead)
|
||||
{
|
||||
@@ -193,6 +193,20 @@ void _glfwInputError(int code, const char* format, ...)
|
||||
_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 //////
|
||||
@@ -201,7 +215,7 @@ void _glfwInputError(int code, const char* format, ...)
|
||||
GLFWAPI int glfwInit(void)
|
||||
{
|
||||
if (_glfw.initialized)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
memset(&_glfw, 0, sizeof(_glfw));
|
||||
_glfw.hints.init = _glfwInitHints;
|
||||
@@ -209,7 +223,7 @@ GLFWAPI int glfwInit(void)
|
||||
if (!_glfwPlatformInit())
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
|
||||
@@ -217,12 +231,12 @@ GLFWAPI int glfwInit(void)
|
||||
!_glfwPlatformCreateTls(&_glfw.contextSlot))
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||
|
||||
_glfw.initialized = GLFW_TRUE;
|
||||
_glfw.initialized = true;
|
||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
||||
|
||||
glfwDefaultWindowHints();
|
||||
@@ -235,12 +249,12 @@ GLFWAPI int glfwInit(void)
|
||||
if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
|
||||
{
|
||||
terminate();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwTerminate(void)
|
||||
@@ -320,3 +334,34 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
|
||||
_GLFW_SWAP_POINTERS(_glfwErrorCallback, 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);
|
||||
}
|
||||
|
||||
110
glfw/input.c
vendored
110
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
|
||||
//
|
||||
static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
|
||||
static bool isValidElementForJoystick(const _GLFWmapelement* e,
|
||||
const _GLFWjoystick* js)
|
||||
{
|
||||
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)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
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
|
||||
@@ -110,7 +110,7 @@ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
|
||||
|
||||
// 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;
|
||||
size_t i, length;
|
||||
@@ -148,7 +148,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||
if (length != 32 || c[length] != ',')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(mapping->guid, c, length);
|
||||
@@ -158,7 +158,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||
if (length >= sizeof(mapping->name) || c[length] != ',')
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_VALUE, NULL);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(mapping->name, c, length);
|
||||
@@ -168,7 +168,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||
{
|
||||
// TODO: Implement output modifiers
|
||||
if (*c == '+' || *c == '-')
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
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);
|
||||
if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -246,7 +246,7 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
|
||||
}
|
||||
|
||||
_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)
|
||||
{
|
||||
GLFWbool repeated = GLFW_FALSE;
|
||||
bool repeated = false;
|
||||
|
||||
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
||||
return;
|
||||
|
||||
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
||||
repeated = GLFW_TRUE;
|
||||
repeated = true;
|
||||
|
||||
if (action == GLFW_RELEASE && window->stickyKeys)
|
||||
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
|
||||
// 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)
|
||||
{
|
||||
@@ -328,7 +328,7 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
|
||||
|
||||
// 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)
|
||||
window->callbacks.cursorEnter((GLFWwindow*) window, entered);
|
||||
@@ -406,7 +406,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
return NULL;
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
js->present = GLFW_TRUE;
|
||||
js->present = true;
|
||||
js->name = _glfw_strdup(name);
|
||||
js->axes = calloc(axisCount, sizeof(float));
|
||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
||||
@@ -415,7 +415,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
js->buttonCount = buttonCount;
|
||||
js->hatCount = hatCount;
|
||||
|
||||
strcpy(js->guid, guid);
|
||||
strncpy(js->guid, guid, sizeof(js->guid) - 1);
|
||||
js->mapping = findValidMapping(js);
|
||||
|
||||
return js;
|
||||
@@ -487,6 +487,8 @@ const char* _glfwGetKeyName(int key)
|
||||
case GLFW_KEY_SLASH: return "SLASH";
|
||||
case GLFW_KEY_WORLD_1: return "WORLD 1";
|
||||
case GLFW_KEY_WORLD_2: return "WORLD 2";
|
||||
case GLFW_KEY_PLUS: return "PLUS";
|
||||
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
|
||||
|
||||
// Function keys
|
||||
case GLFW_KEY_ESCAPE: return "ESCAPE";
|
||||
@@ -564,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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -622,7 +633,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
}
|
||||
else if (mode == GLFW_STICKY_KEYS)
|
||||
{
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
value = value ? true : false;
|
||||
if (window->stickyKeys == value)
|
||||
return;
|
||||
|
||||
@@ -642,7 +653,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
}
|
||||
else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
|
||||
{
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
value = value ? true : false;
|
||||
if (window->stickyMouseButtons == value)
|
||||
return;
|
||||
|
||||
@@ -661,7 +672,7 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
||||
window->stickyMouseButtons = value;
|
||||
}
|
||||
else if (mode == GLFW_LOCK_KEY_MODS)
|
||||
window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
window->lockKeyMods = value ? true : false;
|
||||
else
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||
}
|
||||
@@ -821,20 +832,15 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot,
|
||||
return (GLFWcursor*) cursor;
|
||||
}
|
||||
|
||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
|
||||
GLFWAPI GLFWcursor* glfwCreateStandardCursor(GLFWCursorShape shape)
|
||||
{
|
||||
_GLFWcursor* cursor;
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
if (shape != GLFW_ARROW_CURSOR &&
|
||||
shape != GLFW_IBEAM_CURSOR &&
|
||||
shape != GLFW_CROSSHAIR_CURSOR &&
|
||||
shape != GLFW_HAND_CURSOR &&
|
||||
shape != GLFW_HRESIZE_CURSOR &&
|
||||
shape != GLFW_VRESIZE_CURSOR)
|
||||
if (shape >= GLFW_INVALID_CURSOR)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor: %d", shape);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -914,7 +920,7 @@ GLFWAPI void glfwUpdateIMEState(GLFWwindow* handle, int which, int a, int b, int
|
||||
assert(window != NULL);
|
||||
|
||||
_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);
|
||||
#else
|
||||
(void)window; (void)which; (void)a; (void)b; (void)c; (void)d;
|
||||
@@ -982,17 +988,17 @@ GLFWAPI int glfwJoystickPresent(int jid)
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
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)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
|
||||
}
|
||||
@@ -1184,7 +1190,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||
|
||||
assert(string != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
|
||||
while (*c)
|
||||
{
|
||||
@@ -1234,7 +1240,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
|
||||
js->mapping = findValidMapping(js);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwJoystickIsGamepad(int jid)
|
||||
@@ -1244,20 +1250,20 @@ GLFWAPI int glfwJoystickIsGamepad(int jid)
|
||||
assert(jid >= GLFW_JOYSTICK_1);
|
||||
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)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
return js->mapping != NULL;
|
||||
}
|
||||
@@ -1301,23 +1307,23 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
||||
|
||||
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)
|
||||
{
|
||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
js = _glfw.joysticks + jid;
|
||||
if (!js->present)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (!js->mapping)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
|
||||
{
|
||||
@@ -1358,7 +1364,7 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
||||
state->axes[i] = (float) js->buttons[e->index];
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
||||
@@ -1375,6 +1381,22 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
||||
return _glfwPlatformGetClipboardString();
|
||||
}
|
||||
|
||||
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
||||
GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle, const char* string)
|
||||
{
|
||||
assert(string != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
_glfwPlatformSetPrimarySelectionString(string);
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return _glfwPlatformGetPrimarySelectionString();
|
||||
}
|
||||
#endif
|
||||
|
||||
GLFWAPI double glfwGetTime(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
||||
|
||||
166
glfw/internal.h
vendored
166
glfw/internal.h
vendored
@@ -60,7 +60,6 @@
|
||||
|
||||
#define _GLFW_MESSAGE_SIZE 1024
|
||||
|
||||
typedef int GLFWbool;
|
||||
typedef unsigned long long GLFWid;
|
||||
|
||||
typedef struct _GLFWerror _GLFWerror;
|
||||
@@ -87,8 +86,8 @@ typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
|
||||
typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
|
||||
#define GL_VERSION 0x1f02
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_NONE 0
|
||||
#define GL_COLOR_BUFFER_BIT 0x00004000
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_EXTENSIONS 0x1f03
|
||||
#define GL_NUM_EXTENSIONS 0x821d
|
||||
@@ -105,7 +104,7 @@ typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
|
||||
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
|
||||
#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
|
||||
|
||||
typedef int GLint;
|
||||
typedef int GLint;
|
||||
typedef unsigned int GLuint;
|
||||
typedef unsigned int GLenum;
|
||||
typedef unsigned int GLbitfield;
|
||||
@@ -129,7 +128,6 @@ typedef enum VkStructureType
|
||||
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
|
||||
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
|
||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||
@@ -191,14 +189,19 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
||||
#include "x11_platform.h"
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
#include "wl_platform.h"
|
||||
#elif defined(_GLFW_MIR)
|
||||
#include "mir_platform.h"
|
||||
#elif defined(_GLFW_OSMESA)
|
||||
#include "null_platform.h"
|
||||
#else
|
||||
#error "No supported window creation API selected"
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
|
||||
#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
|
||||
@@ -244,12 +247,12 @@ struct _GLFWerror
|
||||
//
|
||||
struct _GLFWinitconfig
|
||||
{
|
||||
GLFWbool hatButtons;
|
||||
GLFWbool debugKeyboard;
|
||||
GLFWbool enableJoysticks;
|
||||
bool hatButtons;
|
||||
bool debugKeyboard;
|
||||
bool enableJoysticks;
|
||||
struct {
|
||||
GLFWbool menubar;
|
||||
GLFWbool chdir;
|
||||
bool menubar;
|
||||
bool chdir;
|
||||
} ns;
|
||||
};
|
||||
|
||||
@@ -264,18 +267,18 @@ struct _GLFWwndconfig
|
||||
int width;
|
||||
int height;
|
||||
const char* title;
|
||||
GLFWbool resizable;
|
||||
GLFWbool visible;
|
||||
GLFWbool decorated;
|
||||
GLFWbool focused;
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool maximized;
|
||||
GLFWbool centerCursor;
|
||||
GLFWbool focusOnShow;
|
||||
GLFWbool scaleToMonitor;
|
||||
bool resizable;
|
||||
bool visible;
|
||||
bool decorated;
|
||||
bool focused;
|
||||
bool autoIconify;
|
||||
bool floating;
|
||||
bool maximized;
|
||||
bool centerCursor;
|
||||
bool focusOnShow;
|
||||
bool scaleToMonitor;
|
||||
struct {
|
||||
GLFWbool retina;
|
||||
bool retina;
|
||||
char frameName[256];
|
||||
} ns;
|
||||
struct {
|
||||
@@ -299,15 +302,15 @@ struct _GLFWctxconfig
|
||||
int source;
|
||||
int major;
|
||||
int minor;
|
||||
GLFWbool forward;
|
||||
GLFWbool debug;
|
||||
GLFWbool noerror;
|
||||
bool forward;
|
||||
bool debug;
|
||||
bool noerror;
|
||||
int profile;
|
||||
int robustness;
|
||||
int release;
|
||||
_GLFWwindow* share;
|
||||
struct {
|
||||
GLFWbool offline;
|
||||
bool offline;
|
||||
} nsgl;
|
||||
};
|
||||
|
||||
@@ -332,11 +335,11 @@ struct _GLFWfbconfig
|
||||
int accumBlueBits;
|
||||
int accumAlphaBits;
|
||||
int auxBuffers;
|
||||
GLFWbool stereo;
|
||||
bool stereo;
|
||||
int samples;
|
||||
GLFWbool sRGB;
|
||||
GLFWbool doublebuffer;
|
||||
GLFWbool transparent;
|
||||
bool sRGB;
|
||||
bool doublebuffer;
|
||||
bool transparent;
|
||||
uintptr_t handle;
|
||||
};
|
||||
|
||||
@@ -347,7 +350,7 @@ struct _GLFWcontext
|
||||
int client;
|
||||
int source;
|
||||
int major, minor, revision;
|
||||
GLFWbool forward, debug, noerror;
|
||||
bool forward, debug, noerror;
|
||||
int profile;
|
||||
int robustness;
|
||||
int release;
|
||||
@@ -378,12 +381,12 @@ struct _GLFWwindow
|
||||
struct _GLFWwindow* next;
|
||||
|
||||
// Window settings and state
|
||||
GLFWbool resizable;
|
||||
GLFWbool decorated;
|
||||
GLFWbool autoIconify;
|
||||
GLFWbool floating;
|
||||
GLFWbool focusOnShow;
|
||||
GLFWbool shouldClose;
|
||||
bool resizable;
|
||||
bool decorated;
|
||||
bool autoIconify;
|
||||
bool floating;
|
||||
bool focusOnShow;
|
||||
bool shouldClose;
|
||||
void* userPointer;
|
||||
GLFWid id;
|
||||
GLFWvidmode videoMode;
|
||||
@@ -394,9 +397,9 @@ struct _GLFWwindow
|
||||
int maxwidth, maxheight;
|
||||
int numer, denom;
|
||||
|
||||
GLFWbool stickyKeys;
|
||||
GLFWbool stickyMouseButtons;
|
||||
GLFWbool lockKeyMods;
|
||||
bool stickyKeys;
|
||||
bool stickyMouseButtons;
|
||||
bool lockKeyMods;
|
||||
int cursorMode;
|
||||
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
||||
char keys[GLFW_KEY_LAST + 1];
|
||||
@@ -411,6 +414,7 @@ struct _GLFWwindow
|
||||
GLFWwindowclosefun close;
|
||||
GLFWwindowrefreshfun refresh;
|
||||
GLFWwindowfocusfun focus;
|
||||
GLFWwindowocclusionfun occlusion;
|
||||
GLFWwindowiconifyfun iconify;
|
||||
GLFWwindowmaximizefun maximize;
|
||||
GLFWframebuffersizefun fbsize;
|
||||
@@ -421,6 +425,7 @@ struct _GLFWwindow
|
||||
GLFWscrollfun scroll;
|
||||
GLFWkeyboardfun keyboard;
|
||||
GLFWdropfun drop;
|
||||
GLFWliveresizefun liveResize;
|
||||
} callbacks;
|
||||
|
||||
// This is defined in the window API's platform.h
|
||||
@@ -485,7 +490,7 @@ struct _GLFWmapping
|
||||
//
|
||||
struct _GLFWjoystick
|
||||
{
|
||||
GLFWbool present;
|
||||
bool present;
|
||||
float* axes;
|
||||
int axisCount;
|
||||
unsigned char* buttons;
|
||||
@@ -521,7 +526,7 @@ struct _GLFWmutex
|
||||
//
|
||||
struct _GLFWlibrary
|
||||
{
|
||||
GLFWbool initialized;
|
||||
bool initialized;
|
||||
|
||||
struct {
|
||||
_GLFWinitconfig init;
|
||||
@@ -554,25 +559,23 @@ struct _GLFWlibrary
|
||||
} timer;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
char* extensions[2];
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||
#endif
|
||||
GLFWbool KHR_surface;
|
||||
bool KHR_surface;
|
||||
#if defined(_GLFW_WIN32)
|
||||
GLFWbool KHR_win32_surface;
|
||||
bool KHR_win32_surface;
|
||||
#elif defined(_GLFW_COCOA)
|
||||
GLFWbool MVK_macos_surface;
|
||||
bool MVK_macos_surface;
|
||||
#elif defined(_GLFW_X11)
|
||||
GLFWbool KHR_xlib_surface;
|
||||
GLFWbool KHR_xcb_surface;
|
||||
bool KHR_xlib_surface;
|
||||
bool KHR_xcb_surface;
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
GLFWbool KHR_wayland_surface;
|
||||
#elif defined(_GLFW_MIR)
|
||||
GLFWbool KHR_mir_surface;
|
||||
bool KHR_wayland_surface;
|
||||
#endif
|
||||
} vk;
|
||||
|
||||
@@ -611,7 +614,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
|
||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
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 _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||
|
||||
@@ -622,13 +625,18 @@ void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
float* xscale, float* yscale);
|
||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
|
||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
|
||||
|
||||
void _glfwPlatformSetClipboardString(const char* string);
|
||||
const char* _glfwPlatformGetClipboardString(void);
|
||||
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
||||
void _glfwPlatformSetPrimarySelectionString(const char* string);
|
||||
const char* _glfwPlatformGetPrimarySelectionString(void);
|
||||
#endif
|
||||
|
||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
||||
@@ -653,11 +661,13 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||
int maxwidth, int maxheight);
|
||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||
void _glfwInputLiveResize(_GLFWwindow* window, bool started);
|
||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||
int* left, int* top,
|
||||
int* right, int* bottom);
|
||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
float* xscale, float* yscale);
|
||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||
@@ -669,16 +679,18 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
||||
int xpos, int ypos, int width, int height,
|
||||
int refreshRate);
|
||||
bool _glfwPlatformToggleFullscreen(_GLFWwindow *w, unsigned int flags);
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window);
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window);
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
|
||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
|
||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled);
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled);
|
||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled);
|
||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
|
||||
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,
|
||||
VkSurfaceKHR* surface);
|
||||
|
||||
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||
bool _glfwPlatformCreateTls(_GLFWtls* tls);
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls);
|
||||
void* _glfwPlatformGetTls(_GLFWtls* tls);
|
||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
|
||||
|
||||
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
||||
bool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex);
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
||||
@@ -711,14 +723,15 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
|
||||
////// 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 _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
|
||||
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
|
||||
void _glfwInputWindowContentScale(_GLFWwindow* window,
|
||||
float xscale, float yscale);
|
||||
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
|
||||
void _glfwInputWindowIconify(_GLFWwindow* window, bool iconified);
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, bool maximized);
|
||||
void _glfwInputWindowDamage(_GLFWwindow* window);
|
||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||
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 _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||
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 _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||
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 _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
void _glfwInputError(int code, const char* format, ...)
|
||||
__attribute__((format(printf, 2, 3)));
|
||||
void _glfwDebug(const char* format, ...)
|
||||
__attribute__((format(printf, 1, 2)));
|
||||
#else
|
||||
void _glfwInputError(int code, const char* format, ...);
|
||||
void _glfwDebug(const char* format, ...);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EVENT_LOOP
|
||||
#define EVDBG(...) _glfwDebug(__VA_ARGS__)
|
||||
#else
|
||||
#define EVDBG(...)
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////// 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* alternatives,
|
||||
unsigned int count);
|
||||
GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
bool _glfwRefreshContextAttribs(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig);
|
||||
GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||
bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
|
||||
|
||||
const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
|
||||
const GLFWvidmode* desired);
|
||||
@@ -773,11 +794,18 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
||||
int hatCount);
|
||||
void _glfwFreeJoystick(_GLFWjoystick* js);
|
||||
const char* _glfwGetKeyName(int key);
|
||||
void _glfwCenterCursorInContentArea(_GLFWwindow* window);
|
||||
|
||||
GLFWbool _glfwInitVulkan(int mode);
|
||||
bool _glfwInitVulkan(int mode);
|
||||
void _glfwTerminateVulkan(void);
|
||||
const char* _glfwGetVulkanResultString(VkResult result);
|
||||
_GLFWwindow* _glfwFocusedWindow();
|
||||
_GLFWwindow* _glfwFocusedWindow(void);
|
||||
_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);
|
||||
|
||||
27
glfw/linux_joystick.c
vendored
27
glfw/linux_joystick.c
vendored
@@ -124,7 +124,7 @@ static void pollAbsState(_GLFWjoystick* js)
|
||||
|
||||
// Attempt to open the specified joystick device
|
||||
//
|
||||
static GLFWbool openJoystickDevice(const char* path)
|
||||
static bool openJoystickDevice(const char* path)
|
||||
{
|
||||
int jid, code;
|
||||
char name[256] = "";
|
||||
@@ -142,12 +142,12 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
if (!_glfw.joysticks[jid].present)
|
||||
continue;
|
||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||
if (linjs.fd == -1)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 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",
|
||||
strerror(errno));
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure this device supports the events expected of a joystick
|
||||
if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
||||
@@ -225,16 +225,16 @@ static GLFWbool openJoystickDevice(const char* path)
|
||||
if (!js)
|
||||
{
|
||||
close(linjs.fd);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
strncpy(linjs.path, path, sizeof(linjs.path));
|
||||
strncpy(linjs.path, path, sizeof(linjs.path) - 1);
|
||||
memcpy(&js->linjs, &linjs, sizeof(linjs));
|
||||
|
||||
pollAbsState(js);
|
||||
|
||||
_glfwInputJoystick(js, GLFW_CONNECTED);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef isBitSet
|
||||
@@ -264,7 +264,7 @@ static int compareJoysticks(const void* fp, const void* sp)
|
||||
|
||||
// Initialize joystick interface
|
||||
//
|
||||
GLFWbool _glfwInitJoysticksLinux(void)
|
||||
bool _glfwInitJoysticksLinux(void)
|
||||
{
|
||||
DIR* dir;
|
||||
int count = 0;
|
||||
@@ -286,7 +286,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
dir = opendir(dirname);
|
||||
@@ -315,7 +315,7 @@ GLFWbool _glfwInitJoysticksLinux(void)
|
||||
// Continue with no joysticks if enumeration fails
|
||||
|
||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Close all opened joystick handles
|
||||
@@ -408,10 +408,10 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
if (e.type == EV_SYN)
|
||||
{
|
||||
if (e.code == SYN_DROPPED)
|
||||
_glfw.linjs.dropped = GLFW_TRUE;
|
||||
_glfw.linjs.dropped = true;
|
||||
else if (e.code == SYN_REPORT)
|
||||
{
|
||||
_glfw.linjs.dropped = GLFW_FALSE;
|
||||
_glfw.linjs.dropped = false;
|
||||
pollAbsState(js);
|
||||
}
|
||||
}
|
||||
@@ -431,4 +431,3 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
4
glfw/linux_joystick.h
vendored
4
glfw/linux_joystick.h
vendored
@@ -52,11 +52,11 @@ typedef struct _GLFWlibraryLinux
|
||||
int inotify;
|
||||
int watch;
|
||||
regex_t regex;
|
||||
GLFWbool dropped;
|
||||
bool dropped;
|
||||
} _GLFWlibraryLinux;
|
||||
|
||||
|
||||
GLFWbool _glfwInitJoysticksLinux(void);
|
||||
bool _glfwInitJoysticksLinux(void);
|
||||
void _glfwTerminateJoysticksLinux(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);
|
||||
}
|
||||
54
glfw/memfd.h
vendored
Normal file
54
glfw/memfd.h
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef HAS_MEMFD_CREATE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
static inline int memfd_create(const char *name, unsigned int flags) {
|
||||
return syscall(__NR_memfd_create, name, flags);
|
||||
}
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
|
||||
#ifndef F_ADD_SEALS
|
||||
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
|
||||
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
|
||||
|
||||
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
|
||||
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
|
||||
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
|
||||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
#endif
|
||||
|
||||
#ifndef MFD_CLOEXEC
|
||||
#define MFD_CLOEXEC 0x0001U
|
||||
#define MFD_ALLOW_SEALING 0x0002U
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static inline int
|
||||
createTmpfileCloexec(char* tmpname)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = mkostemp(tmpname, O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
unlink(tmpname);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#endif
|
||||
59
glfw/monitor.c
vendored
59
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
|
||||
//
|
||||
static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
||||
static bool refreshVideoModes(_GLFWmonitor* monitor)
|
||||
{
|
||||
int modeCount;
|
||||
GLFWvidmode* modes;
|
||||
|
||||
if (monitor->modes)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
|
||||
if (!modes)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
||||
|
||||
@@ -78,7 +78,7 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
|
||||
monitor->modes = modes;
|
||||
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)
|
||||
{
|
||||
_glfw.monitorCount--;
|
||||
memmove(_glfw.monitors + i,
|
||||
_glfw.monitors + i + 1,
|
||||
(_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
|
||||
remove_i_from_array(_glfw.monitors, i, _glfw.monitorCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -330,6 +327,25 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* 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)
|
||||
{
|
||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||
@@ -427,11 +443,11 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
|
||||
|
||||
GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||
{
|
||||
int i;
|
||||
unsigned short values[256];
|
||||
unsigned int i;
|
||||
unsigned short* values;
|
||||
GLFWgammaramp ramp;
|
||||
const GLFWgammaramp* original;
|
||||
assert(handle != NULL);
|
||||
assert(gamma == gamma);
|
||||
assert(gamma >= 0.f);
|
||||
assert(gamma <= FLT_MAX);
|
||||
|
||||
@@ -442,13 +458,18 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
||||
return;
|
||||
}
|
||||
original = glfwGetGammaRamp(handle);
|
||||
if (!original)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
values = calloc(original->size, sizeof(unsigned short));
|
||||
|
||||
for (i = 0; i < original->size; i++)
|
||||
{
|
||||
float value;
|
||||
|
||||
// Calculate intensity
|
||||
value = i / 255.f;
|
||||
value = i / (float) (original->size - 1);
|
||||
// Apply gamma curve
|
||||
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||
|
||||
@@ -462,9 +483,10 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
||||
ramp.red = values;
|
||||
ramp.green = values;
|
||||
ramp.blue = values;
|
||||
ramp.size = 256;
|
||||
ramp.size = original->size;
|
||||
|
||||
glfwSetGammaRamp(handle, &ramp);
|
||||
free(values);
|
||||
}
|
||||
|
||||
GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
||||
@@ -475,7 +497,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
|
||||
_glfwFreeGammaArrays(&monitor->currentRamp);
|
||||
_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
|
||||
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
|
||||
return NULL;
|
||||
|
||||
return &monitor->currentRamp;
|
||||
}
|
||||
@@ -501,8 +524,10 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (!monitor->originalRamp.size)
|
||||
_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
|
||||
{
|
||||
if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwPlatformSetGammaRamp(monitor, ramp);
|
||||
}
|
||||
|
||||
|
||||
6
glfw/nsgl_context.h
vendored
6
glfw/nsgl_context.h
vendored
@@ -33,7 +33,7 @@
|
||||
typedef struct _GLFWcontextNSGL
|
||||
{
|
||||
id pixelFormat;
|
||||
id object;
|
||||
id object;
|
||||
|
||||
} _GLFWcontextNSGL;
|
||||
|
||||
@@ -47,9 +47,9 @@ typedef struct _GLFWlibraryNSGL
|
||||
} _GLFWlibraryNSGL;
|
||||
|
||||
|
||||
GLFWbool _glfwInitNSGL(void);
|
||||
bool _glfwInitNSGL(void);
|
||||
void _glfwTerminateNSGL(void);
|
||||
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||
|
||||
@@ -45,17 +45,16 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
||||
|
||||
static void swapIntervalNSGL(int interval)
|
||||
{
|
||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
||||
|
||||
GLint sync = interval;
|
||||
[window->context.nsgl.object setValues:&sync
|
||||
forParameter:NSOpenGLCPSwapInterval];
|
||||
// As of Mojave this does not work so we use CVDisplayLink instead
|
||||
(void)(interval);
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"NSGL: Swap intervals do not work on macOS");
|
||||
}
|
||||
|
||||
static int extensionSupportedNSGL(const char* extension)
|
||||
{
|
||||
// There are no NSGL extensions
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressNSGL(const char* procname)
|
||||
@@ -72,8 +71,6 @@ static GLFWglproc getProcAddressNSGL(const char* procname)
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// Destroy the OpenGL context
|
||||
//
|
||||
static void destroyContextNSGL(_GLFWwindow* window)
|
||||
{
|
||||
[window->context.nsgl.pixelFormat release];
|
||||
@@ -90,10 +87,10 @@ static void destroyContextNSGL(_GLFWwindow* window)
|
||||
|
||||
// Initialize OpenGL support
|
||||
//
|
||||
GLFWbool _glfwInitNSGL(void)
|
||||
bool _glfwInitNSGL(void)
|
||||
{
|
||||
if (_glfw.nsgl.framework)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
_glfw.nsgl.framework =
|
||||
CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
@@ -101,10 +98,10 @@ GLFWbool _glfwInitNSGL(void)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"NSGL: Failed to locate OpenGL framework");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Terminate OpenGL support
|
||||
@@ -115,7 +112,7 @@ void _glfwTerminateNSGL(void)
|
||||
|
||||
// Create the OpenGL context
|
||||
//
|
||||
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@@ -123,7 +120,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"NSGL: OpenGL ES is not available on macOS");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->major > 2)
|
||||
@@ -132,15 +129,9 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
{
|
||||
_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");
|
||||
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
|
||||
@@ -175,9 +166,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
// Info.plist for unbundled applications
|
||||
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||
// a straightforward wrapper of its CGL counterpart
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||
}
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
|
||||
@@ -242,7 +231,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"NSGL: Stereo rendering is deprecated");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
#else
|
||||
addAttrib(NSOpenGLPFAStereo);
|
||||
#endif
|
||||
@@ -278,7 +267,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
||||
"NSGL: Failed to find a suitable pixel format");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
NSOpenGLContext* share = NULL;
|
||||
@@ -293,15 +282,22 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"NSGL: Failed to create OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fbconfig->transparent)
|
||||
{
|
||||
GLint opaque = 0;
|
||||
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
|
||||
[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.makeCurrent = makeContextCurrentNSGL;
|
||||
@@ -311,7 +307,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
||||
window->context.getProcAddress = getProcAddressNSGL;
|
||||
window->context.destroy = destroyContextNSGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -332,4 +328,3 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
|
||||
|
||||
return window->context.nsgl.object;
|
||||
}
|
||||
|
||||
|
||||
2
glfw/null_init.c
vendored
2
glfw/null_init.c
vendored
@@ -35,7 +35,7 @@
|
||||
int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInitTimerPOSIX();
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
||||
{
|
||||
}
|
||||
|
||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
||||
{
|
||||
return NULL;
|
||||
@@ -58,11 +62,11 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
{
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
48
glfw/null_window.c
vendored
48
glfw/null_window.c
vendored
@@ -34,7 +34,7 @@ static int createNativeWindow(_GLFWwindow* window,
|
||||
window->null.width = wndconfig->width;
|
||||
window->null.height = wndconfig->height;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
if (!createNativeWindow(window, wndconfig))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
@@ -56,18 +56,18 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
@@ -148,6 +148,11 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
*yscale = 1.f;
|
||||
}
|
||||
|
||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||
{
|
||||
}
|
||||
@@ -162,28 +167,28 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -207,7 +212,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
||||
@@ -224,17 +229,22 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||
|
||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
void _glfwPlatformPollEvents(void)
|
||||
@@ -269,12 +279,12 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot, int count)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
||||
{
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
@@ -312,7 +322,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
VkPhysicalDevice device,
|
||||
uint32_t queuefamily)
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
||||
|
||||
39
glfw/osmesa_context.c
vendored
39
glfw/osmesa_context.c
vendored
@@ -100,7 +100,7 @@ static void swapIntervalOSMesa(int interval)
|
||||
static int extensionSupportedOSMesa(const char* extension)
|
||||
{
|
||||
// OSMesa does not have extensions
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ static int extensionSupportedOSMesa(const char* extension)
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void)
|
||||
bool _glfwInitOSMesa(void)
|
||||
{
|
||||
int i;
|
||||
const char* sonames[] =
|
||||
@@ -130,7 +130,7 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
};
|
||||
|
||||
if (_glfw.osmesa.handle)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
for (i = 0; sonames[i]; i++)
|
||||
{
|
||||
@@ -142,7 +142,7 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
if (!_glfw.osmesa.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
||||
@@ -171,10 +171,10 @@ GLFWbool _glfwInitOSMesa(void)
|
||||
"OSMesa: Failed to load required entry points");
|
||||
|
||||
_glfwTerminateOSMesa();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwTerminateOSMesa(void)
|
||||
@@ -193,7 +193,7 @@ void _glfwTerminateOSMesa(void)
|
||||
attribs[index++] = v; \
|
||||
}
|
||||
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
bool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@@ -207,7 +207,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"OSMesa: OpenGL ES is not available on OSMesa");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->share)
|
||||
@@ -240,8 +240,8 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
if (ctxconfig->forward)
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Foward-compatible contexts not supported");
|
||||
return GLFW_FALSE;
|
||||
"OSMesa: Forward-compatible contexts not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
setAttrib(0, 0);
|
||||
@@ -255,7 +255,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: OpenGL profiles unavailable");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
window->context.osmesa.handle =
|
||||
@@ -270,7 +270,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
||||
"OSMesa: Failed to create context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
window->context.makeCurrent = makeContextCurrentOSMesa;
|
||||
@@ -280,7 +280,7 @@ GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
window->context.getProcAddress = getProcAddressOSMesa;
|
||||
window->context.destroy = destroyContextOSMesa;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
@@ -298,7 +298,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
|
||||
if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
@@ -306,7 +306,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve color buffer");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width)
|
||||
@@ -318,7 +318,7 @@ GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
@@ -331,7 +331,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
|
||||
if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
|
||||
&mesaWidth, &mesaHeight,
|
||||
@@ -339,7 +339,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"OSMesa: Failed to retrieve depth buffer");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width)
|
||||
@@ -351,7 +351,7 @@ GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
|
||||
if (buffer)
|
||||
*buffer = mesaBuffer;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||
@@ -367,4 +367,3 @@ GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
|
||||
|
||||
return window->context.osmesa.handle;
|
||||
}
|
||||
|
||||
|
||||
4
glfw/osmesa_context.h
vendored
4
glfw/osmesa_context.h
vendored
@@ -86,9 +86,9 @@ typedef struct _GLFWlibraryOSMesa
|
||||
} _GLFWlibraryOSMesa;
|
||||
|
||||
|
||||
GLFWbool _glfwInitOSMesa(void);
|
||||
bool _glfwInitOSMesa(void);
|
||||
void _glfwTerminateOSMesa(void);
|
||||
GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
bool _glfwCreateContextOSMesa(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig);
|
||||
|
||||
|
||||
26
glfw/posix_thread.c
vendored
26
glfw/posix_thread.c
vendored
@@ -35,19 +35,19 @@
|
||||
////// 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)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"POSIX: Failed to create context TLS");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
tls->posix.allocated = GLFW_TRUE;
|
||||
return GLFW_TRUE;
|
||||
tls->posix.allocated = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
@@ -59,27 +59,27 @@ void _glfwPlatformDestroyTls(_GLFWtls* tls)
|
||||
|
||||
void* _glfwPlatformGetTls(_GLFWtls* tls)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_TRUE);
|
||||
assert(tls->posix.allocated == true);
|
||||
return pthread_getspecific(tls->posix.key);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
|
||||
{
|
||||
assert(tls->posix.allocated == GLFW_TRUE);
|
||||
assert(tls->posix.allocated == true);
|
||||
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)
|
||||
{
|
||||
_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)
|
||||
@@ -91,13 +91,13 @@ void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
|
||||
|
||||
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
assert(mutex->posix.allocated == true);
|
||||
pthread_mutex_lock(&mutex->posix.handle);
|
||||
}
|
||||
|
||||
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
|
||||
{
|
||||
assert(mutex->posix.allocated == GLFW_TRUE);
|
||||
assert(mutex->posix.allocated == true);
|
||||
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
|
||||
{
|
||||
GLFWbool allocated;
|
||||
bool allocated;
|
||||
pthread_key_t key;
|
||||
|
||||
} _GLFWtlsPOSIX;
|
||||
@@ -44,7 +44,7 @@ typedef struct _GLFWtlsPOSIX
|
||||
//
|
||||
typedef struct _GLFWmutexPOSIX
|
||||
{
|
||||
GLFWbool allocated;
|
||||
bool allocated;
|
||||
pthread_mutex_t handle;
|
||||
|
||||
} _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)
|
||||
{
|
||||
_glfw.timer.posix.monotonic = GLFW_TRUE;
|
||||
_glfw.timer.posix.monotonic = true;
|
||||
_glfw.timer.posix.frequency = 1000000000;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
_glfw.timer.posix.monotonic = GLFW_FALSE;
|
||||
_glfw.timer.posix.monotonic = false;
|
||||
_glfw.timer.posix.frequency = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
2
glfw/posix_time.h
vendored
2
glfw/posix_time.h
vendored
@@ -34,7 +34,7 @@
|
||||
//
|
||||
typedef struct _GLFWtimerPOSIX
|
||||
{
|
||||
GLFWbool monotonic;
|
||||
bool monotonic;
|
||||
uint64_t frequency;
|
||||
|
||||
} _GLFWtimerPOSIX;
|
||||
|
||||
@@ -64,14 +64,18 @@
|
||||
"egl_context.h",
|
||||
"osmesa_context.h",
|
||||
"linux_joystick.h",
|
||||
"null_joystick.h"
|
||||
"null_joystick.h",
|
||||
"linux_notify.h",
|
||||
"main_loop.h"
|
||||
],
|
||||
"protocols": [
|
||||
"stable/xdg-shell/xdg-shell.xml",
|
||||
"stable/viewporter/viewporter.xml",
|
||||
"unstable/relative-pointer/relative-pointer-unstable-v1.xml",
|
||||
"unstable/pointer-constraints/pointer-constraints-unstable-v1.xml",
|
||||
"unstable/idle-inhibit/idle-inhibit-unstable-v1.xml"
|
||||
"unstable/idle-inhibit/idle-inhibit-unstable-v1.xml",
|
||||
"unstable/xdg-decoration/xdg-decoration-unstable-v1.xml",
|
||||
"unstable/primary-selection/primary-selection-unstable-v1.xml"
|
||||
],
|
||||
"sources": [
|
||||
"wl_init.c",
|
||||
@@ -86,12 +90,13 @@
|
||||
"osmesa_context.c",
|
||||
"backend_utils.c",
|
||||
"linux_joystick.c",
|
||||
"null_joystick.c"
|
||||
"null_joystick.c",
|
||||
"linux_notify.c"
|
||||
]
|
||||
},
|
||||
"wayland_protocols": [
|
||||
1,
|
||||
12
|
||||
17
|
||||
],
|
||||
"win32": {
|
||||
"headers": [
|
||||
@@ -126,7 +131,9 @@
|
||||
"egl_context.h",
|
||||
"osmesa_context.h",
|
||||
"linux_joystick.h",
|
||||
"null_joystick.h"
|
||||
"null_joystick.h",
|
||||
"linux_notify.h",
|
||||
"main_loop.h"
|
||||
],
|
||||
"sources": [
|
||||
"x11_init.c",
|
||||
@@ -142,7 +149,8 @@
|
||||
"osmesa_context.c",
|
||||
"backend_utils.c",
|
||||
"linux_joystick.c",
|
||||
"null_joystick.c"
|
||||
"null_joystick.c",
|
||||
"linux_notify.c"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
glfw/vulkan.c
vendored
42
glfw/vulkan.c
vendored
@@ -39,14 +39,14 @@
|
||||
////// GLFW internal API //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLFWbool _glfwInitVulkan(int mode)
|
||||
bool _glfwInitVulkan(int mode)
|
||||
{
|
||||
VkResult err;
|
||||
VkExtensionProperties* ep;
|
||||
uint32_t i, count;
|
||||
|
||||
if (_glfw.vk.available)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
#if !defined(_GLFW_VULKAN_STATIC)
|
||||
#if defined(_GLFW_VULKAN_LIBRARY)
|
||||
@@ -63,7 +63,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
if (mode == _GLFW_REQUIRE_LOADER)
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
||||
@@ -74,7 +74,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
"Vulkan: Loader does not export vkGetInstanceProcAddr");
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
|
||||
@@ -85,7 +85,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
"Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
#endif // _GLFW_VULKAN_STATIC
|
||||
|
||||
@@ -101,7 +101,7 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
}
|
||||
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
ep = calloc(count, sizeof(VkExtensionProperties));
|
||||
@@ -115,40 +115,37 @@ GLFWbool _glfwInitVulkan(int mode)
|
||||
|
||||
free(ep);
|
||||
_glfwTerminateVulkan();
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
|
||||
_glfw.vk.KHR_surface = GLFW_TRUE;
|
||||
_glfw.vk.KHR_surface = true;
|
||||
#if defined(_GLFW_WIN32)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
_glfw.vk.KHR_xcb_surface = GLFW_TRUE;
|
||||
_glfw.vk.KHR_xcb_surface = true;
|
||||
#elif defined(_GLFW_WAYLAND)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
|
||||
_glfw.vk.KHR_wayland_surface = GLFW_TRUE;
|
||||
#elif defined(_GLFW_MIR)
|
||||
else if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
|
||||
_glfw.vk.KHR_mir_surface = GLFW_TRUE;
|
||||
_glfw.vk.KHR_wayland_surface = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
free(ep);
|
||||
|
||||
_glfw.vk.available = GLFW_TRUE;
|
||||
_glfw.vk.available = true;
|
||||
|
||||
_glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwTerminateVulkan(void)
|
||||
@@ -221,7 +218,7 @@ const char* _glfwGetVulkanResultString(VkResult result)
|
||||
|
||||
GLFWAPI int glfwVulkanSupported(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
return _glfwInitVulkan(_GLFW_FIND_LOADER);
|
||||
}
|
||||
|
||||
@@ -276,16 +273,16 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
assert(instance != 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))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (!_glfw.vk.extensions[0])
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"Vulkan: Window surface creation extensions not found");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
|
||||
@@ -326,4 +323,3 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
|
||||
|
||||
return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
|
||||
u->stereo = GLFW_TRUE;
|
||||
u->stereo = true;
|
||||
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
u->doublebuffer = true;
|
||||
|
||||
if (_glfw.wgl.ARB_multisample)
|
||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
||||
@@ -135,7 +135,7 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
||||
{
|
||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
||||
u->sRGB = GLFW_TRUE;
|
||||
u->sRGB = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -145,7 +145,7 @@ static int choosePixelFormat(_GLFWwindow* window,
|
||||
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_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;
|
||||
|
||||
if (pfd.dwFlags & PFD_STEREO)
|
||||
u->stereo = GLFW_TRUE;
|
||||
u->stereo = true;
|
||||
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
||||
u->doublebuffer = GLFW_TRUE;
|
||||
u->doublebuffer = true;
|
||||
}
|
||||
|
||||
u->handle = n;
|
||||
@@ -308,7 +308,7 @@ static int extensionSupportedWGL(const char* extension)
|
||||
if (extensions)
|
||||
{
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,11 +318,11 @@ static int extensionSupportedWGL(const char* extension)
|
||||
if (extensions)
|
||||
{
|
||||
if (_glfwStringInExtensionString(extension, extensions))
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static GLFWglproc getProcAddressWGL(const char* procname)
|
||||
@@ -352,21 +352,21 @@ static void destroyContextWGL(_GLFWwindow* window)
|
||||
|
||||
// Initialize WGL
|
||||
//
|
||||
GLFWbool _glfwInitWGL(void)
|
||||
bool _glfwInitWGL(void)
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
HGLRC prc, rc;
|
||||
HDC pdc, dc;
|
||||
|
||||
if (_glfw.wgl.instance)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
|
||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
||||
if (!_glfw.wgl.instance)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to load opengl32.dll");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
||||
@@ -389,7 +389,7 @@ GLFWbool _glfwInitWGL(void)
|
||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
||||
// creation failure occurs during manual pixel format enumeration
|
||||
|
||||
dc = GetDC(_glfw.win32.helperWindowHandle);;
|
||||
dc = GetDC(_glfw.win32.helperWindowHandle);
|
||||
|
||||
ZeroMemory(&pfd, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
@@ -402,7 +402,7 @@ GLFWbool _glfwInitWGL(void)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set pixel format for dummy context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = wglCreateContext(dc);
|
||||
@@ -410,7 +410,7 @@ GLFWbool _glfwInitWGL(void)
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to create dummy context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
pdc = wglGetCurrentDC();
|
||||
@@ -422,7 +422,7 @@ GLFWbool _glfwInitWGL(void)
|
||||
"WGL: Failed to make dummy context current");
|
||||
wglMakeCurrent(pdc, prc);
|
||||
wglDeleteContext(rc);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
||||
@@ -467,7 +467,7 @@ GLFWbool _glfwInitWGL(void)
|
||||
|
||||
wglMakeCurrent(pdc, prc);
|
||||
wglDeleteContext(rc);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Terminate WGL
|
||||
@@ -487,7 +487,7 @@ void _glfwTerminateWGL(void)
|
||||
|
||||
// Create the OpenGL or OpenGL ES context
|
||||
//
|
||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
const _GLFWfbconfig* fbconfig)
|
||||
{
|
||||
@@ -504,26 +504,26 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve DC for window");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
||||
if (!pixelFormat)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
||||
pixelFormat, sizeof(pfd), &pfd))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to retrieve PFD for selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"WGL: Failed to set selected pixel format");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
||||
@@ -534,7 +534,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_VERSION_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,
|
||||
"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,
|
||||
"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 (_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
|
||||
@@ -687,7 +687,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -697,7 +697,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
||||
"WGL: Failed to create OpenGL context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (share)
|
||||
@@ -706,7 +706,7 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||
"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.destroy = destroyContextWGL;
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
#undef setAttrib
|
||||
@@ -741,4 +741,3 @@ GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* 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;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||
GLFWbool EXT_swap_control;
|
||||
GLFWbool EXT_colorspace;
|
||||
GLFWbool ARB_multisample;
|
||||
GLFWbool ARB_framebuffer_sRGB;
|
||||
GLFWbool EXT_framebuffer_sRGB;
|
||||
GLFWbool ARB_pixel_format;
|
||||
GLFWbool ARB_create_context;
|
||||
GLFWbool ARB_create_context_profile;
|
||||
GLFWbool EXT_create_context_es2_profile;
|
||||
GLFWbool ARB_create_context_robustness;
|
||||
GLFWbool ARB_create_context_no_error;
|
||||
GLFWbool ARB_context_flush_control;
|
||||
bool EXT_swap_control;
|
||||
bool EXT_colorspace;
|
||||
bool ARB_multisample;
|
||||
bool ARB_framebuffer_sRGB;
|
||||
bool EXT_framebuffer_sRGB;
|
||||
bool ARB_pixel_format;
|
||||
bool ARB_create_context;
|
||||
bool ARB_create_context_profile;
|
||||
bool EXT_create_context_es2_profile;
|
||||
bool ARB_create_context_robustness;
|
||||
bool ARB_create_context_no_error;
|
||||
bool ARB_context_flush_control;
|
||||
|
||||
} _GLFWlibraryWGL;
|
||||
|
||||
|
||||
GLFWbool _glfwInitWGL(void);
|
||||
bool _glfwInitWGL(void);
|
||||
void _glfwTerminateWGL(void);
|
||||
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
||||
const _GLFWctxconfig* ctxconfig,
|
||||
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);
|
||||
|
||||
513
glfw/win32_monitor.c
vendored
513
glfw/win32_monitor.c
vendored
@@ -1,513 +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);
|
||||
}
|
||||
|
||||
void _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));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
2192
glfw/win32_window.c
vendored
2192
glfw/win32_window.c
vendored
File diff suppressed because it is too large
Load Diff
170
glfw/window.c
vendored
170
glfw/window.c
vendored
@@ -40,7 +40,7 @@
|
||||
|
||||
// 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)
|
||||
window->callbacks.focus((GLFWwindow*) window, focused);
|
||||
@@ -88,8 +88,16 @@ _GLFWwindow* _glfwWindowForId(GLFWid id) {
|
||||
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
|
||||
// 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)
|
||||
{
|
||||
@@ -108,7 +116,7 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
|
||||
|
||||
// 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)
|
||||
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
|
||||
//
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
|
||||
void _glfwInputWindowMaximize(_GLFWwindow* window, bool maximized)
|
||||
{
|
||||
if (window->callbacks.maximize)
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
{
|
||||
window->shouldClose = GLFW_TRUE;
|
||||
window->shouldClose = true;
|
||||
|
||||
if (window->callbacks.close)
|
||||
window->callbacks.close((GLFWwindow*) window);
|
||||
@@ -254,19 +270,17 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
||||
if (window->monitor)
|
||||
{
|
||||
if (wndconfig.centerCursor)
|
||||
{
|
||||
int width, height;
|
||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
||||
}
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wndconfig.visible)
|
||||
{
|
||||
_glfwPlatformShowWindow(window);
|
||||
#ifndef _GLFW_WAYLAND
|
||||
if (wndconfig.focused)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,13 +300,13 @@ void glfwDefaultWindowHints(void)
|
||||
|
||||
// The default is a focused, visible, resizable window with decorations
|
||||
memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
|
||||
_glfw.hints.window.resizable = GLFW_TRUE;
|
||||
_glfw.hints.window.visible = GLFW_TRUE;
|
||||
_glfw.hints.window.decorated = GLFW_TRUE;
|
||||
_glfw.hints.window.focused = GLFW_TRUE;
|
||||
_glfw.hints.window.autoIconify = GLFW_TRUE;
|
||||
_glfw.hints.window.centerCursor = GLFW_TRUE;
|
||||
_glfw.hints.window.focusOnShow = GLFW_TRUE;
|
||||
_glfw.hints.window.resizable = true;
|
||||
_glfw.hints.window.visible = true;
|
||||
_glfw.hints.window.decorated = true;
|
||||
_glfw.hints.window.focused = true;
|
||||
_glfw.hints.window.autoIconify = true;
|
||||
_glfw.hints.window.centerCursor = true;
|
||||
_glfw.hints.window.focusOnShow = true;
|
||||
|
||||
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
|
||||
// double buffered
|
||||
@@ -303,13 +317,13 @@ void glfwDefaultWindowHints(void)
|
||||
_glfw.hints.framebuffer.alphaBits = 8;
|
||||
_glfw.hints.framebuffer.depthBits = 24;
|
||||
_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
|
||||
_glfw.hints.refreshRate = GLFW_DONT_CARE;
|
||||
|
||||
// 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)
|
||||
@@ -352,55 +366,55 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
_glfw.hints.framebuffer.auxBuffers = value;
|
||||
return;
|
||||
case GLFW_STEREO:
|
||||
_glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.framebuffer.stereo = value ? true : false;
|
||||
return;
|
||||
case GLFW_DOUBLEBUFFER:
|
||||
_glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.framebuffer.doublebuffer = value ? true : false;
|
||||
return;
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
_glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.framebuffer.transparent = value ? true : false;
|
||||
return;
|
||||
case GLFW_SAMPLES:
|
||||
_glfw.hints.framebuffer.samples = value;
|
||||
return;
|
||||
case GLFW_SRGB_CAPABLE:
|
||||
_glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.framebuffer.sRGB = value ? true : false;
|
||||
return;
|
||||
case GLFW_RESIZABLE:
|
||||
_glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.resizable = value ? true : false;
|
||||
return;
|
||||
case GLFW_DECORATED:
|
||||
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.decorated = value ? true : false;
|
||||
return;
|
||||
case GLFW_FOCUSED:
|
||||
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.focused = value ? true : false;
|
||||
return;
|
||||
case GLFW_AUTO_ICONIFY:
|
||||
_glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.autoIconify = value ? true : false;
|
||||
return;
|
||||
case GLFW_FLOATING:
|
||||
_glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.floating = value ? true : false;
|
||||
return;
|
||||
case GLFW_MAXIMIZED:
|
||||
_glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.maximized = value ? true : false;
|
||||
return;
|
||||
case GLFW_VISIBLE:
|
||||
_glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.visible = value ? true : false;
|
||||
return;
|
||||
case GLFW_COCOA_RETINA_FRAMEBUFFER:
|
||||
_glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.ns.retina = value ? true : false;
|
||||
return;
|
||||
case GLFW_COCOA_GRAPHICS_SWITCHING:
|
||||
_glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.context.nsgl.offline = value ? true : false;
|
||||
return;
|
||||
case GLFW_SCALE_TO_MONITOR:
|
||||
_glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.scaleToMonitor = value ? true : false;
|
||||
return;
|
||||
case GLFW_CENTER_CURSOR:
|
||||
_glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.centerCursor = value ? true : false;
|
||||
return;
|
||||
case GLFW_FOCUS_ON_SHOW:
|
||||
_glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.window.focusOnShow = value ? true : false;
|
||||
return;
|
||||
case GLFW_CLIENT_API:
|
||||
_glfw.hints.context.client = value;
|
||||
@@ -418,13 +432,13 @@ GLFWAPI void glfwWindowHint(int hint, int value)
|
||||
_glfw.hints.context.robustness = value;
|
||||
return;
|
||||
case GLFW_OPENGL_FORWARD_COMPAT:
|
||||
_glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.context.forward = value ? true : false;
|
||||
return;
|
||||
case GLFW_OPENGL_DEBUG_CONTEXT:
|
||||
_glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.context.debug = value ? true : false;
|
||||
return;
|
||||
case GLFW_CONTEXT_NO_ERROR:
|
||||
_glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
_glfw.hints.context.noerror = value ? true : false;
|
||||
return;
|
||||
case GLFW_OPENGL_PROFILE:
|
||||
_glfw.hints.context.profile = value;
|
||||
@@ -721,6 +735,15 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
|
||||
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
|
||||
}
|
||||
|
||||
GLFWAPI double glfwGetDoubleClickInterval(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.5f);
|
||||
return _glfwPlatformGetDoubleClickInterval(window);
|
||||
}
|
||||
|
||||
GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -792,8 +815,10 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle)
|
||||
|
||||
_glfwPlatformShowWindow(window);
|
||||
|
||||
#ifndef _GLFW_WAYLAND
|
||||
if (window->focusOnShow)
|
||||
_glfwPlatformFocusWindow(window);
|
||||
#endif
|
||||
}
|
||||
|
||||
GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
||||
@@ -811,7 +836,7 @@ GLFWAPI int glfwWindowBell(GLFWwindow* handle)
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
assert(window != NULL);
|
||||
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(false);
|
||||
|
||||
return _glfwPlatformWindowBell(window);
|
||||
}
|
||||
@@ -862,6 +887,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
|
||||
return window->focusOnShow;
|
||||
case GLFW_TRANSPARENT_FRAMEBUFFER:
|
||||
return _glfwPlatformFramebufferTransparent(window);
|
||||
case GLFW_OCCLUDED:
|
||||
return _glfwPlatformWindowOccluded(window);
|
||||
case GLFW_RESIZABLE:
|
||||
return window->resizable;
|
||||
case GLFW_DECORATED:
|
||||
@@ -905,7 +932,7 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
|
||||
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
value = value ? GLFW_TRUE : GLFW_FALSE;
|
||||
value = value ? true : false;
|
||||
|
||||
if (attrib == GLFW_AUTO_ICONIFY)
|
||||
window->autoIconify = value;
|
||||
@@ -990,6 +1017,12 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
|
||||
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)
|
||||
{
|
||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||
@@ -1063,6 +1096,17 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
|
||||
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,
|
||||
GLFWwindowiconifyfun cbfun)
|
||||
{
|
||||
@@ -1096,6 +1140,17 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle
|
||||
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,
|
||||
GLFWwindowcontentscalefun cbfun)
|
||||
{
|
||||
@@ -1107,44 +1162,9 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
|
||||
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)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
if (!_glfw.windowListHead)
|
||||
return;
|
||||
|
||||
_glfwPlatformPostEmptyEvent();
|
||||
}
|
||||
|
||||
226
glfw/wl_init.c
vendored
226
glfw/wl_init.c
vendored
@@ -29,6 +29,8 @@
|
||||
#include "backend_utils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -101,10 +103,10 @@ static void pointerHandleEnter(void* data,
|
||||
_glfw.wl.pointerSerial = serial;
|
||||
_glfw.wl.pointerFocus = window;
|
||||
|
||||
window->wl.hovered = GLFW_TRUE;
|
||||
window->wl.hovered = true;
|
||||
|
||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||
_glfwInputCursorEnter(window, true);
|
||||
}
|
||||
|
||||
static void pointerHandleLeave(void* data,
|
||||
@@ -117,28 +119,22 @@ static void pointerHandleLeave(void* data,
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
window->wl.hovered = GLFW_FALSE;
|
||||
window->wl.hovered = false;
|
||||
|
||||
_glfw.wl.pointerSerial = serial;
|
||||
_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_cursor* cursor;
|
||||
struct wl_cursor_image* image;
|
||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||
|
||||
cursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
||||
name);
|
||||
if (!cursor)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Standard cursor not found");
|
||||
return;
|
||||
}
|
||||
cursor = _glfwLoadCursor(shape);
|
||||
if (!cursor) return;
|
||||
// TODO: handle animated cursors too.
|
||||
image = cursor->images[0];
|
||||
|
||||
@@ -165,56 +161,51 @@ static void pointerHandleMotion(void* data,
|
||||
wl_fixed_t sy)
|
||||
{
|
||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||
const char* cursorName = NULL;
|
||||
GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR;
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||
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)
|
||||
{
|
||||
case mainWindow:
|
||||
_glfwInputCursorPos(window,
|
||||
wl_fixed_to_double(sx),
|
||||
wl_fixed_to_double(sy));
|
||||
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||
return;
|
||||
case topDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
cursorName = "n-resize";
|
||||
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||
else
|
||||
cursorName = "left_ptr";
|
||||
cursorShape = GLFW_ARROW_CURSOR;
|
||||
break;
|
||||
case leftDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
cursorName = "nw-resize";
|
||||
cursorShape = GLFW_NW_RESIZE_CURSOR;
|
||||
else
|
||||
cursorName = "w-resize";
|
||||
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||
break;
|
||||
case rightDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
cursorName = "ne-resize";
|
||||
cursorShape = GLFW_NE_RESIZE_CURSOR;
|
||||
else
|
||||
cursorName = "e-resize";
|
||||
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||
break;
|
||||
case bottomDecoration:
|
||||
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)
|
||||
cursorName = "se-resize";
|
||||
cursorShape = GLFW_SE_RESIZE_CURSOR;
|
||||
else
|
||||
cursorName = "s-resize";
|
||||
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
setCursor(cursorName);
|
||||
setCursor(cursorShape);
|
||||
}
|
||||
|
||||
static void pointerHandleButton(void* data,
|
||||
@@ -227,8 +218,7 @@ static void pointerHandleButton(void* data,
|
||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||
int glfwButton;
|
||||
|
||||
// Both xdg-shell and wl_shell use the same values.
|
||||
uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
|
||||
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
@@ -240,46 +230,40 @@ static void pointerHandleButton(void* data,
|
||||
break;
|
||||
case topDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
edges = WL_SHELL_SURFACE_RESIZE_TOP;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
|
||||
else
|
||||
{
|
||||
if (window->wl.xdg.toplevel)
|
||||
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
|
||||
else
|
||||
wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
|
||||
}
|
||||
break;
|
||||
case leftDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
|
||||
else
|
||||
edges = WL_SHELL_SURFACE_RESIZE_LEFT;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
|
||||
break;
|
||||
case rightDecoration:
|
||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
||||
edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
|
||||
else
|
||||
edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
|
||||
break;
|
||||
case bottomDecoration:
|
||||
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)
|
||||
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
|
||||
else
|
||||
edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
|
||||
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
|
||||
break;
|
||||
default:
|
||||
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,
|
||||
serial, edges);
|
||||
else
|
||||
wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
|
||||
serial, edges);
|
||||
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
|
||||
serial, edges);
|
||||
}
|
||||
}
|
||||
else if (button == BTN_RIGHT)
|
||||
@@ -386,7 +370,7 @@ static void keyboardHandleEnter(void* data,
|
||||
}
|
||||
|
||||
_glfw.wl.keyboardFocus = window;
|
||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
||||
_glfwInputWindowFocus(window, true);
|
||||
}
|
||||
|
||||
static void keyboardHandleLeave(void* data,
|
||||
@@ -400,14 +384,14 @@ static void keyboardHandleLeave(void* data,
|
||||
return;
|
||||
|
||||
_glfw.wl.keyboardFocus = NULL;
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
_glfwInputWindowFocus(window, false);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatchPendingKeyRepeats(id_type timer_id, void *data) {
|
||||
if (_glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return;
|
||||
glfw_xkb_handle_key_event(_glfw.wl.keyRepeatInfo.keyboardFocus, &_glfw.wl.xkb, _glfw.wl.keyRepeatInfo.key, GLFW_REPEAT);
|
||||
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, ((double)_glfw.wl.keyboardRepeatRate) / 1000.0);
|
||||
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (1.0 / (double)_glfw.wl.keyboardRepeatRate));
|
||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
|
||||
}
|
||||
|
||||
@@ -424,12 +408,12 @@ static void keyboardHandleKey(void* data,
|
||||
return;
|
||||
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||
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))
|
||||
{
|
||||
_glfw.wl.keyRepeatInfo.key = key;
|
||||
repeatable = GLFW_TRUE;
|
||||
repeatable = true;
|
||||
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
||||
}
|
||||
if (repeatable) {
|
||||
@@ -542,11 +526,6 @@ static void registryHandleGlobal(void* data,
|
||||
_glfw.wl.shm =
|
||||
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)
|
||||
{
|
||||
_glfwAddOutputWayland(name, version);
|
||||
@@ -561,8 +540,11 @@ static void registryHandleGlobal(void* data,
|
||||
_glfw.wl.seatVersion);
|
||||
wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
|
||||
}
|
||||
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager && !_glfw.wl.dataDevice) {
|
||||
_glfwSetupWaylandDataDevice();
|
||||
if (_glfw.wl.seat) {
|
||||
if (_glfw.wl.dataDeviceManager && !_glfw.wl.dataDevice) _glfwSetupWaylandDataDevice();
|
||||
if (_glfw.wl.primarySelectionDeviceManager && !_glfw.wl.primarySelectionDevice) {
|
||||
_glfwSetupWaylandPrimarySelectionDevice();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(interface, "xdg_wm_base") == 0)
|
||||
@@ -571,6 +553,12 @@ static void registryHandleGlobal(void* data,
|
||||
wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
|
||||
}
|
||||
else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
|
||||
{
|
||||
_glfw.wl.decorationManager =
|
||||
wl_registry_bind(registry, name,
|
||||
&zxdg_decoration_manager_v1_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "wp_viewporter") == 0)
|
||||
{
|
||||
_glfw.wl.viewporter =
|
||||
@@ -607,6 +595,17 @@ static void registryHandleGlobal(void* data,
|
||||
_glfwSetupWaylandDataDevice();
|
||||
}
|
||||
}
|
||||
else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0 ||
|
||||
strcmp(interface, "gtk_primary_selection_device_manager") == 0)
|
||||
{
|
||||
_glfw.wl.primarySelectionDeviceManager =
|
||||
wl_registry_bind(registry, name,
|
||||
&zwp_primary_selection_device_manager_v1_interface,
|
||||
1);
|
||||
if (_glfw.wl.seat && _glfw.wl.primarySelectionDeviceManager && !_glfw.wl.primarySelectionDevice) {
|
||||
_glfwSetupWaylandPrimarySelectionDevice();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -614,14 +613,20 @@ static void registryHandleGlobalRemove(void *data,
|
||||
struct wl_registry *registry,
|
||||
uint32_t name)
|
||||
{
|
||||
int i;
|
||||
_GLFWmonitor* monitor;
|
||||
|
||||
for (i = 0; i < _glfw.monitorCount; ++i)
|
||||
for (int i = 0; i < _glfw.monitorCount; ++i)
|
||||
{
|
||||
monitor = _glfw.monitors[i];
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@@ -635,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 //////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -645,7 +683,7 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: failed to create self pipe");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
||||
@@ -653,7 +691,7 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to open libwayland-cursor");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
|
||||
@@ -670,7 +708,7 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to open libwayland-egl");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
|
||||
@@ -685,17 +723,17 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"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));
|
||||
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.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, animateCursorImage, 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, true, animateCursorImage, NULL, NULL);
|
||||
|
||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||
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
|
||||
wl_display_roundtrip(_glfw.wl.display);
|
||||
@@ -706,26 +744,42 @@ int _glfwPlatformInit(void)
|
||||
#ifdef __linux__
|
||||
if (_glfw.hints.init.enableJoysticks) {
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
if (_glfw.wl.pointer && _glfw.wl.shm)
|
||||
if (!_glfw.wl.wmBase)
|
||||
{
|
||||
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Failed to find xdg-shell in your compositor");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_glfw.wl.shm)
|
||||
{
|
||||
const char *cursorTheme = getenv("XCURSOR_THEME"), *cursorSizeStr = getenv("XCURSOR_SIZE");
|
||||
char *cursorSizeEnd;
|
||||
int cursorSize = 32;
|
||||
if (cursorSizeStr)
|
||||
{
|
||||
errno = 0;
|
||||
long cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
|
||||
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
|
||||
cursorSize = (int)cursorSizeLong;
|
||||
}
|
||||
_glfw.wl.cursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
|
||||
if (!_glfw.wl.cursorTheme)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Unable to load default cursor theme");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
_glfw.wl.cursorSurface =
|
||||
wl_compositor_create_surface(_glfw.wl.compositor);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
@@ -759,10 +813,10 @@ void _glfwPlatformTerminate(void)
|
||||
wl_compositor_destroy(_glfw.wl.compositor);
|
||||
if (_glfw.wl.shm)
|
||||
wl_shm_destroy(_glfw.wl.shm);
|
||||
if (_glfw.wl.shell)
|
||||
wl_shell_destroy(_glfw.wl.shell);
|
||||
if (_glfw.wl.viewporter)
|
||||
wp_viewporter_destroy(_glfw.wl.viewporter);
|
||||
if (_glfw.wl.decorationManager)
|
||||
zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
|
||||
if (_glfw.wl.wmBase)
|
||||
xdg_wm_base_destroy(_glfw.wl.wmBase);
|
||||
if (_glfw.wl.pointer)
|
||||
@@ -788,6 +842,10 @@ void _glfwPlatformTerminate(void)
|
||||
wl_data_device_destroy(_glfw.wl.dataDevice);
|
||||
if (_glfw.wl.dataDeviceManager)
|
||||
wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
|
||||
if (_glfw.wl.primarySelectionDevice)
|
||||
zwp_primary_selection_device_v1_destroy(_glfw.wl.primarySelectionDevice);
|
||||
if (_glfw.wl.primarySelectionDeviceManager)
|
||||
zwp_primary_selection_device_manager_v1_destroy(_glfw.wl.primarySelectionDeviceManager);
|
||||
if (_glfw.wl.registry)
|
||||
wl_registry_destroy(_glfw.wl.registry);
|
||||
if (_glfw.wl.display)
|
||||
@@ -797,13 +855,14 @@ void _glfwPlatformTerminate(void)
|
||||
}
|
||||
closeFds(_glfw.wl.eventLoopData.wakeupFds, sizeof(_glfw.wl.eventLoopData.wakeupFds)/sizeof(_glfw.wl.eventLoopData.wakeupFds[0]));
|
||||
free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL;
|
||||
free(_glfw.wl.clipboardSourceString); _glfw.wl.clipboardSourceString = NULL;
|
||||
free(_glfw.wl.primarySelectionString); _glfw.wl.primarySelectionString = NULL;
|
||||
free(_glfw.wl.pasteString); _glfw.wl.pasteString = NULL;
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
" clock_gettime"
|
||||
#else
|
||||
@@ -815,3 +874,6 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#define GLFW_LOOP_BACKEND wl
|
||||
#include "main_loop.h"
|
||||
|
||||
80
glfw/wl_monitor.c
vendored
80
glfw/wl_monitor.c
vendored
@@ -30,18 +30,19 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
static void geometry(void* data,
|
||||
struct wl_output* output,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t physicalWidth,
|
||||
int32_t physicalHeight,
|
||||
int32_t subpixel,
|
||||
const char* make,
|
||||
const char* model,
|
||||
int32_t transform)
|
||||
static void outputHandleGeometry(void* data,
|
||||
struct wl_output* output,
|
||||
int32_t x,
|
||||
int32_t y,
|
||||
int32_t physicalWidth,
|
||||
int32_t physicalHeight,
|
||||
int32_t subpixel,
|
||||
const char* make,
|
||||
const char* model,
|
||||
int32_t transform)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
char name[1024];
|
||||
@@ -55,12 +56,12 @@ static void geometry(void* data,
|
||||
monitor->name = _glfw_strdup(name);
|
||||
}
|
||||
|
||||
static void mode(void* data,
|
||||
struct wl_output* output,
|
||||
uint32_t flags,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int32_t refresh)
|
||||
static void outputHandleMode(void* data,
|
||||
struct wl_output* output,
|
||||
uint32_t flags,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int32_t refresh)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
GLFWvidmode mode;
|
||||
@@ -70,7 +71,7 @@ static void mode(void* data,
|
||||
mode.redBits = 8;
|
||||
mode.greenBits = 8;
|
||||
mode.blueBits = 8;
|
||||
mode.refreshRate = refresh / 1000;
|
||||
mode.refreshRate = (int)round(refresh / 1000.0);
|
||||
|
||||
monitor->modeCount++;
|
||||
monitor->modes =
|
||||
@@ -81,27 +82,30 @@ static void mode(void* data,
|
||||
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||
}
|
||||
|
||||
static void done(void* data, struct wl_output* output)
|
||||
static void outputHandleDone(void* data, struct wl_output* output)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void scale(void* data,
|
||||
struct wl_output* output,
|
||||
int32_t factor)
|
||||
static void outputHandleScale(void* data,
|
||||
struct wl_output* output,
|
||||
int32_t factor)
|
||||
{
|
||||
struct _GLFWmonitor *monitor = data;
|
||||
|
||||
monitor->wl.scale = factor;
|
||||
if (factor > 0 && factor < 24)
|
||||
monitor->wl.scale = factor;
|
||||
}
|
||||
|
||||
static const struct wl_output_listener outputListener = {
|
||||
geometry,
|
||||
mode,
|
||||
done,
|
||||
scale,
|
||||
outputHandleGeometry,
|
||||
outputHandleMode,
|
||||
outputHandleDone,
|
||||
outputHandleScale,
|
||||
};
|
||||
|
||||
|
||||
@@ -169,6 +173,18 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
*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)
|
||||
{
|
||||
*found = monitor->modeCount;
|
||||
@@ -180,18 +196,17 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
*mode = monitor->modes[monitor->wl.currentMode];
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Gamma ramp getting not supported yet");
|
||||
"Wayland: Gamma ramp access is not available");
|
||||
return false;
|
||||
}
|
||||
|
||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
{
|
||||
// TODO
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Wayland: Gamma ramp setting not supported yet");
|
||||
"Wayland: Gamma ramp access is not available");
|
||||
}
|
||||
|
||||
|
||||
@@ -205,4 +220,3 @@ GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return monitor->wl.output;
|
||||
}
|
||||
|
||||
|
||||
59
glfw/wl_platform.h
vendored
59
glfw/wl_platform.h
vendored
@@ -56,9 +56,11 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
||||
|
||||
#include "wayland-xdg-shell-client-protocol.h"
|
||||
#include "wayland-viewporter-client-protocol.h"
|
||||
#include "wayland-xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
|
||||
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "wayland-primary-selection-unstable-v1-client-protocol.h"
|
||||
|
||||
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
|
||||
#define _glfw_dlclose(handle) dlclose(handle)
|
||||
@@ -131,18 +133,18 @@ typedef struct _GLFWdecorationWayland
|
||||
typedef struct _GLFWwindowWayland
|
||||
{
|
||||
int width, height;
|
||||
GLFWbool visible;
|
||||
GLFWbool maximized;
|
||||
GLFWbool hovered;
|
||||
GLFWbool transparent;
|
||||
bool visible;
|
||||
bool maximized;
|
||||
bool hovered;
|
||||
bool transparent;
|
||||
struct wl_surface* surface;
|
||||
struct wl_egl_window* native;
|
||||
struct wl_shell_surface* shellSurface;
|
||||
struct wl_callback* callback;
|
||||
|
||||
struct {
|
||||
struct xdg_surface* surface;
|
||||
struct xdg_toplevel* toplevel;
|
||||
struct zxdg_toplevel_decoration_v1* decoration;
|
||||
} xdg;
|
||||
|
||||
_GLFWcursor* currentCursor;
|
||||
@@ -165,22 +167,37 @@ typedef struct _GLFWwindowWayland
|
||||
|
||||
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||
|
||||
// This is a hack to prevent auto-iconification on creation.
|
||||
GLFWbool justCreated;
|
||||
bool fullscreened;
|
||||
|
||||
struct {
|
||||
bool serverSide;
|
||||
struct wl_buffer* buffer;
|
||||
_GLFWdecorationWayland top, left, right, bottom;
|
||||
int focus;
|
||||
} decorations;
|
||||
|
||||
struct {
|
||||
unsigned long long id;
|
||||
void(*callback)(unsigned long long id);
|
||||
struct wl_callback *current_wl_callback;
|
||||
} frameCallbackData;
|
||||
|
||||
|
||||
} _GLFWwindowWayland;
|
||||
|
||||
typedef enum _GLFWWaylandOfferType
|
||||
{
|
||||
EXPIRED,
|
||||
CLIPBOARD,
|
||||
DRAG_AND_DROP,
|
||||
PRIMARY_SELECTION
|
||||
}_GLFWWaylandOfferType ;
|
||||
|
||||
typedef struct _GLFWWaylandDataOffer
|
||||
{
|
||||
struct wl_data_offer *id;
|
||||
const char *mime;
|
||||
int offer_type;
|
||||
_GLFWWaylandOfferType offer_type;
|
||||
size_t idx;
|
||||
int is_self_offer;
|
||||
int has_uri_list;
|
||||
@@ -189,6 +206,17 @@ typedef struct _GLFWWaylandDataOffer
|
||||
struct wl_surface *surface;
|
||||
} _GLFWWaylandDataOffer;
|
||||
|
||||
typedef struct _GLFWWaylandPrimaryOffer
|
||||
{
|
||||
struct zwp_primary_selection_offer_v1 *id;
|
||||
const char *mime;
|
||||
_GLFWWaylandOfferType offer_type;
|
||||
size_t idx;
|
||||
int is_self_offer;
|
||||
int has_uri_list;
|
||||
struct wl_surface *surface;
|
||||
} _GLFWWaylandPrimaryOffer;
|
||||
|
||||
// Wayland-specific global data
|
||||
//
|
||||
typedef struct _GLFWlibraryWayland
|
||||
@@ -197,12 +225,12 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_registry* registry;
|
||||
struct wl_compositor* compositor;
|
||||
struct wl_subcompositor* subcompositor;
|
||||
struct wl_shell* shell;
|
||||
struct wl_shm* shm;
|
||||
struct wl_seat* seat;
|
||||
struct wl_pointer* pointer;
|
||||
struct wl_keyboard* keyboard;
|
||||
struct xdg_wm_base* wmBase;
|
||||
struct zxdg_decoration_manager_v1* decorationManager;
|
||||
struct wp_viewporter* viewporter;
|
||||
struct zwp_relative_pointer_manager_v1* relativePointerManager;
|
||||
struct zwp_pointer_constraints_v1* pointerConstraints;
|
||||
@@ -210,6 +238,9 @@ typedef struct _GLFWlibraryWayland
|
||||
struct wl_data_device_manager* dataDeviceManager;
|
||||
struct wl_data_device* dataDevice;
|
||||
struct wl_data_source* dataSourceForClipboard;
|
||||
struct zwp_primary_selection_device_manager_v1* primarySelectionDeviceManager;
|
||||
struct zwp_primary_selection_device_v1* primarySelectionDevice;
|
||||
struct zwp_primary_selection_source_v1* dataSourceForPrimarySelection;
|
||||
|
||||
int compositorVersion;
|
||||
int seatVersion;
|
||||
@@ -250,11 +281,13 @@ typedef struct _GLFWlibraryWayland
|
||||
} egl;
|
||||
|
||||
EventLoopData eventLoopData;
|
||||
char* pasteString;
|
||||
char* clipboardString;
|
||||
char* clipboardSourceString;
|
||||
struct wl_data_offer* clipboardSourceOffer;
|
||||
size_t dataOffersCounter;
|
||||
_GLFWWaylandDataOffer dataOffers[8];
|
||||
char* primarySelectionString;
|
||||
size_t primarySelectionOffersCounter;
|
||||
_GLFWWaylandPrimaryOffer primarySelectionOffers[8];
|
||||
} _GLFWlibraryWayland;
|
||||
|
||||
// Wayland-specific per-monitor data
|
||||
@@ -284,5 +317,7 @@ typedef struct _GLFWcursorWayland
|
||||
|
||||
|
||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||
void _glfwSetupWaylandDataDevice();
|
||||
void _glfwSetupWaylandDataDevice(void);
|
||||
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
||||
void animateCursorImage(id_type timer_id, void *data);
|
||||
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape);
|
||||
|
||||
1049
glfw/wl_window.c
vendored
1049
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");
|
||||
_glfw.x11.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 =
|
||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW");
|
||||
_glfw.x11.NET_FRAME_EXTENTS =
|
||||
@@ -150,7 +154,7 @@ static void detectEWMH(void)
|
||||
|
||||
// Look for and initialize supported X11 extensions
|
||||
//
|
||||
static GLFWbool initExtensions(void)
|
||||
static bool initExtensions(void)
|
||||
{
|
||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
||||
if (_glfw.x11.vidmode.handle)
|
||||
@@ -195,7 +199,7 @@ static GLFWbool initExtensions(void)
|
||||
&_glfw.x11.xi.major,
|
||||
&_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
|
||||
if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)
|
||||
_glfw.x11.randr.available = GLFW_TRUE;
|
||||
_glfw.x11.randr.available = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -273,14 +277,14 @@ static GLFWbool initExtensions(void)
|
||||
{
|
||||
// This is likely an older Nvidia driver with broken gamma support
|
||||
// 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)
|
||||
{
|
||||
// A system without CRTCs is likely a system with broken RandR
|
||||
// Disable the RandR monitor path and fall back to core functions
|
||||
_glfw.x11.randr.monitorBroken = GLFW_TRUE;
|
||||
_glfw.x11.randr.monitorBroken = true;
|
||||
}
|
||||
|
||||
XRRFreeScreenResources(sr);
|
||||
@@ -326,7 +330,7 @@ static GLFWbool initExtensions(void)
|
||||
&_glfw.x11.xinerama.minor))
|
||||
{
|
||||
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.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)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to load Xkb extension");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
Bool supported;
|
||||
if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &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_create_context(&_glfw.x11.xkb)) return GLFW_FALSE;
|
||||
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return GLFW_FALSE;
|
||||
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return GLFW_FALSE;
|
||||
if (!glfw_xkb_set_x11_events_mask()) return false;
|
||||
if (!glfw_xkb_create_context(&_glfw.x11.xkb)) return false;
|
||||
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return false;
|
||||
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return false;
|
||||
|
||||
// Detect whether an EWMH-conformant window manager is running
|
||||
detectEWMH();
|
||||
@@ -453,12 +457,12 @@ static GLFWbool initExtensions(void)
|
||||
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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
|
||||
// for which monitor a window is considered to be on
|
||||
@@ -620,7 +624,7 @@ int _glfwPlatformInit(void)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: failed to create self pipe");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
_glfw.x11.display = XOpenDisplay(NULL);
|
||||
@@ -638,7 +642,7 @@ int _glfwPlatformInit(void)
|
||||
"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));
|
||||
@@ -650,10 +654,10 @@ int _glfwPlatformInit(void)
|
||||
_glfw.x11.RESOURCE_MANAGER = XInternAtom(_glfw.x11.display, "RESOURCE_MANAGER", True);
|
||||
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())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
_glfw.x11.helperWindowHandle = createHelperWindow();
|
||||
_glfw.x11.hiddenCursorHandle = createHiddenCursor();
|
||||
@@ -661,7 +665,7 @@ int _glfwPlatformInit(void)
|
||||
#if defined(__linux__)
|
||||
if (_glfw.hints.init.enableJoysticks) {
|
||||
if (!_glfwInitJoysticksLinux())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (_glfw.linjs.inotify > 0)
|
||||
addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL);
|
||||
}
|
||||
@@ -670,11 +674,12 @@ int _glfwPlatformInit(void)
|
||||
_glfwInitTimerPOSIX();
|
||||
|
||||
_glfwPollMonitorsX11();
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformTerminate(void)
|
||||
{
|
||||
removeAllTimers(&_glfw.x11.eventLoopData);
|
||||
if (_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
|
||||
@@ -754,7 +759,7 @@ void _glfwPlatformTerminate(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)
|
||||
" clock_gettime"
|
||||
#else
|
||||
@@ -768,3 +773,5 @@ const char* _glfwPlatformGetVersionString(void)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#include "main_loop.h"
|
||||
|
||||
113
glfw/x11_monitor.c
vendored
113
glfw/x11_monitor.c
vendored
@@ -30,11 +30,12 @@
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -44,7 +45,7 @@ static GLFWbool modeIsGood(const XRRModeInfo* mi)
|
||||
static int calculateRefreshRate(const XRRModeInfo* mi)
|
||||
{
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
@@ -348,6 +349,100 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
||||
*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* result;
|
||||
@@ -433,7 +528,7 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
||||
}
|
||||
}
|
||||
|
||||
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
{
|
||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||
{
|
||||
@@ -449,6 +544,7 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
memcpy(ramp->blue, gamma->blue, size * sizeof(unsigned short));
|
||||
|
||||
XRRFreeGamma(gamma);
|
||||
return true;
|
||||
}
|
||||
else if (_glfw.x11.vidmode.available)
|
||||
{
|
||||
@@ -460,6 +556,13 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||
XF86VidModeGetGammaRamp(_glfw.x11.display,
|
||||
_glfw.x11.screen,
|
||||
ramp->size, ramp->red, ramp->green, ramp->blue);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Gamma ramp access not supported by server");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,6 +595,10 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||
(unsigned short*) ramp->green,
|
||||
(unsigned short*) ramp->blue);
|
||||
}
|
||||
else {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Gamma ramp access not supported by server");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
30
glfw/x11_platform.h
vendored
30
glfw/x11_platform.h
vendored
@@ -182,12 +182,11 @@ typedef struct _GLFWwindowX11
|
||||
Colormap colormap;
|
||||
Window handle;
|
||||
|
||||
GLFWbool overrideRedirect;
|
||||
GLFWbool iconified;
|
||||
GLFWbool maximized;
|
||||
bool iconified;
|
||||
bool maximized;
|
||||
|
||||
// Whether the visual supports framebuffer transparency
|
||||
GLFWbool transparent;
|
||||
bool transparent;
|
||||
|
||||
// Cached position and size used to filter out duplicate events
|
||||
int width, height;
|
||||
@@ -198,9 +197,6 @@ typedef struct _GLFWwindowX11
|
||||
// The last position the cursor was warped to by GLFW
|
||||
int warpCursorPosX, warpCursorPosY;
|
||||
|
||||
// The time of the last KeyPress event
|
||||
Time lastKeyTime;
|
||||
|
||||
} _GLFWwindowX11;
|
||||
|
||||
// X11-specific global data
|
||||
@@ -251,6 +247,8 @@ typedef struct _GLFWlibraryX11
|
||||
Atom NET_WM_FULLSCREEN_MONITORS;
|
||||
Atom NET_WM_WINDOW_OPACITY;
|
||||
Atom NET_WM_CM_Sx;
|
||||
Atom NET_WORKAREA;
|
||||
Atom NET_CURRENT_DESKTOP;
|
||||
Atom NET_ACTIVE_WINDOW;
|
||||
Atom NET_FRAME_EXTENTS;
|
||||
Atom NET_REQUEST_FRAME_EXTENTS;
|
||||
@@ -286,14 +284,14 @@ typedef struct _GLFWlibraryX11
|
||||
Atom RESOURCE_MANAGER;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
int eventBase;
|
||||
int errorBase;
|
||||
int major;
|
||||
int minor;
|
||||
GLFWbool gammaBroken;
|
||||
GLFWbool monitorBroken;
|
||||
bool gammaBroken;
|
||||
bool monitorBroken;
|
||||
PFN_XRRAllocGamma AllocGamma;
|
||||
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
||||
PFN_XRRFreeGamma FreeGamma;
|
||||
@@ -338,7 +336,7 @@ typedef struct _GLFWlibraryX11
|
||||
} xcursor;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
int major;
|
||||
int minor;
|
||||
@@ -348,7 +346,7 @@ typedef struct _GLFWlibraryX11
|
||||
} xinerama;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
int eventBase;
|
||||
int errorBase;
|
||||
@@ -359,7 +357,7 @@ typedef struct _GLFWlibraryX11
|
||||
} vidmode;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
int majorOpcode;
|
||||
int eventBase;
|
||||
@@ -371,7 +369,7 @@ typedef struct _GLFWlibraryX11
|
||||
} xi;
|
||||
|
||||
struct {
|
||||
GLFWbool available;
|
||||
bool available;
|
||||
void* handle;
|
||||
int major;
|
||||
int minor;
|
||||
@@ -418,11 +416,11 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
||||
Atom property,
|
||||
Atom type,
|
||||
unsigned char** value);
|
||||
GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
|
||||
bool _glfwIsVisualTransparentX11(Visual* visual);
|
||||
|
||||
void _glfwGrabErrorHandlerX11(void);
|
||||
void _glfwReleaseErrorHandlerX11(void);
|
||||
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);
|
||||
|
||||
490
glfw/x11_window.c
vendored
490
glfw/x11_window.c
vendored
@@ -28,6 +28,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "internal.h"
|
||||
#include "backend_utils.h"
|
||||
#include "linux_notify.h"
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xmd.h>
|
||||
@@ -54,32 +55,40 @@
|
||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||
// covers GLX functions
|
||||
//
|
||||
GLFWbool _glfwDispatchX11Events(void);
|
||||
static unsigned _glfwDispatchX11Events(void);
|
||||
|
||||
static void
|
||||
handleEvents(double timeout) {
|
||||
EVDBG("starting handleEvents(%.2f)", 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_dbus_session_bus_dispatch();
|
||||
EVDBG("other dispatch done");
|
||||
}
|
||||
|
||||
static GLFWbool
|
||||
static bool
|
||||
waitForX11Event(double timeout) {
|
||||
// returns true iff there is X11 data waiting to be read, does not run watches and timers
|
||||
double end_time = glfwGetTime() + timeout;
|
||||
while(GLFW_TRUE) {
|
||||
while(true) {
|
||||
if (timeout >= 0) {
|
||||
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();
|
||||
if (timeout <= 0) return GLFW_FALSE;
|
||||
if (timeout <= 0) return false;
|
||||
if (result < 0 && (errno == EINTR || errno == EAGAIN)) continue;
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
} else {
|
||||
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;
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,7 +96,7 @@ waitForX11Event(double timeout) {
|
||||
// Waits until a VisibilityNotify event arrives for the specified window or the
|
||||
// timeout period elapses (ICCCM section 4.2.2)
|
||||
//
|
||||
static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
||||
static bool waitForVisibilityNotify(_GLFWwindow* window)
|
||||
{
|
||||
XEvent dummy;
|
||||
|
||||
@@ -97,10 +106,10 @@ static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
|
||||
&dummy))
|
||||
{
|
||||
if (!waitForX11Event(0.1))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns whether the window is iconified
|
||||
@@ -256,6 +265,76 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
|
||||
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
|
||||
//
|
||||
static void updateWindowMode(_GLFWwindow* window)
|
||||
@@ -274,43 +353,8 @@ static void updateWindowMode(_GLFWwindow* window)
|
||||
0);
|
||||
}
|
||||
|
||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||
{
|
||||
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
|
||||
set_fullscreen(window, true);
|
||||
|
||||
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
|
||||
{
|
||||
@@ -321,32 +365,8 @@ static void updateWindowMode(_GLFWwindow* window)
|
||||
_glfw.x11.NET_WM_FULLSCREEN_MONITORS);
|
||||
}
|
||||
|
||||
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
|
||||
{
|
||||
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);
|
||||
set_fullscreen(window, false);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
//
|
||||
static void updateCursorImage(_GLFWwindow* window)
|
||||
@@ -453,7 +464,7 @@ static void disableCursor(_GLFWwindow* window)
|
||||
&_glfw.x11.restoreCursorPosX,
|
||||
&_glfw.x11.restoreCursorPosY);
|
||||
updateCursorImage(window);
|
||||
centerCursor(window);
|
||||
_glfwCenterCursorInContentArea(window);
|
||||
XGrabPointer(_glfw.x11.display, window->x11.handle, True,
|
||||
ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
@@ -488,7 +499,7 @@ static void enableCursor(_GLFWwindow* window)
|
||||
|
||||
// Create the X11 window (and its colormap)
|
||||
//
|
||||
static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
static bool createNativeWindow(_GLFWwindow* window,
|
||||
const _GLFWwndconfig* wndconfig,
|
||||
Visual* visual, int depth)
|
||||
{
|
||||
@@ -540,7 +551,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to create window");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
XSaveContext(_glfw.x11.display,
|
||||
@@ -550,7 +561,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
if (!wndconfig->decorated)
|
||||
_glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
|
||||
_glfwPlatformSetWindowDecorated(window, false);
|
||||
|
||||
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_HORZ;
|
||||
window->x11.maximized = GLFW_TRUE;
|
||||
window->x11.maximized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,7 +630,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
{
|
||||
_glfwInputError(GLFW_OUT_OF_MEMORY,
|
||||
"X11: Failed to allocate WM hints");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
hints->flags = StateHint;
|
||||
@@ -673,7 +684,7 @@ static GLFWbool createNativeWindow(_GLFWwindow* window,
|
||||
_glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
|
||||
_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
|
||||
@@ -873,6 +884,7 @@ static const char* getSelectionString(Atom selection)
|
||||
Atom actualType;
|
||||
int actualFormat;
|
||||
unsigned long itemCount, bytesAfter;
|
||||
double start = glfwGetTime();
|
||||
XEvent notification, dummy;
|
||||
|
||||
XConvertSelection(_glfw.x11.display,
|
||||
@@ -887,7 +899,10 @@ static const char* getSelectionString(Atom selection)
|
||||
SelectionNotify,
|
||||
¬ification))
|
||||
{
|
||||
waitForX11Event(-1);
|
||||
double time = glfwGetTime();
|
||||
if (time - start > 2)
|
||||
return "";
|
||||
waitForX11Event(2.0 - (time - start));
|
||||
}
|
||||
|
||||
if (notification.xselection.property == None)
|
||||
@@ -918,12 +933,16 @@ static const char* getSelectionString(Atom selection)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
start = glfwGetTime();
|
||||
while (!XCheckIfEvent(_glfw.x11.display,
|
||||
&dummy,
|
||||
isSelPropNewValueNotify,
|
||||
(XPointer) ¬ification))
|
||||
{
|
||||
waitForX11Event(-1);
|
||||
double time = glfwGetTime();
|
||||
if (time - start > 2)
|
||||
return "";
|
||||
waitForX11Event(2.0 - (time - start));
|
||||
}
|
||||
|
||||
XFree(data);
|
||||
@@ -1008,19 +1027,6 @@ static void acquireMonitor(_GLFWwindow* window)
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
@@ -1047,10 +1053,10 @@ static void releaseMonitor(_GLFWwindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
static void onConfigChange()
|
||||
static void onConfigChange(void)
|
||||
{
|
||||
float xscale, yscale;
|
||||
_glfwGetSystemContentScaleX11(&xscale, &yscale, GLFW_TRUE);
|
||||
_glfwGetSystemContentScaleX11(&xscale, &yscale, true);
|
||||
|
||||
if (xscale != _glfw.x11.contentScaleX || yscale != _glfw.x11.contentScaleY)
|
||||
{
|
||||
@@ -1070,7 +1076,8 @@ static void onConfigChange()
|
||||
static void processEvent(XEvent *event)
|
||||
{
|
||||
_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)
|
||||
{
|
||||
@@ -1146,11 +1153,12 @@ static void processEvent(XEvent *event)
|
||||
/* fallthrough */
|
||||
case XkbMapNotify:
|
||||
{
|
||||
glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL);
|
||||
keymap_dirty = true;
|
||||
return;
|
||||
}
|
||||
case XkbStateNotify:
|
||||
{
|
||||
UPDATE_KEYMAP_IF_NEEDED;
|
||||
XkbStateNotifyEvent *state_event = (XkbStateNotifyEvent*)kb_event;
|
||||
glfw_xkb_update_modifiers(
|
||||
&_glfw.x11.xkb, state_event->base_mods, state_event->latched_mods,
|
||||
@@ -1175,12 +1183,14 @@ static void processEvent(XEvent *event)
|
||||
{
|
||||
case KeyPress:
|
||||
{
|
||||
UPDATE_KEYMAP_IF_NEEDED;
|
||||
glfw_xkb_handle_key_event(window, &_glfw.x11.xkb, event->xkey.keycode, GLFW_PRESS);
|
||||
return;
|
||||
}
|
||||
|
||||
case KeyRelease:
|
||||
{
|
||||
UPDATE_KEYMAP_IF_NEEDED;
|
||||
if (!_glfw.x11.xkb.detectable)
|
||||
{
|
||||
// HACK: Key repeat events will arrive as KeyRelease/KeyPress
|
||||
@@ -1291,18 +1301,26 @@ static void processEvent(XEvent *event)
|
||||
|
||||
case EnterNotify:
|
||||
{
|
||||
// XEnterWindowEvent is XCrossingEvent
|
||||
const int x = event->xcrossing.x;
|
||||
const int y = event->xcrossing.y;
|
||||
|
||||
// HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
|
||||
// ignore the defined cursor for hidden cursor mode
|
||||
if (window->cursorMode == GLFW_CURSOR_HIDDEN)
|
||||
updateCursorImage(window);
|
||||
|
||||
_glfwInputCursorEnter(window, GLFW_TRUE);
|
||||
_glfwInputCursorEnter(window, true);
|
||||
_glfwInputCursorPos(window, x, y);
|
||||
|
||||
window->x11.lastCursorPosX = x;
|
||||
window->x11.lastCursorPosY = y;
|
||||
return;
|
||||
}
|
||||
|
||||
case LeaveNotify:
|
||||
{
|
||||
_glfwInputCursorEnter(window, GLFW_FALSE);
|
||||
_glfwInputCursorEnter(window, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1359,7 +1377,7 @@ static void processEvent(XEvent *event)
|
||||
if (event->xconfigure.x != window->x11.xpos ||
|
||||
event->xconfigure.y != window->x11.ypos)
|
||||
{
|
||||
if (window->x11.overrideRedirect || event->xany.send_event)
|
||||
if (event->xany.send_event)
|
||||
{
|
||||
_glfwInputWindowPos(window,
|
||||
event->xconfigure.x,
|
||||
@@ -1377,9 +1395,6 @@ static void processEvent(XEvent *event)
|
||||
{
|
||||
// Custom client message, probably from the window manager
|
||||
|
||||
if (filtered)
|
||||
return;
|
||||
|
||||
if (event->xclient.message_type == None)
|
||||
return;
|
||||
|
||||
@@ -1415,7 +1430,7 @@ static void processEvent(XEvent *event)
|
||||
// A drag operation has entered the window
|
||||
unsigned long i, count;
|
||||
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.version = event->xclient.data.l[1] >> 24;
|
||||
@@ -1597,7 +1612,7 @@ static void processEvent(XEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
_glfwInputWindowFocus(window, GLFW_TRUE);
|
||||
_glfwInputWindowFocus(window, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1617,7 +1632,7 @@ static void processEvent(XEvent *event)
|
||||
if (window->monitor && window->autoIconify)
|
||||
_glfwPlatformIconifyWindow(window);
|
||||
|
||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||
_glfwInputWindowFocus(window, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1638,7 +1653,7 @@ static void processEvent(XEvent *event)
|
||||
if (state != IconicState && state != NormalState)
|
||||
return;
|
||||
|
||||
const GLFWbool iconified = (state == IconicState);
|
||||
const bool iconified = (state == IconicState);
|
||||
if (window->x11.iconified != iconified)
|
||||
{
|
||||
if (window->monitor)
|
||||
@@ -1655,7 +1670,7 @@ static void processEvent(XEvent *event)
|
||||
}
|
||||
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)
|
||||
{
|
||||
window->x11.maximized = maximized;
|
||||
@@ -1669,6 +1684,7 @@ static void processEvent(XEvent *event)
|
||||
case DestroyNotify:
|
||||
return;
|
||||
}
|
||||
#undef UPDATE_KEYMAP_IF_NEEDED
|
||||
}
|
||||
|
||||
|
||||
@@ -1704,10 +1720,10 @@ unsigned long _glfwGetWindowPropertyX11(Window window,
|
||||
return itemCount;
|
||||
}
|
||||
|
||||
GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
|
||||
bool _glfwIsVisualTransparentX11(Visual* visual)
|
||||
{
|
||||
if (!_glfw.x11.xrender.available)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
|
||||
return pf && pf->direct.alphaMask;
|
||||
@@ -1779,21 +1795,21 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitGLX())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitEGL())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwInitOSMesa())
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1805,24 +1821,24 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
if (!createNativeWindow(window, wndconfig, visual, depth))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
if (ctxconfig->client != GLFW_NO_API)
|
||||
{
|
||||
if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
|
||||
{
|
||||
if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1834,7 +1850,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||
}
|
||||
|
||||
XFlush(_glfw.x11.display);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
@@ -2100,32 +2116,19 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||
*yscale = _glfw.x11.contentScaleY;
|
||||
}
|
||||
|
||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
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);
|
||||
XFlush(_glfw.x11.display);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
XMapWindow(_glfw.x11.display, window->x11.handle);
|
||||
@@ -2191,7 +2194,7 @@ void _glfwPlatformRequestWindowAttention(_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)
|
||||
@@ -2223,10 +2226,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!window->resizable)
|
||||
updateNormalHints(window, width, height);
|
||||
|
||||
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
||||
xpos, ypos, width, height);
|
||||
}
|
||||
|
||||
XFlush(_glfw.x11.display);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2235,16 +2242,20 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||
|
||||
_glfwInputWindowMonitor(window, monitor);
|
||||
updateNormalHints(window, width, height);
|
||||
updateWindowMode(window);
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
XMapRaised(_glfw.x11.display, window->x11.handle);
|
||||
if (waitForVisibilityNotify(window))
|
||||
acquireMonitor(window);
|
||||
if (!_glfwPlatformWindowVisible(window))
|
||||
{
|
||||
XMapRaised(_glfw.x11.display, window->x11.handle);
|
||||
waitForVisibilityNotify(window);
|
||||
}
|
||||
updateWindowMode(window);
|
||||
acquireMonitor(window);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateWindowMode(window);
|
||||
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
|
||||
xpos, ypos, width, height);
|
||||
}
|
||||
@@ -2261,6 +2272,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
||||
return window->x11.handle == focused;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
||||
{
|
||||
return getWindowState(window) == IconicState;
|
||||
@@ -2277,7 +2293,11 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
{
|
||||
Atom* states;
|
||||
unsigned long i;
|
||||
GLFWbool maximized = GLFW_FALSE;
|
||||
bool maximized = false;
|
||||
if (!_glfw.x11.NET_WM_STATE ||
|
||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||
return maximized;
|
||||
const unsigned long count =
|
||||
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||
_glfw.x11.NET_WM_STATE,
|
||||
@@ -2289,7 +2309,7 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
||||
if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||
states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||
{
|
||||
maximized = GLFW_TRUE;
|
||||
maximized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2312,32 +2332,32 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
||||
if (!XQueryPointer(_glfw.x11.display, w,
|
||||
&root, &w, &rootX, &rootY, &childX, &childY, &mask))
|
||||
{
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (w == window->x11.handle)
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||
{
|
||||
if (!window->x11.transparent)
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
|
||||
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;
|
||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||
updateNormalHints(window, width, height);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
@@ -2368,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)
|
||||
return;
|
||||
@@ -2464,23 +2484,29 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
||||
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) {
|
||||
_GLFWwindow* window;
|
||||
GLFWbool dispatched = GLFW_FALSE;
|
||||
unsigned dispatched = 0;
|
||||
|
||||
#if defined(__linux__)
|
||||
_glfwDetectJoystickConnectionLinux();
|
||||
#endif
|
||||
XPending(_glfw.x11.display);
|
||||
|
||||
while (XQLength(_glfw.x11.display))
|
||||
{
|
||||
XEvent event;
|
||||
XNextEvent(_glfw.x11.display, &event);
|
||||
processEvent(&event);
|
||||
dispatched = GLFW_TRUE;
|
||||
}
|
||||
dispatched += dispatch_x11_queued_events();
|
||||
|
||||
window = _glfw.x11.disabledCursorWindow;
|
||||
if (window)
|
||||
@@ -2498,6 +2524,8 @@ _glfwDispatchX11Events(void) {
|
||||
}
|
||||
|
||||
XFlush(_glfw.x11.display);
|
||||
// XFlush can cause events to be queued
|
||||
dispatched += dispatch_x11_queued_events();
|
||||
return dispatched;
|
||||
}
|
||||
|
||||
@@ -2521,16 +2549,6 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -2594,39 +2612,40 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
{
|
||||
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
|
||||
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;
|
||||
|
||||
if (shape == GLFW_ARROW_CURSOR)
|
||||
native = XC_left_ptr;
|
||||
else if (shape == GLFW_IBEAM_CURSOR)
|
||||
native = XC_xterm;
|
||||
else if (shape == GLFW_CROSSHAIR_CURSOR)
|
||||
native = XC_crosshair;
|
||||
else if (shape == GLFW_HAND_CURSOR)
|
||||
native = XC_hand1;
|
||||
else if (shape == GLFW_HRESIZE_CURSOR)
|
||||
native = XC_sb_h_double_arrow;
|
||||
else if (shape == GLFW_VRESIZE_CURSOR)
|
||||
native = XC_sb_v_double_arrow;
|
||||
else
|
||||
return GLFW_FALSE;
|
||||
#define C(name, val) case name: native = val; break;
|
||||
switch(shape) {
|
||||
C(GLFW_ARROW_CURSOR, XC_arrow);
|
||||
C(GLFW_IBEAM_CURSOR, XC_xterm);
|
||||
C(GLFW_CROSSHAIR_CURSOR, XC_crosshair);
|
||||
C(GLFW_HAND_CURSOR, XC_hand2);
|
||||
C(GLFW_HRESIZE_CURSOR, XC_sb_h_double_arrow);
|
||||
C(GLFW_VRESIZE_CURSOR, XC_sb_v_double_arrow);
|
||||
C(GLFW_NW_RESIZE_CURSOR, XC_top_left_corner);
|
||||
C(GLFW_NE_RESIZE_CURSOR, XC_top_right_corner);
|
||||
C(GLFW_SW_RESIZE_CURSOR, XC_bottom_left_corner);
|
||||
C(GLFW_SE_RESIZE_CURSOR, XC_bottom_right_corner);
|
||||
case GLFW_INVALID_CURSOR:
|
||||
return false;
|
||||
}
|
||||
#undef C
|
||||
|
||||
cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
|
||||
if (!cursor->x11.handle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to create standard cursor");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||
@@ -2667,6 +2686,29 @@ const char* _glfwPlatformGetClipboardString(void)
|
||||
return getSelectionString(_glfw.x11.CLIPBOARD);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetPrimarySelectionString(const char* string)
|
||||
{
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
_glfw.x11.primarySelectionString = _glfw_strdup(string);
|
||||
|
||||
XSetSelectionOwner(_glfw.x11.display,
|
||||
_glfw.x11.PRIMARY,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to become owner of primary selection");
|
||||
}
|
||||
}
|
||||
|
||||
const char* _glfwPlatformGetPrimarySelectionString(void)
|
||||
{
|
||||
return getSelectionString(_glfw.x11.PRIMARY);
|
||||
}
|
||||
|
||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
||||
{
|
||||
if (!_glfw.vk.KHR_surface)
|
||||
@@ -2705,7 +2747,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xcb_surface extension");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
xcb_connection_t* connection = XGetXCBConnection(_glfw.x11.display);
|
||||
@@ -2713,7 +2755,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to retrieve XCB connection");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
|
||||
@@ -2731,7 +2773,7 @@ int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
||||
{
|
||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||
"X11: Vulkan instance missing VK_KHR_xlib_surface extension");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
|
||||
@@ -2838,32 +2880,14 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
|
||||
return window->x11.handle;
|
||||
}
|
||||
|
||||
GLFWAPI void glfwSetX11SelectionString(const char* string)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT();
|
||||
|
||||
free(_glfw.x11.primarySelectionString);
|
||||
_glfw.x11.primarySelectionString = _glfw_strdup(string);
|
||||
|
||||
XSetSelectionOwner(_glfw.x11.display,
|
||||
_glfw.x11.PRIMARY,
|
||||
_glfw.x11.helperWindowHandle,
|
||||
CurrentTime);
|
||||
|
||||
if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
|
||||
_glfw.x11.helperWindowHandle)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"X11: Failed to become owner of primary selection");
|
||||
}
|
||||
}
|
||||
|
||||
GLFWAPI const char* glfwGetX11SelectionString(void)
|
||||
{
|
||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||
return getSelectionString(_glfw.x11.PRIMARY);
|
||||
}
|
||||
|
||||
GLFWAPI int glfwGetXKBScancode(const char* keyName, GLFWbool caseSensitive) {
|
||||
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool 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);
|
||||
}
|
||||
|
||||
45
glfw/xkb_glfw.c
vendored
45
glfw/xkb_glfw.c
vendored
@@ -46,6 +46,8 @@
|
||||
S(bracketleft, LEFT_BRACKET); \
|
||||
S(backslash, BACKSLASH); \
|
||||
S(bracketright, RIGHT_BRACKET); \
|
||||
S(plus, PLUS); \
|
||||
S(underscore, UNDERSCORE); \
|
||||
S(grave, GRAVE_ACCENT); \
|
||||
S(Escape, ESCAPE); \
|
||||
S(Return, ENTER); \
|
||||
@@ -134,30 +136,30 @@ glfw_xkb_sym_for_key(int key) {
|
||||
|
||||
#ifdef _GLFW_X11
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_xkb_set_x11_events_mask(void) {
|
||||
if (!XkbSelectEvents(_glfw.x11.display, XkbUseCoreKbd, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask)) {
|
||||
_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) {
|
||||
xkb->keyboard_device_id = -1;
|
||||
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display);
|
||||
if (!conn) {
|
||||
_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);
|
||||
if (xkb->keyboard_device_id == -1) {
|
||||
_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, ...) {\
|
||||
@@ -202,17 +204,17 @@ glfw_xkb_release(_GLFWXKBData *xkb) {
|
||||
glfw_ibus_terminate(&xkb->ibus);
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_xkb_create_context(_GLFWXKBData *xkb) {
|
||||
xkb->context = xkb_context_new(0);
|
||||
if (!xkb->context)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Failed to initialize XKB context");
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
glfw_connect_to_ibus(&xkb->ibus);
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char*
|
||||
@@ -255,9 +257,10 @@ load_compose_tables(_GLFWXKBData *xkb) {
|
||||
if (!xkb->states.composeState) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose state");
|
||||
}
|
||||
xkb_compose_table_unref(compose_table);
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
||||
const char *err;
|
||||
release_keyboard_data(xkb);
|
||||
@@ -265,13 +268,13 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
||||
if (err) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
||||
release_keyboard_data(xkb);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
err = load_states(xkb);
|
||||
if (err) {
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "%s", err);
|
||||
release_keyboard_data(xkb);
|
||||
return GLFW_FALSE;
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
@@ -289,7 +292,7 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
||||
}
|
||||
xkb->states.modifiers = 0;
|
||||
xkb->states.activeUnknownModifiers = 0;
|
||||
return GLFW_TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline xkb_mod_mask_t
|
||||
@@ -323,7 +326,7 @@ glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_m
|
||||
update_modifiers(xkb, &xkb->states);
|
||||
}
|
||||
|
||||
GLFWbool
|
||||
bool
|
||||
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
|
||||
#ifdef _GLFW_WAYLAND
|
||||
scancode += 8;
|
||||
@@ -363,7 +366,7 @@ glfw_xkb_keysym_name(xkb_keysym_t sym) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -410,7 +413,7 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
|
||||
int x = 0, y = 0;
|
||||
switch(which) {
|
||||
case 1:
|
||||
glfw_ibus_set_focused(&xkb->ibus, a ? GLFW_TRUE : GLFW_FALSE);
|
||||
glfw_ibus_set_focused(&xkb->ibus, a ? true : false);
|
||||
break;
|
||||
case 2:
|
||||
_glfwPlatformGetWindowPos(w, &x, &y);
|
||||
@@ -421,7 +424,7 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
|
||||
}
|
||||
|
||||
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);
|
||||
if (failed && window && window->callbacks.keyboard) {
|
||||
// notify application to remove any existing pre-edit text
|
||||
@@ -434,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.
|
||||
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
|
||||
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);
|
||||
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",
|
||||
@@ -497,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); }
|
||||
}
|
||||
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]) {
|
||||
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
|
||||
if (num_default_syms > 0) {
|
||||
glfw_sym = default_syms[0];
|
||||
glfw_keycode = glfw_key_for_sym(glfw_sym);
|
||||
is_fallback = GLFW_TRUE;
|
||||
is_fallback = true;
|
||||
}
|
||||
}
|
||||
debug(
|
||||
|
||||
18
glfw/xkb_glfw.h
vendored
18
glfw/xkb_glfw.h
vendored
@@ -67,8 +67,8 @@ typedef struct {
|
||||
|
||||
#ifdef _GLFW_X11
|
||||
int32_t keyboard_device_id;
|
||||
GLFWbool available;
|
||||
GLFWbool detectable;
|
||||
bool available;
|
||||
bool detectable;
|
||||
int majorOpcode;
|
||||
int eventBase;
|
||||
int errorBase;
|
||||
@@ -79,18 +79,18 @@ typedef struct {
|
||||
} _GLFWXKBData;
|
||||
|
||||
#ifdef _GLFW_X11
|
||||
GLFWbool glfw_xkb_set_x11_events_mask(void);
|
||||
GLFWbool glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb);
|
||||
bool glfw_xkb_set_x11_events_mask(void);
|
||||
bool glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb);
|
||||
#endif
|
||||
|
||||
void glfw_xkb_release(_GLFWXKBData *xkb);
|
||||
GLFWbool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
||||
GLFWbool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
|
||||
bool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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_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
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import os
|
||||
from contextlib import suppress
|
||||
|
||||
from kitty.cli import parse_args
|
||||
from kitty.constants import cache_dir
|
||||
@@ -27,10 +28,8 @@ class HistoryCompleter:
|
||||
self.history_path = None
|
||||
if name:
|
||||
ddir = os.path.join(cache_dir(), 'ask')
|
||||
try:
|
||||
with suppress(FileExistsError):
|
||||
os.makedirs(ddir)
|
||||
except FileExistsError:
|
||||
pass
|
||||
self.history_path = os.path.join(ddir, name)
|
||||
|
||||
def complete(self, text, state):
|
||||
@@ -50,10 +49,8 @@ class HistoryCompleter:
|
||||
|
||||
def __enter__(self):
|
||||
if self.history_path:
|
||||
try:
|
||||
with suppress(Exception):
|
||||
readline.read_history_file(self.history_path)
|
||||
except Exception:
|
||||
pass
|
||||
readline.set_completer(self.complete)
|
||||
return self
|
||||
|
||||
@@ -106,10 +103,8 @@ def main(args):
|
||||
print(styled(args.message, bold=True))
|
||||
|
||||
prompt = '> '
|
||||
try:
|
||||
with suppress(KeyboardInterrupt, EOFError):
|
||||
ans['response'] = input(prompt)
|
||||
except (KeyboardInterrupt, EOFError):
|
||||
pass
|
||||
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);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user