Compare commits
1145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b65119b8a9 | ||
|
|
86703da917 | ||
|
|
610e9afdf0 | ||
|
|
e3af9f68d3 | ||
|
|
747ac85e7c | ||
|
|
8c23f9e526 | ||
|
|
e6e339fcd3 | ||
|
|
f04680ac47 | ||
|
|
90985cc846 | ||
|
|
63917944f2 | ||
|
|
793605f80f | ||
|
|
93a281c7e3 | ||
|
|
8f1c6c4d74 | ||
|
|
1610dba7ab | ||
|
|
d9d419991c | ||
|
|
f9e86b19aa | ||
|
|
fffb976e43 | ||
|
|
0da566b49f | ||
|
|
da55717d20 | ||
|
|
254836902c | ||
|
|
d01f8d1865 | ||
|
|
a46c3f7007 | ||
|
|
4e58062025 | ||
|
|
aa3be0535f | ||
|
|
8ebf5e007c | ||
|
|
c2957e7f12 | ||
|
|
bf7c26d357 | ||
|
|
0547102bdd | ||
|
|
a07369ce69 | ||
|
|
21c5610431 | ||
|
|
6dbdf72f40 | ||
|
|
76a6bba643 | ||
|
|
b0b8222a96 | ||
|
|
0d87b8fac5 | ||
|
|
5227b1f98b | ||
|
|
c4f7c5c1cd | ||
|
|
33a84a609c | ||
|
|
037111715a | ||
|
|
93271b93e6 | ||
|
|
04488ada06 | ||
|
|
21c7002c68 | ||
|
|
97cae0e355 | ||
|
|
85fc0a59b1 | ||
|
|
eddd45bbc3 | ||
|
|
e2339697b9 | ||
|
|
cfe9b408ce | ||
|
|
83e8018787 | ||
|
|
372d2008a6 | ||
|
|
ab9a36f8c1 | ||
|
|
2458c3a7c6 | ||
|
|
e827e6fa21 | ||
|
|
342f0981d8 | ||
|
|
9c19e88288 | ||
|
|
7329bd4910 | ||
|
|
b9ad62226e | ||
|
|
3bff3bcbe4 | ||
|
|
a06fdad034 | ||
|
|
a49bd98ec6 | ||
|
|
90f41108d3 | ||
|
|
382c31ddf2 | ||
|
|
871ca4dda6 | ||
|
|
fa003f8233 | ||
|
|
12f37bcfad | ||
|
|
e86c712424 | ||
|
|
e8a9935cb2 | ||
|
|
f353131b44 | ||
|
|
7c4a2ba329 | ||
|
|
dfb543bd94 | ||
|
|
c912eef040 | ||
|
|
5f06d3a427 | ||
|
|
a70fa9abc5 | ||
|
|
5956277863 | ||
|
|
d3f37eeba4 | ||
|
|
ea48332f46 | ||
|
|
eb12511646 | ||
|
|
aa11ddf32c | ||
|
|
a348f64833 | ||
|
|
626a96e20f | ||
|
|
60995ff04b | ||
|
|
ba4e711715 | ||
|
|
891b184195 | ||
|
|
5414dc398e | ||
|
|
917559f883 | ||
|
|
9f2fb76309 | ||
|
|
b6692849d6 | ||
|
|
b27f6d5957 | ||
|
|
cda1e28b32 | ||
|
|
8a3e71d3d0 | ||
|
|
149ae2866a | ||
|
|
21707171bb | ||
|
|
2ebdf738ca | ||
|
|
0e871a89aa | ||
|
|
2d4f194f0d | ||
|
|
ce94a9b2df | ||
|
|
bfbb3c7068 | ||
|
|
6d1fd20542 | ||
|
|
bb8cab3a02 | ||
|
|
10435c23c2 | ||
|
|
01142cdc8c | ||
|
|
fc0adfd965 | ||
|
|
8803eeb890 | ||
|
|
25be705bcf | ||
|
|
d8f214a267 | ||
|
|
f74fb846e5 | ||
|
|
8ae110691e | ||
|
|
abff2292c1 | ||
|
|
7d690bbad2 | ||
|
|
7298de646a | ||
|
|
3c2f3ecd8e | ||
|
|
ac2c21e046 | ||
|
|
c817ba9eae | ||
|
|
92827ae647 | ||
|
|
5bdb405635 | ||
|
|
9beae321d7 | ||
|
|
353db678a2 | ||
|
|
9b973ef99c | ||
|
|
308d171dae | ||
|
|
7057bc663e | ||
|
|
d84cff0baf | ||
|
|
645890ccc8 | ||
|
|
cc1336a616 | ||
|
|
9b32f18109 | ||
|
|
a0321376d5 | ||
|
|
0a6e264d09 | ||
|
|
afec07b124 | ||
|
|
8a34fede55 | ||
|
|
686b5f297e | ||
|
|
6609d219f4 | ||
|
|
804998ca69 | ||
|
|
de5254469c | ||
|
|
ef879bab9c | ||
|
|
f729985346 | ||
|
|
1e998b6a3f | ||
|
|
77e9460eea | ||
|
|
81a58186c6 | ||
|
|
ac149be2bb | ||
|
|
a76a163db5 | ||
|
|
4ae59d3f77 | ||
|
|
d83a450260 | ||
|
|
61acc0784e | ||
|
|
f05890719d | ||
|
|
0f4e7921ee | ||
|
|
ec8c96b8e6 | ||
|
|
f0b29e15c3 | ||
|
|
8ad62106e0 | ||
|
|
36eb52424f | ||
|
|
c9ce2f47dc | ||
|
|
5035ed61ee | ||
|
|
a4cc10c41b | ||
|
|
5730ce5f53 | ||
|
|
27524bfc3d | ||
|
|
8843ded1c9 | ||
|
|
64b497589f | ||
|
|
ee48fd7151 | ||
|
|
291cd5e23f | ||
|
|
be668cfd9a | ||
|
|
f889c1c75a | ||
|
|
55c5f3e9fd | ||
|
|
242d335095 | ||
|
|
c763db94ce | ||
|
|
a391732600 | ||
|
|
06b45fcace | ||
|
|
bdac5f7d5b | ||
|
|
74865efddb | ||
|
|
b1f4d16692 | ||
|
|
01b8e2c3f5 | ||
|
|
8c1ef94b26 | ||
|
|
507fbc7abf | ||
|
|
2f8002c567 | ||
|
|
551e28d8e0 | ||
|
|
e84163e838 | ||
|
|
3a64b835fb | ||
|
|
08a44ed4dd | ||
|
|
4b8cc23a86 | ||
|
|
c4b2de8939 | ||
|
|
e2a603dcda | ||
|
|
294d01def6 | ||
|
|
05f289f912 | ||
|
|
4343c4067e | ||
|
|
c167dcc4e9 | ||
|
|
9a67176719 | ||
|
|
42d1a4755a | ||
|
|
1690e6933f | ||
|
|
5bbc15583e | ||
|
|
e03aabd972 | ||
|
|
6f5968eeb0 | ||
|
|
71b6e8f12a | ||
|
|
9c486f6e69 | ||
|
|
2f24588c66 | ||
|
|
6b1ea326a0 | ||
|
|
4512d0dbac | ||
|
|
511c4da6a3 | ||
|
|
af8fdf1dbe | ||
|
|
b7d12de0a7 | ||
|
|
2d870fc84a | ||
|
|
6e87929603 | ||
|
|
2b441df9e9 | ||
|
|
3e672ac178 | ||
|
|
12a24d5c86 | ||
|
|
dec1a0886d | ||
|
|
a82e45ad71 | ||
|
|
82e5750d71 | ||
|
|
6a3eb3f3d7 | ||
|
|
533a739e2b | ||
|
|
b12a8331f1 | ||
|
|
8f4ec036e7 | ||
|
|
cba36f2240 | ||
|
|
b54ffbefe4 | ||
|
|
6d470e4da0 | ||
|
|
4e1ebec8c2 | ||
|
|
e9779258e9 | ||
|
|
5c83f45bc6 | ||
|
|
eb65aca1f4 | ||
|
|
5d7e393c93 | ||
|
|
d6d01102fe | ||
|
|
1ad802b194 | ||
|
|
4a191b65bb | ||
|
|
65cc9f4e1b | ||
|
|
9f4b13b523 | ||
|
|
97e1b62a1e | ||
|
|
3ac966a38b | ||
|
|
6f1fda0a48 | ||
|
|
c00b486864 | ||
|
|
7928fff645 | ||
|
|
0285f5a1ad | ||
|
|
56e5c8be32 | ||
|
|
ef569976cb | ||
|
|
f8ae048d60 | ||
|
|
c51f4df0ca | ||
|
|
84453bf15c | ||
|
|
917350f058 | ||
|
|
0c58662eb6 | ||
|
|
52ca75855e | ||
|
|
49a07651b9 | ||
|
|
90a8ba3789 | ||
|
|
734c3199f0 | ||
|
|
64567646d9 | ||
|
|
1a1638cc7f | ||
|
|
fdf055312c | ||
|
|
b0b8b06b56 | ||
|
|
9c1ffb1adf | ||
|
|
563bafea08 | ||
|
|
efe4c32ffd | ||
|
|
0f003a9a77 | ||
|
|
3eff929652 | ||
|
|
3010ebfef5 | ||
|
|
ff14f47781 | ||
|
|
0b99a5caae | ||
|
|
467b96f2f2 | ||
|
|
18751a05c0 | ||
|
|
9007623d0c | ||
|
|
c1abb7038d | ||
|
|
53f7eebc4d | ||
|
|
d54d29122d | ||
|
|
1d71791b3c | ||
|
|
0c6145d4f2 | ||
|
|
62e273c5bb | ||
|
|
d82f399be7 | ||
|
|
20a7050564 | ||
|
|
b235f411b0 | ||
|
|
99faeeacfc | ||
|
|
08ad4f389d | ||
|
|
edba63d0d9 | ||
|
|
e33f882abc | ||
|
|
53e059f4f7 | ||
|
|
830364e026 | ||
|
|
332714a925 | ||
|
|
1eee6deb22 | ||
|
|
547f138703 | ||
|
|
b6c345fc3c | ||
|
|
29c40a4957 | ||
|
|
72af821e1b | ||
|
|
5fe4d10f38 | ||
|
|
3b36470e84 | ||
|
|
f9e8a4050c | ||
|
|
ce308286df | ||
|
|
b670973226 | ||
|
|
01b11b8a53 | ||
|
|
75c47a8659 | ||
|
|
5b4e0ed483 | ||
|
|
7432a7f346 | ||
|
|
0830fc3b5a | ||
|
|
ab2c901e85 | ||
|
|
3774cc54c7 | ||
|
|
330ed8e4ae | ||
|
|
eddae44d6d | ||
|
|
226488717a | ||
|
|
2f9dabd344 | ||
|
|
cf1b7c0adb | ||
|
|
eb57d0d431 | ||
|
|
8116ee015a | ||
|
|
0fa3cec61f | ||
|
|
eb60464177 | ||
|
|
44b2651a0f | ||
|
|
f2e91b5ed2 | ||
|
|
e72b60c882 | ||
|
|
5263babc9a | ||
|
|
9034b50b3a | ||
|
|
fdd7fe1948 | ||
|
|
8e7b8b70dc | ||
|
|
9bf24bdff5 | ||
|
|
ee53edd96d | ||
|
|
1bc5d7038d | ||
|
|
8a6b8b415c | ||
|
|
86174c81c8 | ||
|
|
374500d7b0 | ||
|
|
319a141967 | ||
|
|
c0d0062ef8 | ||
|
|
aaaa34e119 | ||
|
|
fba9502a9d | ||
|
|
6670cc1534 | ||
|
|
970729dca0 | ||
|
|
6627586d6e | ||
|
|
9f364209af | ||
|
|
c31a39a052 | ||
|
|
36fda90814 | ||
|
|
7ccfbc16e9 | ||
|
|
ad3b527bc4 | ||
|
|
f7eef3f456 | ||
|
|
1870364888 | ||
|
|
d7dfc85cf7 | ||
|
|
c047e5f16a | ||
|
|
8d21f63ec2 | ||
|
|
85b6a91e5c | ||
|
|
c788e30b66 | ||
|
|
a99caed693 | ||
|
|
9589fb5275 | ||
|
|
1a6dc530a4 | ||
|
|
60835871eb | ||
|
|
644ee646a2 | ||
|
|
8f1ec053ef | ||
|
|
2e3037ce3a | ||
|
|
109a856b91 | ||
|
|
eaec854bfb | ||
|
|
2c6cc6f047 | ||
|
|
f32ae10339 | ||
|
|
c46317f96f | ||
|
|
a67e4e550e | ||
|
|
65a7b19f40 | ||
|
|
1b5daf930a | ||
|
|
748ca81d4b | ||
|
|
0ea7d24ba4 | ||
|
|
6c9861cb76 | ||
|
|
a1125b5cc8 | ||
|
|
b4e189d2bf | ||
|
|
dbc763fca0 | ||
|
|
4c03ffeae2 | ||
|
|
2719ac7d01 | ||
|
|
219b81b5ee | ||
|
|
8e1443360f | ||
|
|
d55242aa82 | ||
|
|
ba531969ec | ||
|
|
c12e7587cb | ||
|
|
3aac0860a2 | ||
|
|
e4fd12001c | ||
|
|
3581ffe04b | ||
|
|
f6901e4a3d | ||
|
|
5a2cc4578e | ||
|
|
6b5acc4d3d | ||
|
|
43326c9bd0 | ||
|
|
96f3253e6d | ||
|
|
f5090c951a | ||
|
|
edacdc5e25 | ||
|
|
c67661af61 | ||
|
|
5e60329adf | ||
|
|
6b4f8408de | ||
|
|
ea1ef709c6 | ||
|
|
bbf247c5c0 | ||
|
|
8243fd505f | ||
|
|
ed9f9db1b0 | ||
|
|
74bed658e1 | ||
|
|
2f7bdc274d | ||
|
|
1347ff27d9 | ||
|
|
5bf4d520f5 | ||
|
|
cf8d665eb7 | ||
|
|
b2eee6df5c | ||
|
|
e8121b39ec | ||
|
|
5359abab76 | ||
|
|
01644ac3f0 | ||
|
|
8fbf552494 | ||
|
|
9c3390c5e6 | ||
|
|
24d45b99e3 | ||
|
|
936f2186cc | ||
|
|
c68b302fa2 | ||
|
|
ca7cab1a2d | ||
|
|
083b294659 | ||
|
|
bc24716476 | ||
|
|
4acab65016 | ||
|
|
f6b03f106c | ||
|
|
8f9bbeabd7 | ||
|
|
ac72ac7af2 | ||
|
|
68e00bc8e1 | ||
|
|
922d6b3b32 | ||
|
|
4dde98305e | ||
|
|
3593189a75 | ||
|
|
4f135be86c | ||
|
|
605b32f78a | ||
|
|
476a8b1429 | ||
|
|
da9165aebf | ||
|
|
455a1e9532 | ||
|
|
f12031e284 | ||
|
|
df551bc992 | ||
|
|
35fb702833 | ||
|
|
072cd29e3c | ||
|
|
624dd78460 | ||
|
|
51c4737a29 | ||
|
|
d63ea11cac | ||
|
|
3d307794be | ||
|
|
d32a05925f | ||
|
|
04006ea81e | ||
|
|
1723616968 | ||
|
|
23bc2171c9 | ||
|
|
0b3602f764 | ||
|
|
0e448347cd | ||
|
|
e0c66ea5ba | ||
|
|
268de9a9d5 | ||
|
|
74eb523178 | ||
|
|
8c540d5a46 | ||
|
|
2045055ae3 | ||
|
|
d8ed135b46 | ||
|
|
3a4ba7e834 | ||
|
|
fab57fbdf1 | ||
|
|
76a93b6cd6 | ||
|
|
f44c3a4606 | ||
|
|
714bee7f45 | ||
|
|
91673642b3 | ||
|
|
fee08d746c | ||
|
|
527ff0238a | ||
|
|
789d649b5c | ||
|
|
8020657d8c | ||
|
|
a15d3ff12d | ||
|
|
fbce95aeda | ||
|
|
9bc1b5a2d9 | ||
|
|
6a8b7bf92f | ||
|
|
48728bdfdc | ||
|
|
b6416cf8a9 | ||
|
|
053de5763a | ||
|
|
fdb915d0c8 | ||
|
|
c2769c9aed | ||
|
|
57deb19d0b | ||
|
|
321771b150 | ||
|
|
61dd2011f5 | ||
|
|
8a5f189213 | ||
|
|
14560b008a | ||
|
|
db85e07d41 | ||
|
|
07c838fe24 | ||
|
|
1583b1b0c6 | ||
|
|
d250555cd0 | ||
|
|
dbd0dab154 | ||
|
|
b479ea410d | ||
|
|
1db613e95b | ||
|
|
70071fe1f6 | ||
|
|
58688dda38 | ||
|
|
756d65c41e | ||
|
|
b9a08eacb0 | ||
|
|
b653711446 | ||
|
|
e725c647ef | ||
|
|
003f77b257 | ||
|
|
10b578e6d2 | ||
|
|
151c6c2c70 | ||
|
|
53e6de9bd9 | ||
|
|
66a455a079 | ||
|
|
f8855410e0 | ||
|
|
93e8074325 | ||
|
|
296f512bfb | ||
|
|
c8f20d0edf | ||
|
|
286f3630d7 | ||
|
|
38423505b1 | ||
|
|
9a3c621eb6 | ||
|
|
bcf847fe98 | ||
|
|
ee7a5eef99 | ||
|
|
7bed66a458 | ||
|
|
b26229c44e | ||
|
|
c497c0f96a | ||
|
|
6df64613f2 | ||
|
|
46dd648380 | ||
|
|
4cd5de78c7 | ||
|
|
32fa46d6eb | ||
|
|
902c2f6c88 | ||
|
|
2a5196873a | ||
|
|
d2067141d3 | ||
|
|
b5229ec73c | ||
|
|
3a2a16f54c | ||
|
|
b2d428618c | ||
|
|
97af84a063 | ||
|
|
18faee6250 | ||
|
|
fd90a3ddc3 | ||
|
|
a08931d84d | ||
|
|
2f0b6e24c9 | ||
|
|
33c5fc0fb6 | ||
|
|
71adb2dcf8 | ||
|
|
1ae324691d | ||
|
|
689d059517 | ||
|
|
18f0ab9e02 | ||
|
|
088ab5f137 | ||
|
|
3dd83975ba | ||
|
|
a796a6cbef | ||
|
|
4766d7de82 | ||
|
|
4a3686c16c | ||
|
|
b49105495c | ||
|
|
ca2eda2c5b | ||
|
|
4fc7c4aafc | ||
|
|
0981828493 | ||
|
|
6bc4f18a59 | ||
|
|
79532a315c | ||
|
|
7472a992ed | ||
|
|
e40616a0db | ||
|
|
dd8b97a86c | ||
|
|
5eff3897de | ||
|
|
530cf2eb14 | ||
|
|
2baa34beb8 | ||
|
|
87e2f7f86d | ||
|
|
e142083d53 | ||
|
|
2e850a0d0d | ||
|
|
aec9c31bca | ||
|
|
598a147500 | ||
|
|
ba201c4c92 | ||
|
|
5bc7cfaa43 | ||
|
|
2804e1ff81 | ||
|
|
ae27d36902 | ||
|
|
08182fbe4d | ||
|
|
778474f436 | ||
|
|
c6698ce305 | ||
|
|
21bc215313 | ||
|
|
88a9cc42d2 | ||
|
|
28f33a67cf | ||
|
|
6742fabfba | ||
|
|
b3806f4533 | ||
|
|
6d5fb4ccc6 | ||
|
|
2487f18f24 | ||
|
|
f59afff1d1 | ||
|
|
b92f95b092 | ||
|
|
d68ae01448 | ||
|
|
87eda834d3 | ||
|
|
c28ff5259a | ||
|
|
4619259e26 | ||
|
|
7bf0afa621 | ||
|
|
e3e02c7271 | ||
|
|
24e17cb7d8 | ||
|
|
769998adca | ||
|
|
9b5d88e92d | ||
|
|
6d7bebee3a | ||
|
|
1c38654321 | ||
|
|
da7a78691f | ||
|
|
1eaf7083ef | ||
|
|
79a6fcdc5c | ||
|
|
90bcbbf426 | ||
|
|
41049e2a40 | ||
|
|
c9b8510e9c | ||
|
|
d854fc1cd0 | ||
|
|
5f7bcae072 | ||
|
|
652eec3033 | ||
|
|
a9928ec98a | ||
|
|
e1dfb608ca | ||
|
|
2cee3a8809 | ||
|
|
804f72b31a | ||
|
|
e106dcc83b | ||
|
|
9347be639b | ||
|
|
ffc0c42a63 | ||
|
|
f5e855b3ad | ||
|
|
9af4dc4bff | ||
|
|
6f6180c34a | ||
|
|
6ddd751713 | ||
|
|
2c72b06012 | ||
|
|
88854c1aa4 | ||
|
|
5ad704469f | ||
|
|
c140e17a6f | ||
|
|
4fc733a9c8 | ||
|
|
c5c59e4c55 | ||
|
|
e0edef6719 | ||
|
|
0f46ce49e2 | ||
|
|
f9fd39b8c1 | ||
|
|
bd75157428 | ||
|
|
f987f3ba77 | ||
|
|
1c16806efd | ||
|
|
29155fef23 | ||
|
|
c05cbed5b2 | ||
|
|
4f85d4db71 | ||
|
|
468468ab9f | ||
|
|
1b4a6da577 | ||
|
|
aed7a197c7 | ||
|
|
c257b7ecfd | ||
|
|
d6072f6218 | ||
|
|
4ea72a2892 | ||
|
|
89b07a1c6b | ||
|
|
db0cd61807 | ||
|
|
6feb906953 | ||
|
|
7cbf8c63bc | ||
|
|
fae51d4e00 | ||
|
|
c510584afd | ||
|
|
738878c2ff | ||
|
|
d5682fe49a | ||
|
|
d8dd22048a | ||
|
|
737d8b96b6 | ||
|
|
c8627c9713 | ||
|
|
65fa7da24a | ||
|
|
c4c6ef799f | ||
|
|
0d18b91895 | ||
|
|
42089aaadc | ||
|
|
432d0f3318 | ||
|
|
4ade6587e8 | ||
|
|
1724f11429 | ||
|
|
75d66d1048 | ||
|
|
feccef67b9 | ||
|
|
a7d30a199d | ||
|
|
37bbfb11d3 | ||
|
|
79c80b4043 | ||
|
|
18a1402ae2 | ||
|
|
5d639b91b0 | ||
|
|
080c09d22e | ||
|
|
00c2670039 | ||
|
|
f113184165 | ||
|
|
d69f8af107 | ||
|
|
ad2bd1bf63 | ||
|
|
059786ab66 | ||
|
|
72dfa5e5e6 | ||
|
|
d84da6b7b8 | ||
|
|
6aa82d82ad | ||
|
|
a649eb2a48 | ||
|
|
83932c8099 | ||
|
|
95e36cece1 | ||
|
|
7075a7f1c0 | ||
|
|
3093610d26 | ||
|
|
86eed7f895 | ||
|
|
5dc14c5861 | ||
|
|
cab87f6fb2 | ||
|
|
fb3acd1f4a | ||
|
|
b247cef85c | ||
|
|
70445f33e9 | ||
|
|
cadb4f1389 | ||
|
|
bf75a4de61 | ||
|
|
400ab584ac | ||
|
|
9edad62144 | ||
|
|
e94205098f | ||
|
|
35ab7eb472 | ||
|
|
18619b14ac | ||
|
|
97e0b9b65a | ||
|
|
5175d9f4a6 | ||
|
|
a5aed0f4ab | ||
|
|
14d693a8ff | ||
|
|
645963cc24 | ||
|
|
20751c2807 | ||
|
|
dda886b97c | ||
|
|
b796ceecdd | ||
|
|
4def89ebb5 | ||
|
|
bd1c1839dd | ||
|
|
8739f698f9 | ||
|
|
b8c8482f20 | ||
|
|
4348ca8cc5 | ||
|
|
d1aa59080f | ||
|
|
bf0ffa80be | ||
|
|
2a89a0c87e | ||
|
|
de84489a20 | ||
|
|
40901778ad | ||
|
|
c1febea659 | ||
|
|
b42f4ac288 | ||
|
|
fae57a5868 | ||
|
|
7a02d09508 | ||
|
|
8ec6fe960d | ||
|
|
61a77e19ef | ||
|
|
82e88b54c7 | ||
|
|
ab8975f4da | ||
|
|
5e7fd21c8d | ||
|
|
30cd9b2ae4 | ||
|
|
4f7d12f3fd | ||
|
|
62da158823 | ||
|
|
2d19b87208 | ||
|
|
54ca775006 | ||
|
|
a64a0d64cb | ||
|
|
6634dc81fe | ||
|
|
a2d5eef398 | ||
|
|
8184ba246a | ||
|
|
54ad1d103a | ||
|
|
d92f8a90ef | ||
|
|
d33c287344 | ||
|
|
782eebf976 | ||
|
|
0fbf75b95a | ||
|
|
5781facf4b | ||
|
|
b710ffc403 | ||
|
|
7d8edccb04 | ||
|
|
3750d70173 | ||
|
|
025e0bb546 | ||
|
|
033367de91 | ||
|
|
f93b605b75 | ||
|
|
7b4141b0c8 | ||
|
|
90acef72dc | ||
|
|
43f200be77 | ||
|
|
2fbb167803 | ||
|
|
2b396262f0 | ||
|
|
74deca52b9 | ||
|
|
058d956464 | ||
|
|
0f38dc1bd1 | ||
|
|
576b03c047 | ||
|
|
59cb1ad1e0 | ||
|
|
f77acdce14 | ||
|
|
43a98a1df1 | ||
|
|
d1cf771c14 | ||
|
|
10e5fcc375 | ||
|
|
2112932d04 | ||
|
|
be505ce6e0 | ||
|
|
4d6472128c | ||
|
|
26b7b1ec63 | ||
|
|
9a8f0a9b5a | ||
|
|
16dbbf3a1e | ||
|
|
8492d0a264 | ||
|
|
d8f8f1f590 | ||
|
|
b762e81da0 | ||
|
|
8b3b68ea69 | ||
|
|
28525766a5 | ||
|
|
d8fc23c38f | ||
|
|
8cae70fa36 | ||
|
|
7f2b98fad7 | ||
|
|
2b6dde2ac5 | ||
|
|
0c254fa7c7 | ||
|
|
fe7375becc | ||
|
|
b6ee88056e | ||
|
|
96f691ad64 | ||
|
|
8cf3380a77 | ||
|
|
e8d7e3e98b | ||
|
|
8af0a8476f | ||
|
|
2de4248f76 | ||
|
|
8c73ab6afb | ||
|
|
ee9bd77dc4 | ||
|
|
81f31ca215 | ||
|
|
51eff372f8 | ||
|
|
087376b44d | ||
|
|
e49047ef7d | ||
|
|
c117f36009 | ||
|
|
5ec83ee759 | ||
|
|
410165c14d | ||
|
|
973ef9fcda | ||
|
|
396bfb8540 | ||
|
|
aaf597bffd | ||
|
|
63c4f64bf5 | ||
|
|
5745dc34f7 | ||
|
|
114b8cff93 | ||
|
|
261571bb69 | ||
|
|
497e2c9163 | ||
|
|
ac01ffaa54 | ||
|
|
eb9fe06d10 | ||
|
|
506f2f7db7 | ||
|
|
f476c56f91 | ||
|
|
474688888d | ||
|
|
7ddbb613fe | ||
|
|
adc1c06089 | ||
|
|
1f8631cc99 | ||
|
|
f9e4e71285 | ||
|
|
5529194c8d | ||
|
|
5b008163af | ||
|
|
802da7087c | ||
|
|
53ab7617ca | ||
|
|
4369255a25 | ||
|
|
b709ee6842 | ||
|
|
4a8f9efe79 | ||
|
|
19d36fbe69 | ||
|
|
d37e73db54 | ||
|
|
a8f6615380 | ||
|
|
97fe38fbbc | ||
|
|
3378175450 | ||
|
|
9f60d2aea3 | ||
|
|
46d49e18c0 | ||
|
|
43fc335be2 | ||
|
|
f68339c571 | ||
|
|
0d68b7078c | ||
|
|
2e71dde780 | ||
|
|
51ddd584d6 | ||
|
|
4b090259cd | ||
|
|
f3b9ff5f9f | ||
|
|
4ec1a8d9c3 | ||
|
|
350cfeb7ef | ||
|
|
97d379b13e | ||
|
|
2154d555e5 | ||
|
|
1389c36657 | ||
|
|
bd1e7d6942 | ||
|
|
aadab38487 | ||
|
|
91299a279b | ||
|
|
53275c9137 | ||
|
|
fb1c318a09 | ||
|
|
2a07b3f46a | ||
|
|
ffc4e99717 | ||
|
|
fe807dd66f | ||
|
|
40ce5db812 | ||
|
|
649a9f4a6f | ||
|
|
e17ce875be | ||
|
|
415701c58a | ||
|
|
f16f80b459 | ||
|
|
628e6cc87f | ||
|
|
8f9a225c3a | ||
|
|
7b41bc95e1 | ||
|
|
2d06ee5822 | ||
|
|
40b4fb966f | ||
|
|
be696a9d76 | ||
|
|
1ffe9bef35 | ||
|
|
ed70d95c44 | ||
|
|
49bf876f73 | ||
|
|
e512b4d3e3 | ||
|
|
e78b6c7c7c | ||
|
|
a7403c0005 | ||
|
|
5bed0dddaa | ||
|
|
bc302dad23 | ||
|
|
41b0f8852f | ||
|
|
2fadd3e7ba | ||
|
|
dcfd2b8d60 | ||
|
|
7fe63a7aad | ||
|
|
67f2ec2421 | ||
|
|
8e7a23a7b9 | ||
|
|
8e96a27d51 | ||
|
|
b337d4d9d5 | ||
|
|
d9404c0362 | ||
|
|
e4ba5f449f | ||
|
|
17fd749e8d | ||
|
|
f3be5b5e57 | ||
|
|
e619eb9cbb | ||
|
|
a65ee155c5 | ||
|
|
4037480d2b | ||
|
|
97e6978ed8 | ||
|
|
f05eefcc20 | ||
|
|
3f926dfd8b | ||
|
|
59f64c5e33 | ||
|
|
87059a2004 | ||
|
|
7c52dd2bd8 | ||
|
|
70c2765a6e | ||
|
|
3618f4d642 | ||
|
|
698569536d | ||
|
|
c398d3d16e | ||
|
|
9dbc54aad6 | ||
|
|
931cb223cd | ||
|
|
336ee53fea | ||
|
|
34350af61c | ||
|
|
72f7cb3b7d | ||
|
|
481047a446 | ||
|
|
3bf1d73b07 | ||
|
|
b3b830bb5f | ||
|
|
def0c55df3 | ||
|
|
b995e00850 | ||
|
|
32dfc94909 | ||
|
|
20f7118432 | ||
|
|
37e6c3f0cb | ||
|
|
0459dda5c2 | ||
|
|
a10c816c05 | ||
|
|
c0c7cfacc2 | ||
|
|
8cdb6647ed | ||
|
|
b68e3c85b9 | ||
|
|
ef25d5bbd5 | ||
|
|
278bf6e897 | ||
|
|
90a985b73a | ||
|
|
b016353809 | ||
|
|
bc222af2e2 | ||
|
|
44599c9460 | ||
|
|
902fc22670 | ||
|
|
d84e22fbf1 | ||
|
|
6cc720a350 | ||
|
|
c905978874 | ||
|
|
bfe595a8e8 | ||
|
|
94d56d1a9e | ||
|
|
bd3f0b5363 | ||
|
|
6fae3545c7 | ||
|
|
297963f6ab | ||
|
|
a0ceba407e | ||
|
|
35fa91fba2 | ||
|
|
a5d6cd169e | ||
|
|
06c2263657 | ||
|
|
472c6f6b8d | ||
|
|
afcaca85da | ||
|
|
2575349ec2 | ||
|
|
77054f688d | ||
|
|
c5cb24378f | ||
|
|
d66123dd14 | ||
|
|
4ef8f11f9e | ||
|
|
599be7ddc9 | ||
|
|
685497fc8c | ||
|
|
57542fc204 | ||
|
|
8d9323aec6 | ||
|
|
4984a25b19 | ||
|
|
3bdcb29e01 | ||
|
|
b9ab8e6348 | ||
|
|
4a851701e9 | ||
|
|
eafd8af937 | ||
|
|
28bb123be8 | ||
|
|
8e1ed2f8c3 | ||
|
|
4a0fcb3cff | ||
|
|
b5c2163238 | ||
|
|
d0ecdfb330 | ||
|
|
bdf7d98a36 | ||
|
|
e4b0980d15 | ||
|
|
d99c57aeae | ||
|
|
5f855ce547 | ||
|
|
68f3b6fbeb | ||
|
|
dc6d14943e | ||
|
|
05f7334db9 | ||
|
|
cd707e9335 | ||
|
|
505ed5e43b | ||
|
|
9dc8bf5f62 | ||
|
|
f8098662b6 | ||
|
|
de7a0e86c4 | ||
|
|
ca55438fda | ||
|
|
a4b60e7eef | ||
|
|
5d22e07738 | ||
|
|
bdade7e151 | ||
|
|
6958ded4c4 | ||
|
|
cc06104be6 | ||
|
|
059c34c345 | ||
|
|
9cbb726566 | ||
|
|
e8b4356a88 | ||
|
|
634138cd3b | ||
|
|
3f6b07de81 | ||
|
|
d218900b57 | ||
|
|
cab949a939 | ||
|
|
e350822f5e | ||
|
|
3d6fe93297 | ||
|
|
3a5baf2722 | ||
|
|
cdb472cb56 | ||
|
|
e634350e77 | ||
|
|
464a6c1441 | ||
|
|
d3750b2244 | ||
|
|
b8d2b76ee4 | ||
|
|
14fb7c3201 | ||
|
|
922bc62e0e | ||
|
|
00cae4ccd1 | ||
|
|
61df266df7 | ||
|
|
17751666f2 | ||
|
|
961b2c9b65 | ||
|
|
eaf6f06047 | ||
|
|
d0ac218c05 | ||
|
|
1a01bc15d8 | ||
|
|
cdbe2f13ca | ||
|
|
4f5264277e | ||
|
|
bed3adcc95 | ||
|
|
0c5d59bcf6 | ||
|
|
ff20acd8b8 | ||
|
|
d1cffcde68 | ||
|
|
546dd9b225 | ||
|
|
2a666620c8 | ||
|
|
db50985040 | ||
|
|
8c6d593c41 | ||
|
|
40086c8d1c | ||
|
|
38f73b9f5e | ||
|
|
49429b5f49 | ||
|
|
d9f90ef077 | ||
|
|
6a126fa18e | ||
|
|
14d703f5cc | ||
|
|
9850025f3a | ||
|
|
8daab0ba41 | ||
|
|
88f25ccc76 | ||
|
|
50e7351c73 | ||
|
|
51453a54e4 | ||
|
|
c02ba03f39 | ||
|
|
78dec3d698 | ||
|
|
1590c59131 | ||
|
|
b26f79998a | ||
|
|
489f3e6c9d | ||
|
|
5fef4726a7 | ||
|
|
51fdb8200a | ||
|
|
fb0d98ead1 | ||
|
|
4096caba64 | ||
|
|
38f77144fa | ||
|
|
b8041ce17f | ||
|
|
00575733c8 | ||
|
|
621c92780c | ||
|
|
37f03af4b7 | ||
|
|
bdc4558a43 | ||
|
|
46d483e8b2 | ||
|
|
5143b62a07 | ||
|
|
87ed774cb4 | ||
|
|
4e427d05b7 | ||
|
|
195d987331 | ||
|
|
9b58317fb1 | ||
|
|
1cb15dedac | ||
|
|
5521d6b623 | ||
|
|
f5cf6c1dcb | ||
|
|
89307727e7 | ||
|
|
c30c21b250 | ||
|
|
b6fb087d7e | ||
|
|
97c2b7c1fe | ||
|
|
81506640c8 | ||
|
|
8244f7cd58 | ||
|
|
63573d6e26 | ||
|
|
9368f7f670 | ||
|
|
b7a11035d5 | ||
|
|
2e1b5e2fa7 | ||
|
|
8e5cbafe63 | ||
|
|
eb006a6688 | ||
|
|
40b9049deb | ||
|
|
64ffca2d0a | ||
|
|
1f4b6d4e9a | ||
|
|
eb30ba7722 | ||
|
|
3e0f4d36bc | ||
|
|
1fb118edee | ||
|
|
ca39634880 | ||
|
|
f8418d68a6 | ||
|
|
c0000fb24e | ||
|
|
c169f7ae83 | ||
|
|
7ab5244bf5 | ||
|
|
7e36489034 | ||
|
|
d259b12ae7 | ||
|
|
8f8138d9bd | ||
|
|
a8668f5fbf | ||
|
|
e00e6bd1c2 | ||
|
|
0fc6c47556 | ||
|
|
d530dccb96 | ||
|
|
37bf0e81d2 | ||
|
|
f872f955b0 | ||
|
|
003cd0a203 | ||
|
|
e7173f8145 | ||
|
|
93af102bec | ||
|
|
67f23664c9 | ||
|
|
39f6071c68 | ||
|
|
edc8878632 | ||
|
|
93b62c4dfd | ||
|
|
c3e210c80f | ||
|
|
9a5cc8f650 | ||
|
|
5e7fbfefe9 | ||
|
|
29ad6fba22 | ||
|
|
c848c3ee0d | ||
|
|
547132131a | ||
|
|
40186fb54b | ||
|
|
5dc4e79c8d | ||
|
|
556992a117 | ||
|
|
a41ef8d513 | ||
|
|
6d96a89328 | ||
|
|
0fb1481038 | ||
|
|
4b77530c65 | ||
|
|
cdb493cf50 | ||
|
|
c9a574a764 | ||
|
|
bdb633a882 | ||
|
|
37aee7133d | ||
|
|
2cfd55f3ce | ||
|
|
2e8188e89d | ||
|
|
1e172caea3 | ||
|
|
6866cd0fb8 | ||
|
|
2719926870 | ||
|
|
406891abcc | ||
|
|
4be6e9009a | ||
|
|
6a31909557 | ||
|
|
f49f0d19f9 | ||
|
|
a2407f94e4 | ||
|
|
62a0be4a11 | ||
|
|
b9029f6c67 | ||
|
|
92496f42c9 | ||
|
|
841c907efc | ||
|
|
9bc288cd8e | ||
|
|
2ef0391b08 | ||
|
|
6db768d1a3 | ||
|
|
9b080950a9 | ||
|
|
3cd1fef4cb | ||
|
|
a491a801bf | ||
|
|
41ebb72276 | ||
|
|
e4c0e9073e | ||
|
|
efad733cc5 | ||
|
|
1fcd6e1811 | ||
|
|
75d697fa97 | ||
|
|
cde69670ba | ||
|
|
0be6c9cb97 | ||
|
|
8c9d2d3ca2 | ||
|
|
c84e73d8e6 | ||
|
|
3fb00f6c70 | ||
|
|
86305fdeb3 | ||
|
|
710e146d22 | ||
|
|
d5abc84bea | ||
|
|
6f8214c15c | ||
|
|
a56475e32f | ||
|
|
9dadd91887 | ||
|
|
df5a73bb35 | ||
|
|
a50bf59a2c | ||
|
|
241354ae52 | ||
|
|
c863116011 | ||
|
|
5cbd591a1e | ||
|
|
6bb78c9499 | ||
|
|
893f406a99 | ||
|
|
f722b898b0 | ||
|
|
18335b3eac | ||
|
|
4708b592e2 | ||
|
|
7598a2965c | ||
|
|
1b59761a19 | ||
|
|
7fd1053e0f | ||
|
|
e178e7f6a5 | ||
|
|
d0bf21ab16 | ||
|
|
c826965833 | ||
|
|
a76db39c19 | ||
|
|
323a538bdd | ||
|
|
2435feca3b | ||
|
|
29d059680c | ||
|
|
aaaf7f9d8b | ||
|
|
bc90ce569a | ||
|
|
27f9f1756b | ||
|
|
9135387cfa | ||
|
|
af3504e05c | ||
|
|
9c9eac9d46 | ||
|
|
f28383206a | ||
|
|
ba1c093d18 | ||
|
|
3ea3a85694 | ||
|
|
0e1a423889 | ||
|
|
3ce68ed53f | ||
|
|
90c10da398 | ||
|
|
630bf28c22 | ||
|
|
ff89c1d8e4 | ||
|
|
96703c23c8 | ||
|
|
2b78f5adad | ||
|
|
ab7df777eb | ||
|
|
adbc694ff8 | ||
|
|
7709cdb12b | ||
|
|
f6051f73f5 | ||
|
|
d5c2a21cdf | ||
|
|
8ffc841a3a | ||
|
|
6c478977bb | ||
|
|
07beb53b37 | ||
|
|
59df1a8647 | ||
|
|
fb98aa650d | ||
|
|
9981b5a9c6 | ||
|
|
603533e632 | ||
|
|
38bc90f724 | ||
|
|
721beb9202 | ||
|
|
2e99259589 | ||
|
|
83e6b75872 | ||
|
|
cf70946f50 | ||
|
|
f1c36aba83 | ||
|
|
2973cf15a4 | ||
|
|
55969bc3c5 | ||
|
|
a8504c971a | ||
|
|
1644de2083 | ||
|
|
dd1fb85f60 | ||
|
|
b945b19865 | ||
|
|
91bf9f2ec8 | ||
|
|
f151f4c165 | ||
|
|
95b9b2d373 | ||
|
|
8be698681c | ||
|
|
da3e1a3730 | ||
|
|
29f637c19a | ||
|
|
3d01565ba7 | ||
|
|
962291cc8e | ||
|
|
a662dace9c | ||
|
|
d34e0b325e | ||
|
|
4c242ec528 | ||
|
|
658be9405f | ||
|
|
15e8f6ad8a | ||
|
|
a5aca35f1c | ||
|
|
ae9df1ffac | ||
|
|
8bf2e098f5 | ||
|
|
7091d554b5 | ||
|
|
bada795320 | ||
|
|
7d385849fb | ||
|
|
78775b7f6b | ||
|
|
8d21a5b6b3 | ||
|
|
9da095ca50 | ||
|
|
0fafc07db0 |
@@ -1,94 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#!/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)
|
|
||||||
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -3,11 +3,11 @@ kitty/emoji.h linguist-generated=true
|
|||||||
kitty/keys.h linguist-generated=true
|
kitty/keys.h linguist-generated=true
|
||||||
kitty/charsets.c linguist-generated=true
|
kitty/charsets.c linguist-generated=true
|
||||||
kitty/key_encoding.py linguist-generated=true
|
kitty/key_encoding.py linguist-generated=true
|
||||||
kitty/unicode-data.c
|
kitty/unicode-data.c linguist-generated=true
|
||||||
kitty/rgb.py linguist-generated=true
|
kitty/rgb.py linguist-generated=true
|
||||||
kitty/gl-wrapper.* linguist-generated=true
|
kitty/gl-wrapper.* linguist-generated=true
|
||||||
kitty/khrplatform.h linguist-generated=true
|
|
||||||
kitty/glfw-wrapper.* linguist-generated=true
|
kitty/glfw-wrapper.* linguist-generated=true
|
||||||
|
kitty/parse-graphics-command.h linguist-generated=true
|
||||||
glfw/*.c linguist-vendored=true
|
glfw/*.c linguist-vendored=true
|
||||||
glfw/*.h linguist-vendored=true
|
glfw/*.h linguist-vendored=true
|
||||||
kittens/unicode_input/names.h linguist-generated=true
|
kittens/unicode_input/names.h linguist-generated=true
|
||||||
|
|||||||
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
patreon: kovidgoyal
|
||||||
|
liberapay: kovidgoyal
|
||||||
|
custom: https://sw.kovidgoyal.net/kitty/support.html
|
||||||
125
.github/workflows/ci.py
vendored
Normal file
125
.github/workflows/ci.py
vendored
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPLv3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import shlex
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tarfile
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
is_bundle = os.environ.get('KITTY_BUNDLE') == '1'
|
||||||
|
is_macos = 'darwin' in sys.platform.lower()
|
||||||
|
SW = None
|
||||||
|
|
||||||
|
|
||||||
|
def run(*a):
|
||||||
|
if len(a) == 1:
|
||||||
|
a = shlex.split(a[0])
|
||||||
|
print(' '.join(map(shlex.quote, a)))
|
||||||
|
sys.stdout.flush()
|
||||||
|
ret = subprocess.Popen(a).wait()
|
||||||
|
if ret != 0:
|
||||||
|
raise SystemExit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
def install_deps():
|
||||||
|
print('Installing kitty dependencies...')
|
||||||
|
sys.stdout.flush()
|
||||||
|
if is_macos:
|
||||||
|
items = (x.strip() for x in open('Brewfile').readlines() if not x.startswith('#'))
|
||||||
|
run('brew', 'install', *items)
|
||||||
|
else:
|
||||||
|
run('sudo apt-get update')
|
||||||
|
run('sudo 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 libxkbcommon-x11-dev libcanberra-dev')
|
||||||
|
if is_bundle:
|
||||||
|
install_bundle()
|
||||||
|
else:
|
||||||
|
run('pip install Pillow pygments')
|
||||||
|
|
||||||
|
|
||||||
|
def build_kitty():
|
||||||
|
python = 'python3' if is_bundle else sys.executable
|
||||||
|
cmd = '{} setup.py build --verbose'.format(python)
|
||||||
|
if os.environ.get('KITTY_SANITIZE') == '1':
|
||||||
|
cmd += ' --debug --sanitize'
|
||||||
|
run(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def test_kitty():
|
||||||
|
run('./kitty/launcher/kitty +launch test.py')
|
||||||
|
|
||||||
|
|
||||||
|
def package_kitty():
|
||||||
|
py = 'python3' if is_macos else 'python'
|
||||||
|
run(py + ' setup.py linux-package --update-check-interval=0 --verbose')
|
||||||
|
if is_macos:
|
||||||
|
run('python3 setup.py kitty.app --update-check-interval=0 --verbose')
|
||||||
|
run('kitty.app/Contents/MacOS/kitty +runpy "from kitty.constants import *; print(kitty_exe())"')
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_bundle_env():
|
||||||
|
global SW
|
||||||
|
os.environ['SW'] = SW = '/Users/Shared/buildbot/sw/sw' if is_macos else os.path.join(os.environ['GITHUB_WORKSPACE'], 'sw')
|
||||||
|
os.environ['PKG_CONFIG_PATH'] = SW + '/lib/pkgconfig'
|
||||||
|
if is_macos:
|
||||||
|
os.environ['PATH'] = '{}:{}'.format('/usr/local/opt/sphinx-doc/bin', os.environ['PATH'])
|
||||||
|
else:
|
||||||
|
os.environ['LD_LIBRARY_PATH'] = SW + '/lib'
|
||||||
|
os.environ['PYTHONHOME'] = SW
|
||||||
|
os.environ['PATH'] = '{}:{}'.format(os.path.join(SW, 'bin'), os.environ['PATH'])
|
||||||
|
|
||||||
|
|
||||||
|
def install_bundle():
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.makedirs(SW)
|
||||||
|
os.chdir(SW)
|
||||||
|
with urlopen('https://download.calibre-ebook.com/travis/kitty/{}.tar.xz'.format(
|
||||||
|
'osx' if is_macos else 'linux-64')) as f:
|
||||||
|
data = f.read()
|
||||||
|
with tarfile.open(fileobj=io.BytesIO(data), mode='r:xz') as tf:
|
||||||
|
tf.extractall()
|
||||||
|
if not is_macos:
|
||||||
|
replaced = 0
|
||||||
|
for dirpath, dirnames, filenames in os.walk('.'):
|
||||||
|
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')
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if is_bundle:
|
||||||
|
setup_bundle_env()
|
||||||
|
else:
|
||||||
|
if not is_macos:
|
||||||
|
os.environ['LD_LIBRARY_PATH'] = '{}/lib'.format(os.environ['pythonLocation'])
|
||||||
|
action = sys.argv[-1]
|
||||||
|
if action in ('build', 'package'):
|
||||||
|
install_deps()
|
||||||
|
if action == 'build':
|
||||||
|
build_kitty()
|
||||||
|
elif action == 'package':
|
||||||
|
package_kitty()
|
||||||
|
elif action == 'test':
|
||||||
|
test_kitty()
|
||||||
|
else:
|
||||||
|
raise SystemExit('Unknown action: ' + action)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
132
.github/workflows/ci.yml
vendored
Normal file
132
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
env:
|
||||||
|
CI: 'true'
|
||||||
|
ASAN_OPTIONS: leak_check_at_exit=0
|
||||||
|
LC_ALL: en_US.UTF-8
|
||||||
|
LANG: en_US.UTF-8
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
name: Linux (python=${{ matrix.pyver }} cc=${{ matrix.cc }} sanitize=${{ matrix.sanitize }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.cc }}
|
||||||
|
KITTY_SANITIZE: ${{ matrix.sanitize }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python: [a, b, c]
|
||||||
|
cc: [gcc, clang]
|
||||||
|
include:
|
||||||
|
- python: a
|
||||||
|
pyver: 3.6
|
||||||
|
sanitize: 0
|
||||||
|
|
||||||
|
- python: b
|
||||||
|
pyver: 3.7
|
||||||
|
sanitize: 1
|
||||||
|
|
||||||
|
- python: c
|
||||||
|
pyver: 3.8
|
||||||
|
sanitize: 1
|
||||||
|
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
- python: a
|
||||||
|
cc: clang
|
||||||
|
- python: b
|
||||||
|
cc: clang
|
||||||
|
- python: c
|
||||||
|
cc: gcc
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 10
|
||||||
|
- name: Set up Python ${{ matrix.pyver }}
|
||||||
|
uses: actions/setup-python@master
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.pyver }}
|
||||||
|
|
||||||
|
- name: Build kitty
|
||||||
|
run: python .github/workflows/ci.py build
|
||||||
|
|
||||||
|
- name: Test kitty
|
||||||
|
run: python .github/workflows/ci.py test
|
||||||
|
|
||||||
|
linux-package:
|
||||||
|
name: Linux package
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
CFLAGS: -funsigned-char
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 10
|
||||||
|
|
||||||
|
- name: Test for trailing whitespace
|
||||||
|
run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@master
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
|
||||||
|
- name: Install build-only deps
|
||||||
|
run: pip install flake8 mypy sphinx
|
||||||
|
|
||||||
|
- name: Run pyflakes
|
||||||
|
run: python -m flake8 --count .
|
||||||
|
|
||||||
|
- name: Build kitty package
|
||||||
|
run: python .github/workflows/ci.py package
|
||||||
|
|
||||||
|
- name: Run mypy
|
||||||
|
run: python test.py mypy
|
||||||
|
|
||||||
|
- name: Build man page
|
||||||
|
run: make FAIL_WARN=-W man
|
||||||
|
|
||||||
|
- name: Build HTML docs
|
||||||
|
run: make FAIL_WARN=-W html
|
||||||
|
|
||||||
|
bundle:
|
||||||
|
name: Bundle test (${{ matrix.os }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
env:
|
||||||
|
KITTY_BUNDLE: 1
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 10
|
||||||
|
|
||||||
|
- name: Build kitty
|
||||||
|
run: which python3 && python3 .github/workflows/ci.py build
|
||||||
|
|
||||||
|
- name: Test kitty
|
||||||
|
run: python3 .github/workflows/ci.py test
|
||||||
|
|
||||||
|
brew:
|
||||||
|
name: macOS Brew
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@master
|
||||||
|
with:
|
||||||
|
fetch-depth: 10
|
||||||
|
|
||||||
|
- name: Build kitty
|
||||||
|
run: python3 .github/workflows/ci.py build
|
||||||
|
|
||||||
|
- name: Test kitty
|
||||||
|
run: python3 .github/workflows/ci.py test
|
||||||
|
|
||||||
|
- name: Build kitty package
|
||||||
|
run: python3 .github/workflows/ci.py package
|
||||||
31
.gitignore
vendored
31
.gitignore
vendored
@@ -1,19 +1,20 @@
|
|||||||
*.so
|
*.so
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
tags
|
*_stub.pyi
|
||||||
build
|
/.dmypy.json
|
||||||
linux-package
|
/tags
|
||||||
kitty.app
|
/build/
|
||||||
logo/*.iconset
|
/linux-package/
|
||||||
compile_commands.json
|
/kitty.app/
|
||||||
glad/out
|
/compile_commands.json
|
||||||
asan-launcher
|
/link_commands.json
|
||||||
asan-launcher.dSYM
|
/glad/out/
|
||||||
kitty-profile
|
/kitty/launcher/
|
||||||
dev
|
/*.dSYM/
|
||||||
__pycache__
|
__pycache__/
|
||||||
glfw/wayland-*-client-protocol.[ch]
|
/glfw/wayland-*-client-protocol.[ch]
|
||||||
docs/_build
|
/docs/_build/
|
||||||
docs/generated
|
/docs/generated/
|
||||||
|
/.mypy_cache
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
11
Brewfile
11
Brewfile
@@ -1,6 +1,5 @@
|
|||||||
brew 'pkg-config'
|
pkg-config
|
||||||
brew 'imagemagick'
|
python
|
||||||
brew 'optipng'
|
imagemagick
|
||||||
brew 'librsvg'
|
harfbuzz
|
||||||
brew 'harfbuzz'
|
sphinx-doc
|
||||||
brew 'python'
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
To build from source:
|
To build from source: <https://sw.kovidgoyal.net/kitty/build.html>
|
||||||
|
|
||||||
https://sw.kovidgoyal.net/kitty/build.html
|
Pre-built binaries: <https://sw.kovidgoyal.net/kitty/binary.html>
|
||||||
|
|
||||||
Pre-built binaries:
|
|
||||||
|
|
||||||
https://sw.kovidgoyal.net/kitty/binary.html
|
|
||||||
|
|||||||
11
Makefile
11
Makefile
@@ -1,8 +1,8 @@
|
|||||||
ifdef V
|
ifdef V
|
||||||
VVAL=--verbose
|
VVAL=--verbose
|
||||||
endif
|
endif
|
||||||
ifdef VERBOSE
|
ifdef VERBOSE
|
||||||
VVAL=--verbose
|
VVAL=--verbose
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
@@ -28,12 +28,7 @@ asan:
|
|||||||
profile:
|
profile:
|
||||||
python3 setup.py build $(VVAL) --profile
|
python3 setup.py build $(VVAL) --profile
|
||||||
|
|
||||||
logo/kitty.iconset/icon_256x256.png: logo/kitty.svg logo/make.py
|
app:
|
||||||
logo/make.py
|
|
||||||
|
|
||||||
rendered_logo: logo/kitty.iconset/icon_256x256.png
|
|
||||||
|
|
||||||
app: rendered_logo
|
|
||||||
python3 setup.py kitty.app $(VVAL)
|
python3 setup.py kitty.app $(VVAL)
|
||||||
|
|
||||||
man:
|
man:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
= kitty - the fast, featureful, GPU based, terminal emulator
|
= kitty - the fast, featureful, GPU based, terminal emulator
|
||||||
|
|
||||||
See https://sw.kovidgoyal.net/kitty
|
See https://sw.kovidgoyal.net/kitty/
|
||||||
|
|
||||||
image:https://circleci.com/gh/kovidgoyal/kitty.svg?style=svg["Build status", link="https://circleci.com/gh/kovidgoyal/kitty"]
|
image:https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg["Build status", link="https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI"]
|
||||||
|
|||||||
54
__main__.py
54
__main__.py
@@ -4,54 +4,56 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
def icat(args):
|
def icat(args: List[str]) -> None:
|
||||||
from kittens.runner import run_kitten
|
from kittens.runner import run_kitten as rk
|
||||||
sys.argv = args
|
sys.argv = args
|
||||||
run_kitten('icat')
|
rk('icat')
|
||||||
|
|
||||||
|
|
||||||
def list_fonts(args):
|
def list_fonts(args: List[str]) -> None:
|
||||||
from kitty.fonts.list import main
|
from kitty.fonts.list import main as list_main
|
||||||
main(args)
|
list_main(args)
|
||||||
|
|
||||||
|
|
||||||
def remote_control(args):
|
def remote_control(args: List[str]) -> None:
|
||||||
from kitty.remote_control import main
|
from kitty.remote_control import main as rc_main
|
||||||
main(args)
|
rc_main(args)
|
||||||
|
|
||||||
|
|
||||||
def runpy(args):
|
def runpy(args: List[str]) -> None:
|
||||||
sys.argv = ['kitty'] + args[2:]
|
sys.argv = ['kitty'] + args[2:]
|
||||||
exec(args[1])
|
exec(args[1])
|
||||||
|
|
||||||
|
|
||||||
def hold(args):
|
def hold(args: List[str]) -> None:
|
||||||
import subprocess
|
import subprocess
|
||||||
ret = subprocess.Popen(args[1:]).wait()
|
ret = subprocess.Popen(args[1:]).wait()
|
||||||
sys.stdin.read()
|
sys.stdin.read()
|
||||||
raise SystemExit(ret)
|
raise SystemExit(ret)
|
||||||
|
|
||||||
|
|
||||||
def complete(args):
|
def complete(args: List[str]) -> None:
|
||||||
from kitty.complete import main
|
from kitty.complete import main as complete_main
|
||||||
main(args[1:], entry_points, namespaced_entry_points)
|
complete_main(args[1:], entry_points, namespaced_entry_points)
|
||||||
|
|
||||||
|
|
||||||
def launch(args):
|
def launch(args: List[str]) -> None:
|
||||||
import runpy
|
import runpy
|
||||||
sys.argv = args[1:]
|
sys.argv = args[1:]
|
||||||
exe = args[1]
|
exe = args[1]
|
||||||
if exe.startswith(':'):
|
if exe.startswith(':'):
|
||||||
import shutil
|
import shutil
|
||||||
exe = shutil.which(exe[1:])
|
q = shutil.which(exe[1:])
|
||||||
if not exe:
|
if not q:
|
||||||
raise SystemExit('{} not found in PATH'.format(args[1][1:]))
|
raise SystemExit('{} not found in PATH'.format(args[1][1:]))
|
||||||
|
exe = q
|
||||||
runpy.run_path(exe, run_name='__main__')
|
runpy.run_path(exe, run_name='__main__')
|
||||||
|
|
||||||
|
|
||||||
def run_kitten(args):
|
def run_kitten(args: List[str]) -> None:
|
||||||
try:
|
try:
|
||||||
kitten = args[1]
|
kitten = args[1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@@ -59,11 +61,11 @@ def run_kitten(args):
|
|||||||
list_kittens()
|
list_kittens()
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
sys.argv = args[1:]
|
sys.argv = args[1:]
|
||||||
from kittens.runner import run_kitten
|
from kittens.runner import run_kitten as rk
|
||||||
run_kitten(kitten)
|
rk(kitten)
|
||||||
|
|
||||||
|
|
||||||
def namespaced(args):
|
def namespaced(args: List[str]) -> None:
|
||||||
func = namespaced_entry_points[args[1]]
|
func = namespaced_entry_points[args[1]]
|
||||||
func(args[1:])
|
func(args[1:])
|
||||||
|
|
||||||
@@ -84,7 +86,7 @@ namespaced_entry_points['hold'] = hold
|
|||||||
namespaced_entry_points['complete'] = complete
|
namespaced_entry_points['complete'] = complete
|
||||||
|
|
||||||
|
|
||||||
def setup_openssl_environment():
|
def setup_openssl_environment() -> None:
|
||||||
# Workaround for Linux distros that have still failed to get their heads
|
# Workaround for Linux distros that have still failed to get their heads
|
||||||
# out of their asses and implement a common location for SSL certificates.
|
# out of their asses and implement a common location for SSL certificates.
|
||||||
# It's not that hard people, there exists a wonderful tool called the symlink
|
# It's not that hard people, there exists a wonderful tool called the symlink
|
||||||
@@ -92,11 +94,13 @@ def setup_openssl_environment():
|
|||||||
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
|
if 'SSL_CERT_FILE' not in os.environ and 'SSL_CERT_DIR' not in os.environ:
|
||||||
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
if os.access('/etc/pki/tls/certs/ca-bundle.crt', os.R_OK):
|
||||||
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
|
os.environ['SSL_CERT_FILE'] = '/etc/pki/tls/certs/ca-bundle.crt'
|
||||||
|
setattr(sys, 'kitty_ssl_env_var', 'SSL_CERT_FILE')
|
||||||
elif os.path.isdir('/etc/ssl/certs'):
|
elif os.path.isdir('/etc/ssl/certs'):
|
||||||
os.environ['SSL_CERT_DIR'] = '/etc/ssl/certs'
|
os.environ['SSL_CERT_DIR'] = '/etc/ssl/certs'
|
||||||
|
setattr(sys, 'kitty_ssl_env_var', 'SSL_CERT_DIR')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
if getattr(sys, 'frozen', False) and 'darwin' not in sys.platform.lower():
|
if getattr(sys, 'frozen', False) and 'darwin' not in sys.platform.lower():
|
||||||
setup_openssl_environment()
|
setup_openssl_environment()
|
||||||
first_arg = '' if len(sys.argv) < 2 else sys.argv[1]
|
first_arg = '' if len(sys.argv) < 2 else sys.argv[1]
|
||||||
@@ -107,8 +111,8 @@ def main():
|
|||||||
elif first_arg.startswith('+'):
|
elif first_arg.startswith('+'):
|
||||||
namespaced(['+', first_arg[1:]] + sys.argv[2:])
|
namespaced(['+', first_arg[1:]] + sys.argv[2:])
|
||||||
else:
|
else:
|
||||||
from kitty.main import main
|
from kitty.main import main as kitty_main
|
||||||
main()
|
kitty_main()
|
||||||
else:
|
else:
|
||||||
func(sys.argv[1:])
|
func(sys.argv[1:])
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* asan-launcher.c
|
|
||||||
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
|
|
||||||
*
|
|
||||||
* Distributed under terms of the GPL3 license.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Python.h>
|
|
||||||
|
|
||||||
#define MAX_ARGC 1024
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
wchar_t *argvw[MAX_ARGC + 1] = {0};
|
|
||||||
argvw[0] = L"kitty";
|
|
||||||
for (int i = 1; i < argc; i++) argvw[i] = Py_DecodeLocale(argv[i], NULL);
|
|
||||||
int ret = Py_Main(argc, argvw);
|
|
||||||
for (int i = 1; i < argc; i++) PyMem_RawFree(argvw[i]);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,27 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env python
|
||||||
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
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
files_to_exclude = '''\
|
||||||
|
kitty/wcwidth-std.h
|
||||||
|
kitty/glfw.c
|
||||||
|
kitty/keys.h
|
||||||
|
kitty/charsets.c
|
||||||
|
kitty/unicode-data.c
|
||||||
|
kitty/key_encoding.py
|
||||||
|
kitty/rgb.py
|
||||||
|
kitty/gl.h
|
||||||
|
kitty/gl-wrapper.h
|
||||||
|
kitty/gl-wrapper.c
|
||||||
|
kitty/glfw-wrapper.h
|
||||||
|
kitty/glfw-wrapper.c
|
||||||
|
kitty/emoji.h
|
||||||
|
kittens/unicode_input/names.h
|
||||||
|
kitty/parse-graphics-command.h
|
||||||
|
'''
|
||||||
|
|
||||||
|
p = subprocess.Popen([
|
||||||
|
'cloc', '--exclude-list-file', '/dev/stdin', 'kitty', 'kittens'
|
||||||
|
], stdin=subprocess.PIPE)
|
||||||
|
p.communicate(files_to_exclude.encode('utf-8'))
|
||||||
|
raise SystemExit(p.wait())
|
||||||
|
|||||||
2
docs/_static/custom.css
vendored
2
docs/_static/custom.css
vendored
@@ -78,6 +78,8 @@ body div.document {
|
|||||||
div.sphinxsidebar {
|
div.sphinxsidebar {
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
line-height: inherit;
|
line-height: inherit;
|
||||||
|
max-height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebartoc li {
|
#sidebartoc li {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Building kitty from source
|
Building kitty from source
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
.. image:: https://circleci.com/gh/kovidgoyal/kitty.svg?style=svg
|
.. image:: https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg
|
||||||
:alt: Build status
|
:alt: Build status
|
||||||
:target: https://circleci.com/gh/kovidgoyal/kitty
|
:target: https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI
|
||||||
|
|
||||||
|
|
||||||
|kitty| is designed to run from source, for easy hackability. Make sure
|
|kitty| is designed to run from source, for easy hackability. Make sure
|
||||||
@@ -20,6 +20,7 @@ Run-time dependencies:
|
|||||||
* libpng
|
* libpng
|
||||||
* freetype (not needed on macOS)
|
* freetype (not needed on macOS)
|
||||||
* fontconfig (not needed on macOS)
|
* fontconfig (not needed on macOS)
|
||||||
|
* libcanberra (not needed on macOS)
|
||||||
* ImageMagick (optional, needed to use the ``kitty icat`` tool to display images in the terminal)
|
* ImageMagick (optional, needed to use the ``kitty icat`` tool to display images in the terminal)
|
||||||
* pygments (optional, need for syntax highlighting in ``kitty +kitten diff``)
|
* pygments (optional, need for syntax highlighting in ``kitty +kitten diff``)
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ Build-time dependencies:
|
|||||||
* gcc or clang
|
* gcc or clang
|
||||||
* pkg-config
|
* pkg-config
|
||||||
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for:
|
* 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``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev`` and ``libpython-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.
|
if they are not already installed by your distro.
|
||||||
|
|
||||||
Install and run from source
|
Install and run from source
|
||||||
@@ -44,25 +45,17 @@ Now build the native code parts of |kitty| with the following command::
|
|||||||
|
|
||||||
You can run |kitty|, as::
|
You can run |kitty|, as::
|
||||||
|
|
||||||
python3 .
|
./kitty/launcher/kitty
|
||||||
|
|
||||||
If that works, you can create a script to launch |kitty|:
|
If that works, you can create a symlink to the launcher in :file:`~/bin` or
|
||||||
|
some other directory on your PATH so that you can run |kitty| using
|
||||||
.. code-block:: sh
|
|
||||||
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
import runpy
|
|
||||||
runpy.run_path('/path/to/kitty/dir', run_name='__main__')
|
|
||||||
|
|
||||||
And place it in :file:`~/bin` or :file:`/usr/bin` so that you can run |kitty| using
|
|
||||||
just ``kitty``.
|
just ``kitty``.
|
||||||
|
|
||||||
|
|
||||||
Building kitty.app on macOS from source
|
Building kitty.app on macOS from source
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
Install `imagemagick`, `optipng` and `librsvg` using `brew` or similar (needed
|
Run::
|
||||||
for the logo generation step). And run::
|
|
||||||
|
|
||||||
make app
|
make app
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,392 @@ Changelog
|
|||||||
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
|
||||||
To update |kitty|, :doc:`follow the instructions <binary>`.
|
To update |kitty|, :doc:`follow the instructions <binary>`.
|
||||||
|
|
||||||
|
0.17.2 [2020-03-29]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Add a :option:`launch --watcher` option that allows defining callbacks
|
||||||
|
that are called for various events in the window's life-cycle (:iss:`2440`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that broke drawing of borders with non-minimal
|
||||||
|
borders (:iss:`2474`)
|
||||||
|
|
||||||
|
- Hints kitten: Allow copying to primary selection as well as clipboard
|
||||||
|
(:pull:`2487`)
|
||||||
|
|
||||||
|
- Add a new mappable action ``close_other_windows_in_tab`` to close all but the
|
||||||
|
active window (:iss:`2484`)
|
||||||
|
|
||||||
|
- Hints kitten: Adjust the default regex used to detect line numbers to handle
|
||||||
|
line+column numbers (:iss:`2268`)
|
||||||
|
|
||||||
|
- Fix blank space at the start of tab bar in the powerline style when first tab is
|
||||||
|
inactive (:iss:`2478`)
|
||||||
|
|
||||||
|
- Fix regression causing incorrect rendering of separators in tab bar when
|
||||||
|
defining a tab bar background color (:pull:`2480`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that broke the kitty @ launch remote command and
|
||||||
|
also broke the --tab-title option when creating a new tab. (:iss:`2488`)
|
||||||
|
|
||||||
|
- Linux: Fix selection of fonts with multiple width variants not preferring
|
||||||
|
the normal width faces (:iss:`2491`)
|
||||||
|
|
||||||
|
|
||||||
|
0.17.1 [2020-03-24]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Fix :opt:`cursor_underline_thickness` not working (:iss:`2465`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that caused tab bar background to be rendered after
|
||||||
|
the last tab as well (:iss:`2464`)
|
||||||
|
|
||||||
|
- macOS: Fix a regression in 0.17 that caused incorrect variants to be
|
||||||
|
automatically selected for some fonts (:iss:`2462`)
|
||||||
|
|
||||||
|
- Fix a regression in 0.17 that caused kitty @ set-colors to require setting
|
||||||
|
cursor_text_color (:iss:`2470`)
|
||||||
|
|
||||||
|
|
||||||
|
0.17.0 [2020-03-24]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- :ref:`splits_layout` to arrange windows in arbitrary splits
|
||||||
|
(:iss:`2308`)
|
||||||
|
|
||||||
|
- Add support for specifying a background image, see :opt:`background_image`
|
||||||
|
(:iss:`163` and :pull:`2326`; thanks to Fredrick Brennan.)
|
||||||
|
|
||||||
|
- A new :opt:`background_tint` option to darken the background under the text
|
||||||
|
area when using background images and/or transparent windows.
|
||||||
|
|
||||||
|
- Allow selection of single cells with the mouse. Also improve mouse selection
|
||||||
|
to follow semantics common to most programs (:iss:`945`)
|
||||||
|
|
||||||
|
- New options :opt:`cursor_beam_thickness` and :opt:`cursor_underline_thickness` to control the thickness of the
|
||||||
|
beam and underline cursors (:iss:`2337` and :pull:`2342`)
|
||||||
|
|
||||||
|
- When the application running in the terminal grabs the mouse, pass middle
|
||||||
|
clicks to the application unless :opt:`terminal_select_modifiers` are
|
||||||
|
pressed (:iss:`2368`)
|
||||||
|
|
||||||
|
- A new ``copy_and_clear_or_interrupt`` function (:iss:`2403`)
|
||||||
|
|
||||||
|
- X11: Fix arrow mouse cursor using right pointing instead of the default left
|
||||||
|
pointing arrow (:iss:`2341`)
|
||||||
|
|
||||||
|
- Allow passing the currently active kitty window id in the launch command
|
||||||
|
(:iss:`2391`)
|
||||||
|
|
||||||
|
- unicode input kitten: Allow pressing :kbd:`ctrl+tab` to change the input mode
|
||||||
|
(:iss:`2343`)
|
||||||
|
|
||||||
|
- Fix a bug that prevented using custom functions with the new marks feature
|
||||||
|
(:iss:`2344`)
|
||||||
|
|
||||||
|
- Make the set of URL prefixes that are recognized while hovering with the
|
||||||
|
mouse configurable (:iss:`2416`)
|
||||||
|
|
||||||
|
- Fix border/margin/padding sizes not being recalculated on DPI change
|
||||||
|
(:iss:`2346`)
|
||||||
|
|
||||||
|
- diff kitten: Fix directory diffing with removed binary files failing
|
||||||
|
(:iss:`2378`)
|
||||||
|
|
||||||
|
- macOS: Fix menubar title not updating on OS Window focus change (:iss:`2350`)
|
||||||
|
|
||||||
|
- Fix rendering of combining characters with fonts that have glyphs for
|
||||||
|
precomposed characters but not decomposed versions (:iss:`2365`)
|
||||||
|
|
||||||
|
- Fix incorrect rendering of selection when using rectangular select and
|
||||||
|
scrolling (:iss:`2351`)
|
||||||
|
|
||||||
|
- Allow setting WM_CLASS and WM_NAME when creating new OS windows with the
|
||||||
|
launch command (:option:`launch --os-window-class`)
|
||||||
|
|
||||||
|
- macOS: When switching input method while a pending multi-key input is in
|
||||||
|
progress, clear the pending input (:iss:`2358`)
|
||||||
|
|
||||||
|
- Fix a regression in the previous release that broke switching to neighboring windows
|
||||||
|
in the Grid layout when there are less than four windows (:iss:`2377`)
|
||||||
|
|
||||||
|
- Fix colors in scrollback pager off if the window has redefined terminal
|
||||||
|
colors using escape codes (:iss:`2381`)
|
||||||
|
|
||||||
|
- Fix selection not updating properly while scrolling (:iss:`2442`)
|
||||||
|
|
||||||
|
- Allow extending selections by dragging with right button pressed
|
||||||
|
(:iss:`2445`)
|
||||||
|
|
||||||
|
- Workaround for bug in less that causes colors to reset at wrapped lines
|
||||||
|
(:iss:`2381`)
|
||||||
|
|
||||||
|
- X11/Wayland: Allow drag and drop of text/plain in addition to text/uri-list
|
||||||
|
(:iss:`2441`)
|
||||||
|
|
||||||
|
- Dont strip :code:`&` and :code:`-` from the end of URLs (:iss:`2436`)
|
||||||
|
|
||||||
|
- Fix ``@selection`` placeholder not working with launch command (:iss:`2417`)
|
||||||
|
|
||||||
|
- Drop support for python 3.5
|
||||||
|
|
||||||
|
- Wayland: Fix a crash when drag and dropping into kitty (:iss:`2432`)
|
||||||
|
|
||||||
|
- diff kitten: Fix images lingering as blank rectangles after the kitten quits
|
||||||
|
(:iss:`2449`)
|
||||||
|
|
||||||
|
- diff kitten: Fix images losing position when scrolling using mouse
|
||||||
|
wheel/touchpad
|
||||||
|
|
||||||
|
|
||||||
|
0.16.0 [2020-01-28]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- A new :doc:`marks` feature that allows highlighting and scrolling to arbitrary
|
||||||
|
text in the terminal window.
|
||||||
|
|
||||||
|
- hints kitten: Allow pressing :sc:`goto_file_line` to quickly open
|
||||||
|
the selected file at the selected line in vim or a configurable editor (:iss:`2268`)
|
||||||
|
|
||||||
|
- Allow having more than one full height window in the :code:`tall` layout
|
||||||
|
(:iss:`2276`)
|
||||||
|
|
||||||
|
- Allow choosing OpenType features for individual fonts via the
|
||||||
|
:opt:`font_features` option. (:pull:`2248`)
|
||||||
|
|
||||||
|
- Wayland: Fix a freeze in rare circumstances when having multiple OS Windows
|
||||||
|
(:iss:`2307` and :iss:`1722`)
|
||||||
|
|
||||||
|
- Wayland: Fix window titles being set to very long strings on the order of 8KB
|
||||||
|
causing a crash (:iss:`1526`)
|
||||||
|
|
||||||
|
- Add an option :opt:`force_ltr` to turn off the display of text in RTL scripts
|
||||||
|
in right-to-left order (:pull:`2293`)
|
||||||
|
|
||||||
|
- Allow opening new tabs/windows before the current tab/window as well as after
|
||||||
|
it with the :option:`launch --location` option.
|
||||||
|
|
||||||
|
- Add a :opt:`resize_in_steps` option that can be used to resize the OS window
|
||||||
|
in steps as large as character cells (:pull:`2131`)
|
||||||
|
|
||||||
|
- When triple-click+dragging to select multiple lines, extend the selection
|
||||||
|
of the first line to match the rest on the left (:pull:`2284`)
|
||||||
|
|
||||||
|
- macOS: Add a :code:`titlebar-only` setting to
|
||||||
|
:opt:`hide_window_decorations` to only hide the title bar (:pull:`2286`)
|
||||||
|
|
||||||
|
- Fix a segfault when using :option:`kitty --debug-config` with maps (:iss:`2270`)
|
||||||
|
|
||||||
|
- ``goto_tab`` now maps numbers larger than the last tab to the last tab
|
||||||
|
(:iss:`2291`)
|
||||||
|
|
||||||
|
- Fix URL detection not working for urls of the form scheme:///url
|
||||||
|
(:iss:`2292`)
|
||||||
|
|
||||||
|
- When windows are semi-transparent and all contain graphics, correctly render
|
||||||
|
them. (:iss:`2310`)
|
||||||
|
|
||||||
|
0.15.1 [2019-12-21]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Fix a crash/incorrect rendering when detaching a window in some circumstances
|
||||||
|
(:iss:`2173`)
|
||||||
|
|
||||||
|
- hints kitten: Add an option :option:`kitty +kitten hints --ascending` to
|
||||||
|
control if the hints numbers increase or decrease from top to bottom
|
||||||
|
|
||||||
|
- Fix :opt:`background_opacity` incorrectly applying to selected text and
|
||||||
|
reverse video text (:iss:`2177`)
|
||||||
|
|
||||||
|
- Add a new option :opt:`tab_bar_background` to specify a different color
|
||||||
|
for the tab bar (:iss:`2198`)
|
||||||
|
|
||||||
|
- Add a new option :opt:`active_tab_title_template` to specify a different
|
||||||
|
template for active tab titles (:iss:`2198`)
|
||||||
|
|
||||||
|
- Fix lines at the edge of the window at certain windows sizes when drawing
|
||||||
|
images on a transparent window (:iss:`2079`)
|
||||||
|
|
||||||
|
- Fix window not being rendered for the first time until some input has been
|
||||||
|
received from child process (:iss:`2216`)
|
||||||
|
|
||||||
|
|
||||||
|
0.15.0 [2019-11-27]
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
- Add a new action :ref:`detach_window <detach_window>` that can be used to move the current
|
||||||
|
window into a different tab (:iss:`1310`)
|
||||||
|
|
||||||
|
- Add a new action :doc:`launch <launch>` that unifies launching of processes
|
||||||
|
in new kitty windows/tabs.
|
||||||
|
|
||||||
|
- Add a new style ``powerline`` for tab bar rendering, see :opt:`tab_bar_style` (:pull:`2021`)
|
||||||
|
|
||||||
|
- Allow changing colors by mapping a keyboard shortcut to read a kitty config
|
||||||
|
file with color definitions. See the :doc:`FAQ <faq>` for details
|
||||||
|
(:iss:`2083`)
|
||||||
|
|
||||||
|
- hints kitten: Allow completely customizing the matching and actions performed
|
||||||
|
by the kitten using your own script (:iss:`2124`)
|
||||||
|
|
||||||
|
- Wayland: Fix key repeat not being stopped when focus leaves window. This is
|
||||||
|
expected behavior on Wayland, apparently (:iss:`2014`)
|
||||||
|
|
||||||
|
- When drawing unicode symbols that are followed by spaces, use multiple cells
|
||||||
|
to avoid resized or cut-off glyphs (:iss:`1452`)
|
||||||
|
|
||||||
|
- diff kitten: Allow diffing remote files easily via ssh (:iss:`727`)
|
||||||
|
|
||||||
|
- unicode input kitten: Add an option :option:`kitty +kitten unicode_input
|
||||||
|
--emoji-variation` to control the presentation variant of selected emojis
|
||||||
|
(:iss:`2139`)
|
||||||
|
|
||||||
|
- Add specialised rendering for a few more box powerline and unicode symbols
|
||||||
|
(:pull:`2074` and :pull:`2021`)
|
||||||
|
|
||||||
|
- Add a new socket only mode for :opt:`allow_remote_control`. This makes
|
||||||
|
it possible for programs running on the local machine to control kitty
|
||||||
|
but not programs running over ssh.
|
||||||
|
|
||||||
|
- hints kitten: Allow using named groups in the regular expression. The named
|
||||||
|
groups are passed to the invoked program for further processing.
|
||||||
|
|
||||||
|
- Fix a regression in 0.14.5 that caused rendering of private use glyphs
|
||||||
|
with and without spaces to be identical (:iss:`2117`)
|
||||||
|
|
||||||
|
- Wayland: Fix incorrect scale used when first creating an OS window
|
||||||
|
(:iss:`2133`)
|
||||||
|
|
||||||
|
- macOS: Disable mouse hiding by default as getting it to work robustly
|
||||||
|
on Cocoa is too much effort (:iss:`2158`)
|
||||||
|
|
||||||
|
|
||||||
|
0.14.6 [2019-09-25]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- macOS: Fix a regression in the previous release that caused a crash when
|
||||||
|
pressing a unprintable key, such as the POWER key (:iss:`1997`)
|
||||||
|
|
||||||
|
- Fix a regression in the previous release that caused kitty to not always
|
||||||
|
respond to DPI changes (:pull:`1999`)
|
||||||
|
|
||||||
|
|
||||||
|
0.14.5 [2019-09-23]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Implement a hack to (mostly) preserve tabs when cat-ting a file with them and then
|
||||||
|
copying the text or passing screen contents to another program (:iss:`1829`)
|
||||||
|
|
||||||
|
- When all visible windows have the same background color, use that as the
|
||||||
|
color for the global padding, instead of the configured background color
|
||||||
|
(:iss:`1957`)
|
||||||
|
|
||||||
|
- When resetting the terminal, also reset parser state, this allows easy
|
||||||
|
recovery from incomplete escape codes (:iss:`1961`)
|
||||||
|
|
||||||
|
- Allow mapping keys commonly found on European keyboards (:pull:`1928`)
|
||||||
|
|
||||||
|
- Fix incorrect rendering of some symbols when followed by a space while using
|
||||||
|
the PowerLine font which does not have a space glyph (:iss:`1225`)
|
||||||
|
|
||||||
|
- Linux: Allow using fonts with spacing=90 in addition to fonts with
|
||||||
|
spacing=100 (:iss:`1968`)
|
||||||
|
|
||||||
|
- Use selection foreground color for underlines as well (:iss:`1982`)
|
||||||
|
|
||||||
|
0.14.4 [2019-08-31]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- hints kitten: Add a :option:`kitty +kitten hints --alphabet` option to
|
||||||
|
control what alphabets are used for hints (:iss:`1879`)
|
||||||
|
|
||||||
|
- hints kitten: Allow specifying :option:`kitty +kitten hints --program`
|
||||||
|
multiple times to run multiple programs (:iss:`1879`)
|
||||||
|
|
||||||
|
- Add a :opt:`kitten_alias` option that can be used to alias kitten invocation
|
||||||
|
for brevity and to change kitten option defaults globally (:iss:`1879`)
|
||||||
|
|
||||||
|
- macOS: Add an option :opt:`macos_show_window_title_in` to control
|
||||||
|
showing the window title in the menubar/titlebar (:pull:`1837`)
|
||||||
|
|
||||||
|
- macOS: Allow drag and drop of text from other applications into kitty
|
||||||
|
(:pull:`1921`)
|
||||||
|
|
||||||
|
- When running kittens, use the colorscheme of the current window
|
||||||
|
rather than the configured colorscheme (:iss:`1906`)
|
||||||
|
|
||||||
|
- Don't fail to start if running the shell to read the EDITOR env var fails
|
||||||
|
(:iss:`1869`)
|
||||||
|
|
||||||
|
- Disable the ``liga`` and ``dlig`` OpenType features for broken fonts
|
||||||
|
such as Nimbus Mono.
|
||||||
|
|
||||||
|
- Fix a regression that broke setting background_opacity via remote control
|
||||||
|
(:iss:`1895`)
|
||||||
|
|
||||||
|
- Fix piping PNG images into the icat kitten not working (:iss:`1920`)
|
||||||
|
|
||||||
|
- When the OS returns a fallback font that does not actually contain glyphs
|
||||||
|
for the text, do not exhaust the list of fallback fonts (:iss:`1918`)
|
||||||
|
|
||||||
|
- Fix formatting attributes not reset across line boundaries when passing
|
||||||
|
buffer as ANSI (:iss:`1924`)
|
||||||
|
|
||||||
|
|
||||||
|
0.14.3 [2019-07-29]
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
- Remote control: Add a command `kitty @ scroll-window` to scroll windows
|
||||||
|
|
||||||
|
- Allow passing a ``!neighbor`` argument to the new_window mapping to open a
|
||||||
|
new window next to the active window (:iss:`1746`)
|
||||||
|
|
||||||
|
- Document the kitty remote control protocol (:iss:`1646`)
|
||||||
|
|
||||||
|
- Add a new option :opt:`pointer_shape_when_grabbed` that allows you to control
|
||||||
|
the mouse pointer shape when the terminal programs grabs the pointer
|
||||||
|
(:iss:`1808`)
|
||||||
|
|
||||||
|
- Add an option :opt:`terminal_select_modifiers` to control which modifiers
|
||||||
|
are used to override mouse selection even when a terminal application has
|
||||||
|
grabbed the mouse (:iss:`1774`)
|
||||||
|
|
||||||
|
- When piping data to a child in the pipe command do it in a thread so as not
|
||||||
|
to block the UI (:iss:`1708`)
|
||||||
|
|
||||||
|
- unicode_input kitten: Fix a regression that broke using indices to select
|
||||||
|
recently used symbols.
|
||||||
|
|
||||||
|
- Fix a regression that caused closing an overlay window to focus
|
||||||
|
the previously focused window rather than the underlying window (:iss:`1720`)
|
||||||
|
|
||||||
|
- macOS: Reduce energy consumption when idle by shutting down Apple's display
|
||||||
|
link thread after 30 second of inactivity (:iss:`1763`)
|
||||||
|
|
||||||
|
- Linux: Fix incorrect scaling for fallback fonts when the font has an
|
||||||
|
underscore that renders out of bounds (:iss:`1713`)
|
||||||
|
|
||||||
|
- macOS: Fix finding fallback font for private use unicode symbols not working
|
||||||
|
reliably (:iss:`1650`)
|
||||||
|
|
||||||
|
- Fix an out of bounds read causing a crash when selecting text with the mouse
|
||||||
|
in the alternate screen mode (:iss:`1578`)
|
||||||
|
|
||||||
|
- Linux: Use the system "bell" sound for the terminal bell. Adds libcanberra
|
||||||
|
as a new dependency to play the system sound.
|
||||||
|
|
||||||
|
- macOS: Fix a rare deadlock causing kitty to hang (:iss:`1779`)
|
||||||
|
|
||||||
|
- Linux: Fix a regression in 0.14.0 that caused the event loop to tick
|
||||||
|
continuously, wasting CPU even when idle (:iss:`1782`)
|
||||||
|
|
||||||
|
- ssh kitten: Make argument parsing more like ssh (:iss:`1787`)
|
||||||
|
|
||||||
|
- When using :opt:`strip_trailing_spaces` do not remove empty lines
|
||||||
|
(:iss:`1802`)
|
||||||
|
|
||||||
|
- Fix a crash when displaying very large number of images (:iss:`1825`)
|
||||||
|
|
||||||
|
|
||||||
0.14.2 [2019-06-09]
|
0.14.2 [2019-06-09]
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
@@ -137,7 +523,7 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
|||||||
|
|
||||||
- macOS: Fix :kbd:`cmd+period` key not working (:iss:`1318`)
|
- macOS: Fix :kbd:`cmd+period` key not working (:iss:`1318`)
|
||||||
|
|
||||||
- macOS: Add an option :opt:`macos_show_window_title_in_menubar` to not
|
- macOS: Add an option `macos_show_window_title_in_menubar` to not
|
||||||
show the current window title in the menu-bar (:iss:`1066`)
|
show the current window title in the menu-bar (:iss:`1066`)
|
||||||
|
|
||||||
- macOS: Workaround for cocoa bug that could cause the mouse cursor to become
|
- macOS: Workaround for cocoa bug that could cause the mouse cursor to become
|
||||||
|
|||||||
164
docs/conf.py
164
docs/conf.py
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# vim:fileencoding=utf-8
|
||||||
#
|
#
|
||||||
# Configuration file for the Sphinx documentation builder.
|
# Configuration file for the Sphinx documentation builder.
|
||||||
#
|
#
|
||||||
@@ -7,28 +7,34 @@
|
|||||||
# full list see the documentation:
|
# full list see the documentation:
|
||||||
# https://www.sphinx-doc.org/en/master/config
|
# https://www.sphinx-doc.org/en/master/config
|
||||||
|
|
||||||
import importlib
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from typing import (
|
||||||
|
Any, Callable, Dict, Iterable, List, Match, Optional, Sequence, Tuple,
|
||||||
|
Union
|
||||||
|
)
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst.roles import set_classes
|
from docutils.parsers.rst.roles import set_classes
|
||||||
from pygments.lexer import RegexLexer, bygroups
|
from pygments.lexer import RegexLexer, bygroups # type: ignore
|
||||||
from pygments.token import (
|
from pygments.token import ( # type: ignore
|
||||||
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
Comment, Keyword, Literal, Name, Number, String, Whitespace
|
||||||
)
|
)
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes # type: ignore
|
||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree # type: ignore
|
||||||
from sphinx.util.logging import getLogger
|
from sphinx.util.logging import getLogger # type: ignore
|
||||||
|
|
||||||
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
kitty_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
if kitty_src not in sys.path:
|
if kitty_src not in sys.path:
|
||||||
sys.path.insert(0, kitty_src)
|
sys.path.insert(0, kitty_src)
|
||||||
str_version = importlib.import_module('kitty.constants').str_version
|
|
||||||
|
from kitty.conf.definition import Option, Shortcut # noqa
|
||||||
|
from kitty.constants import str_version # noqa
|
||||||
|
|
||||||
|
|
||||||
# config {{{
|
# config {{{
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
@@ -77,7 +83,7 @@ master_doc = 'index'
|
|||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = None
|
language: Optional[str] = None
|
||||||
|
|
||||||
# List of patterns, relative to source directory, that match files and
|
# List of patterns, relative to source directory, that match files and
|
||||||
# directories to ignore when looking for source files.
|
# directories to ignore when looking for source files.
|
||||||
@@ -184,7 +190,7 @@ texinfo_documents = [
|
|||||||
|
|
||||||
# GitHub linking inline roles {{{
|
# GitHub linking inline roles {{{
|
||||||
|
|
||||||
def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def num_role(which: str, name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
' Link to a github issue '
|
' Link to a github issue '
|
||||||
try:
|
try:
|
||||||
issue_num = int(text)
|
issue_num = int(text)
|
||||||
@@ -202,10 +208,11 @@ def num_role(which, name, rawtext, text, lineno, inliner, options={}, content=[]
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def commit_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
' Link to a github commit '
|
' Link to a github commit '
|
||||||
try:
|
try:
|
||||||
commit_id = subprocess.check_output(f'git rev-list --max-count=1 --skip=# {text}'.split()).decode('utf-8').strip()
|
commit_id = subprocess.check_output(
|
||||||
|
f'git rev-list --max-count=1 --skip=# {text}'.split()).decode('utf-8').strip()
|
||||||
except Exception:
|
except Exception:
|
||||||
msg = inliner.reporter.error(
|
msg = inliner.reporter.error(
|
||||||
f'GitHub commit id "{text}" not recognized.', line=lineno)
|
f'GitHub commit id "{text}" not recognized.', line=lineno)
|
||||||
@@ -213,21 +220,22 @@ def commit_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [prb], [msg]
|
return [prb], [msg]
|
||||||
url = f'https://github.com/kovidgoyal/kitty/commit/{commit_id}'
|
url = f'https://github.com/kovidgoyal/kitty/commit/{commit_id}'
|
||||||
set_classes(options)
|
set_classes(options)
|
||||||
short_id = subprocess.check_output(f'git rev-list --max-count=1 --abbrev-commit --skip=# {commit_id}'.split()).decode('utf-8').strip()
|
short_id = subprocess.check_output(
|
||||||
|
f'git rev-list --max-count=1 --abbrev-commit --skip=# {commit_id}'.split()).decode('utf-8').strip()
|
||||||
node = nodes.reference(rawtext, f'commit: {short_id}', refuri=url, **options)
|
node = nodes.reference(rawtext, f'commit: {short_id}', refuri=url, **options)
|
||||||
return [node], []
|
return [node], []
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# Sidebar ToC {{{
|
# Sidebar ToC {{{
|
||||||
def create_toc(app, pagename):
|
def create_toc(app: Any, pagename: str) -> Optional[Any]:
|
||||||
tt = TocTree(app.env)
|
tt = TocTree(app.env)
|
||||||
toctree = tt.get_toc_for(pagename, app.builder)
|
toctree = tt.get_toc_for(pagename, app.builder)
|
||||||
if toctree is not None:
|
if toctree is not None:
|
||||||
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
subtree = toctree[toctree.first_child_matching_class(nodes.list_item)]
|
||||||
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
bl = subtree.first_child_matching_class(nodes.bullet_list)
|
||||||
if bl is None:
|
if bl is None:
|
||||||
return # Empty ToC
|
return None # Empty ToC
|
||||||
subtree = subtree[bl]
|
subtree = subtree[bl]
|
||||||
# for li in subtree.traverse(nodes.list_item):
|
# for li in subtree.traverse(nodes.list_item):
|
||||||
# modify_li(li)
|
# modify_li(li)
|
||||||
@@ -235,29 +243,40 @@ def create_toc(app, pagename):
|
|||||||
return app.builder.render_partial(subtree)['fragment']
|
return app.builder.render_partial(subtree)['fragment']
|
||||||
|
|
||||||
|
|
||||||
def add_html_context(app, pagename, templatename, context, *args):
|
def add_html_context(app: Any, pagename: str, templatename: str, context: Any, *args: Any) -> None:
|
||||||
if 'toc' in context:
|
if 'toc' in context:
|
||||||
context['toc'] = create_toc(app, pagename) or context['toc']
|
context['toc'] = create_toc(app, pagename) or context['toc']
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# CLI docs {{{
|
# CLI docs {{{
|
||||||
def write_cli_docs(all_kitten_names):
|
def write_cli_docs(all_kitten_names: Iterable[str]) -> None:
|
||||||
|
from kitty.launch import options_spec as launch_options_spec
|
||||||
from kitty.cli import option_spec_as_rst
|
from kitty.cli import option_spec_as_rst
|
||||||
|
with open('generated/launch.rst', 'w') as f:
|
||||||
|
f.write(option_spec_as_rst(
|
||||||
|
appname='launch', ospec=launch_options_spec, heading_char='_',
|
||||||
|
message='''\
|
||||||
|
Launch an arbitrary program in a new kitty window/tab. Note that
|
||||||
|
if you specify a program-to-run you can use the special placeholder
|
||||||
|
:code:`@selection` which will be replaced by the current selection.
|
||||||
|
'''
|
||||||
|
))
|
||||||
with open('generated/cli-kitty.rst', 'w') as f:
|
with open('generated/cli-kitty.rst', 'w') as f:
|
||||||
f.write(option_spec_as_rst(appname='kitty').replace(
|
f.write(option_spec_as_rst(appname='kitty').replace(
|
||||||
'kitty --to', 'kitty @ --to'))
|
'kitty --to', 'kitty @ --to'))
|
||||||
as_rst = partial(option_spec_as_rst, heading_char='_')
|
as_rst = partial(option_spec_as_rst, heading_char='_')
|
||||||
from kitty.remote_control import global_options_spec, cli_msg, cmap, all_commands
|
from kitty.rc.base import all_command_names, command_for_name
|
||||||
|
from kitty.remote_control import global_options_spec, cli_msg
|
||||||
with open('generated/cli-kitty-at.rst', 'w') as f:
|
with open('generated/cli-kitty-at.rst', 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('kitty @\n' + '-' * 80)
|
p('kitty @\n' + '-' * 80)
|
||||||
p('.. program::', 'kitty @')
|
p('.. program::', 'kitty @')
|
||||||
p('\n\n' + as_rst(
|
p('\n\n' + as_rst(
|
||||||
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
global_options_spec, message=cli_msg, usage='command ...', appname='kitty @'))
|
||||||
from kitty.cmds import cli_params_for
|
from kitty.rc.base import cli_params_for
|
||||||
for cmd_name in all_commands:
|
for cmd_name in all_command_names():
|
||||||
func = cmap[cmd_name]
|
func = command_for_name(cmd_name)
|
||||||
p(f'.. _at_{func.name}:\n')
|
p(f'.. _at_{func.name}:\n')
|
||||||
p('kitty @', func.name + '\n' + '-' * 120)
|
p('kitty @', func.name + '\n' + '-' * 120)
|
||||||
p('.. program::', 'kitty @', func.name)
|
p('.. program::', 'kitty @', func.name)
|
||||||
@@ -276,6 +295,48 @@ def write_cli_docs(all_kitten_names):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
def write_remote_control_protocol_docs() -> None: # {{{
|
||||||
|
from kitty.rc.base import all_command_names, command_for_name, RemoteCommand
|
||||||
|
field_pat = re.compile(r'\s*([a-zA-Z0-9_+]+)\s*:\s*(.+)')
|
||||||
|
|
||||||
|
def format_cmd(p: Callable, name: str, cmd: RemoteCommand) -> None:
|
||||||
|
p(name)
|
||||||
|
p('-' * 80)
|
||||||
|
lines = (cmd.__doc__ or '').strip().splitlines()
|
||||||
|
fields = []
|
||||||
|
for line in lines:
|
||||||
|
m = field_pat.match(line)
|
||||||
|
if m is None:
|
||||||
|
p(line)
|
||||||
|
else:
|
||||||
|
fields.append((m.group(1), m.group(2)))
|
||||||
|
if fields:
|
||||||
|
p('\nFields are:\n')
|
||||||
|
for (name, desc) in fields:
|
||||||
|
if '+' in name:
|
||||||
|
title = name.replace('+', ' (required)')
|
||||||
|
else:
|
||||||
|
title = name
|
||||||
|
defval = cmd.get_default(name.replace('-', '_'), cmd)
|
||||||
|
if defval is not cmd:
|
||||||
|
title = f'{title} (default: {defval})'
|
||||||
|
else:
|
||||||
|
title = f'{title} (optional)'
|
||||||
|
p(f':code:`{title}`')
|
||||||
|
p(' ', desc), p()
|
||||||
|
p(), p()
|
||||||
|
|
||||||
|
with open(f'generated/rc.rst', 'w') as f:
|
||||||
|
p = partial(print, file=f)
|
||||||
|
for name in sorted(all_command_names()):
|
||||||
|
cmd = command_for_name(name)
|
||||||
|
if not cmd.__doc__:
|
||||||
|
continue
|
||||||
|
name = name.replace('_', '-')
|
||||||
|
format_cmd(p, name, cmd)
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
# config file docs {{{
|
# config file docs {{{
|
||||||
|
|
||||||
class ConfLexer(RegexLexer):
|
class ConfLexer(RegexLexer):
|
||||||
@@ -331,7 +392,7 @@ class SessionLexer(RegexLexer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def link_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
def link_role(name: str, rawtext: str, text: str, lineno: int, inliner: Any, options: Any = {}, content: Any = []) -> Tuple[List, List]:
|
||||||
m = re.match(r'(.+)\s+<(.+?)>', text)
|
m = re.match(r'(.+)\s+<(.+?)>', text)
|
||||||
if m is None:
|
if m is None:
|
||||||
msg = inliner.reporter.error(f'link "{text}" not recognized', line=lineno)
|
msg = inliner.reporter.error(f'link "{text}" not recognized', line=lineno)
|
||||||
@@ -343,24 +404,24 @@ def link_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
|
|||||||
return [node], []
|
return [node], []
|
||||||
|
|
||||||
|
|
||||||
def expand_opt_references(conf_name, text):
|
def expand_opt_references(conf_name: str, text: str) -> str:
|
||||||
conf_name += '.'
|
conf_name += '.'
|
||||||
|
|
||||||
def expand(m):
|
def expand(m: Match) -> str:
|
||||||
ref = m.group(1)
|
ref = m.group(1)
|
||||||
if '<' not in ref and '.' not in ref:
|
if '<' not in ref and '.' not in ref:
|
||||||
full_ref = conf_name + ref
|
full_ref = conf_name + ref
|
||||||
return ':opt:`{} <{}>`'.format(ref, full_ref)
|
return ':opt:`{} <{}>`'.format(ref, full_ref)
|
||||||
return m.group()
|
return str(m.group())
|
||||||
|
|
||||||
return re.sub(r':opt:`(.+?)`', expand, text)
|
return re.sub(r':opt:`(.+?)`', expand, text)
|
||||||
|
|
||||||
|
|
||||||
opt_aliases = {}
|
opt_aliases: Dict[str, str] = {}
|
||||||
shortcut_slugs = {}
|
shortcut_slugs: Dict[str, Tuple[str, str]] = {}
|
||||||
|
|
||||||
|
|
||||||
def parse_opt_node(env, sig, signode):
|
def parse_opt_node(env: Any, sig: str, signode: Any) -> str:
|
||||||
"""Transform an option description into RST nodes."""
|
"""Transform an option description into RST nodes."""
|
||||||
count = 0
|
count = 0
|
||||||
firstname = ''
|
firstname = ''
|
||||||
@@ -382,22 +443,22 @@ def parse_opt_node(env, sig, signode):
|
|||||||
return firstname
|
return firstname
|
||||||
|
|
||||||
|
|
||||||
def parse_shortcut_node(env, sig, signode):
|
def parse_shortcut_node(env: Any, sig: str, signode: Any) -> str:
|
||||||
"""Transform a shortcut description into RST nodes."""
|
"""Transform a shortcut description into RST nodes."""
|
||||||
conf_name, text = sig.split('.', 1)
|
conf_name, text = sig.split('.', 1)
|
||||||
signode += addnodes.desc_name(text, text)
|
signode += addnodes.desc_name(text, text)
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
|
|
||||||
def render_conf(conf_name, all_options):
|
def render_conf(conf_name: str, all_options: Iterable[Union['Option', Sequence['Shortcut']]]) -> str:
|
||||||
from kitty.conf.definition import merged_opts, Option
|
from kitty.conf.definition import merged_opts, Option, Group
|
||||||
ans = ['.. default-domain:: conf', '']
|
ans = ['.. default-domain:: conf', '']
|
||||||
a = ans.append
|
a = ans.append
|
||||||
current_group = None
|
current_group: Optional[Group] = None
|
||||||
all_options = list(all_options)
|
all_options_ = list(all_options)
|
||||||
kitty_mod = 'kitty_mod'
|
kitty_mod = 'kitty_mod'
|
||||||
|
|
||||||
def render_group(group):
|
def render_group(group: Group) -> None:
|
||||||
a('')
|
a('')
|
||||||
a(f'.. _conf-{conf_name}-{group.name}:')
|
a(f'.. _conf-{conf_name}-{group.name}:')
|
||||||
a('')
|
a('')
|
||||||
@@ -409,11 +470,12 @@ def render_conf(conf_name, all_options):
|
|||||||
a(group.start_text)
|
a(group.start_text)
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
def handle_group_end(group):
|
def handle_group_end(group: Group) -> None:
|
||||||
if group.end_text:
|
if group.end_text:
|
||||||
|
assert current_group is not None
|
||||||
a(''), a(current_group.end_text)
|
a(''), a(current_group.end_text)
|
||||||
|
|
||||||
def handle_group(new_group, new_group_is_shortcut=False):
|
def handle_group(new_group: Group, new_group_is_shortcut: bool = False) -> None:
|
||||||
nonlocal current_group
|
nonlocal current_group
|
||||||
if new_group is not current_group:
|
if new_group is not current_group:
|
||||||
if current_group:
|
if current_group:
|
||||||
@@ -421,14 +483,14 @@ def render_conf(conf_name, all_options):
|
|||||||
current_group = new_group
|
current_group = new_group
|
||||||
render_group(current_group)
|
render_group(current_group)
|
||||||
|
|
||||||
def handle_option(i, opt):
|
def handle_option(i: int, opt: Option) -> None:
|
||||||
nonlocal kitty_mod
|
nonlocal kitty_mod
|
||||||
if not opt.long_text or not opt.add_to_docs:
|
if not opt.long_text or not opt.add_to_docs:
|
||||||
return
|
return
|
||||||
handle_group(opt.group)
|
handle_group(opt.group)
|
||||||
if opt.name == 'kitty_mod':
|
if opt.name == 'kitty_mod':
|
||||||
kitty_mod = opt.defval_as_string
|
kitty_mod = opt.defval_as_string
|
||||||
mopts = list(merged_opts(all_options, opt, i))
|
mopts = list(merged_opts(all_options_, opt, i))
|
||||||
a('.. opt:: ' + ', '.join(conf_name + '.' + mo.name for mo in mopts))
|
a('.. opt:: ' + ', '.join(conf_name + '.' + mo.name for mo in mopts))
|
||||||
a('.. code-block:: conf')
|
a('.. code-block:: conf')
|
||||||
a('')
|
a('')
|
||||||
@@ -440,7 +502,7 @@ def render_conf(conf_name, all_options):
|
|||||||
a(expand_opt_references(conf_name, opt.long_text))
|
a(expand_opt_references(conf_name, opt.long_text))
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
def handle_shortcuts(shortcuts):
|
def handle_shortcuts(shortcuts: Sequence[Shortcut]) -> None:
|
||||||
sc = shortcuts[0]
|
sc = shortcuts[0]
|
||||||
handle_group(sc.group, True)
|
handle_group(sc.group, True)
|
||||||
sc_text = f'{conf_name}.{sc.short_text}'
|
sc_text = f'{conf_name}.{sc.short_text}'
|
||||||
@@ -458,7 +520,7 @@ def render_conf(conf_name, all_options):
|
|||||||
a(expand_opt_references(conf_name, sc.long_text))
|
a(expand_opt_references(conf_name, sc.long_text))
|
||||||
a('')
|
a('')
|
||||||
|
|
||||||
for i, opt in enumerate(all_options):
|
for i, opt in enumerate(all_options_):
|
||||||
if isinstance(opt, Option):
|
if isinstance(opt, Option):
|
||||||
handle_option(i, opt)
|
handle_option(i, opt)
|
||||||
else:
|
else:
|
||||||
@@ -469,7 +531,7 @@ def render_conf(conf_name, all_options):
|
|||||||
return '\n'.join(ans)
|
return '\n'.join(ans)
|
||||||
|
|
||||||
|
|
||||||
def process_opt_link(env, refnode, has_explicit_title, title, target):
|
def process_opt_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, opt = target.partition('.')[::2]
|
conf_name, opt = target.partition('.')[::2]
|
||||||
if not opt:
|
if not opt:
|
||||||
conf_name, opt = 'kitty', conf_name
|
conf_name, opt = 'kitty', conf_name
|
||||||
@@ -477,19 +539,22 @@ def process_opt_link(env, refnode, has_explicit_title, title, target):
|
|||||||
return title, opt_aliases.get(full_name, full_name)
|
return title, opt_aliases.get(full_name, full_name)
|
||||||
|
|
||||||
|
|
||||||
def process_shortcut_link(env, refnode, has_explicit_title, title, target):
|
def process_shortcut_link(env: Any, refnode: Any, has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
conf_name, slug = target.partition('.')[::2]
|
conf_name, slug = target.partition('.')[::2]
|
||||||
if not slug:
|
if not slug:
|
||||||
conf_name, slug = 'kitty', conf_name
|
conf_name, slug = 'kitty', conf_name
|
||||||
full_name = conf_name + '.' + slug
|
full_name = conf_name + '.' + slug
|
||||||
try:
|
try:
|
||||||
target, title = shortcut_slugs[full_name]
|
target, stitle = shortcut_slugs[full_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.warning('Unknown shortcut: {}'.format(target), location=refnode)
|
logger.warning('Unknown shortcut: {}'.format(target), location=refnode)
|
||||||
|
else:
|
||||||
|
if not has_explicit_title:
|
||||||
|
title = stitle
|
||||||
return title, target
|
return title, target
|
||||||
|
|
||||||
|
|
||||||
def write_conf_docs(app, all_kitten_names):
|
def write_conf_docs(app: Any, all_kitten_names: Iterable[str]) -> None:
|
||||||
app.add_lexer('conf', ConfLexer())
|
app.add_lexer('conf', ConfLexer())
|
||||||
app.add_object_type(
|
app.add_object_type(
|
||||||
'opt', 'opt',
|
'opt', 'opt',
|
||||||
@@ -510,7 +575,7 @@ def write_conf_docs(app, all_kitten_names):
|
|||||||
sc_role.warn_dangling = True
|
sc_role.warn_dangling = True
|
||||||
sc_role.process_link = process_shortcut_link
|
sc_role.process_link = process_shortcut_link
|
||||||
|
|
||||||
def generate_default_config(all_options, name):
|
def generate_default_config(all_options: Dict[str, Union[Option, Sequence[Shortcut]]], name: str) -> None:
|
||||||
from kitty.conf.definition import as_conf_file
|
from kitty.conf.definition import as_conf_file
|
||||||
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
with open(f'generated/conf-{name}.rst', 'w', encoding='utf-8') as f:
|
||||||
print('.. highlight:: conf\n', file=f)
|
print('.. highlight:: conf\n', file=f)
|
||||||
@@ -532,12 +597,13 @@ def write_conf_docs(app, all_kitten_names):
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app: Any) -> None:
|
||||||
os.makedirs('generated/conf', exist_ok=True)
|
os.makedirs('generated/conf', exist_ok=True)
|
||||||
from kittens.runner import all_kitten_names
|
from kittens.runner import all_kitten_names
|
||||||
all_kitten_names = all_kitten_names()
|
kn = all_kitten_names()
|
||||||
write_cli_docs(all_kitten_names)
|
write_cli_docs(kn)
|
||||||
write_conf_docs(app, all_kitten_names)
|
write_remote_control_protocol_docs()
|
||||||
|
write_conf_docs(app, kn)
|
||||||
app.add_lexer('session', SessionLexer())
|
app.add_lexer('session', SessionLexer())
|
||||||
app.add_role('link', link_role)
|
app.add_role('link', link_role)
|
||||||
app.add_role('iss', partial(num_role, 'issues'))
|
app.add_role('iss', partial(num_role, 'issues'))
|
||||||
|
|||||||
98
docs/faq.rst
98
docs/faq.rst
@@ -63,6 +63,18 @@ Really, the correct solution for this is to convince the OpenSSH maintainers to
|
|||||||
have ssh do this automatically, if possible, when connecting to a server, so that
|
have ssh do this automatically, if possible, when connecting to a server, so that
|
||||||
all terminals work transparently.
|
all terminals work transparently.
|
||||||
|
|
||||||
|
If the server is running FreeBSD, or another system that relies on termcap
|
||||||
|
rather than terminfo, you will need to convert the terminfo file on your local
|
||||||
|
machine by running (on local machine with |kitty|)::
|
||||||
|
|
||||||
|
infocmp -C xterm-kitty
|
||||||
|
|
||||||
|
The output of this command is the termcap description, which should be appended
|
||||||
|
to :file:`/usr/share/misc/termcap` on the remote server. Then run the following
|
||||||
|
command to apply your change (on the server)::
|
||||||
|
|
||||||
|
cap_mkdb /usr/share/misc/termcap
|
||||||
|
|
||||||
|
|
||||||
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
|
Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
|
||||||
-------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------
|
||||||
@@ -97,12 +109,39 @@ How do I change the colors in a running kitty instance?
|
|||||||
|
|
||||||
You can either use the
|
You can either use the
|
||||||
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
|
`OSC terminal escape codes <https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands>`_
|
||||||
to set colors or you can enable :doc:`remote control <remote-control>`
|
to set colors or you can define keyboard shortcuts to set colors, for example::
|
||||||
for |kitty| and use :ref:`at_set-colors`.
|
|
||||||
|
map f1 set_colors --configured /path/to/some/config/file/colors.conf
|
||||||
|
|
||||||
|
Or you can enable :doc:`remote control <remote-control>` for |kitty| and use :ref:`at_set-colors`.
|
||||||
|
The shortcut mapping technique has the same syntax as the remote control
|
||||||
|
command, for details, see :ref:`at_set-colors`.
|
||||||
|
|
||||||
A list of pre-made color themes for kitty is available at:
|
A list of pre-made color themes for kitty is available at:
|
||||||
`kitty-themes <https://github.com/dexpota/kitty-themes>`_
|
`kitty-themes <https://github.com/dexpota/kitty-themes>`_
|
||||||
|
|
||||||
|
Examples of using OSC escape codes to set colors::
|
||||||
|
|
||||||
|
Change the default foreground color:
|
||||||
|
printf '\x1b]10;#ff0000\x1b\\'
|
||||||
|
Change the default background color:
|
||||||
|
printf '\x1b]11;blue\x1b\\'
|
||||||
|
Change the cursor color:
|
||||||
|
printf '\x1b]12;blue\x1b\\'
|
||||||
|
Change the selection background color:
|
||||||
|
printf '\x1b]17;blue\x1b\\'
|
||||||
|
Change the selection foreground color:
|
||||||
|
printf '\x1b]19;blue\x1b\\'
|
||||||
|
Change the nth color (0 - 255):
|
||||||
|
printf '\x1b]4;n;green\x1b\\'
|
||||||
|
|
||||||
|
You can use various syntaxes/names for color specifications in the above
|
||||||
|
examples. See `XParseColor <https://linux.die.net/man/3/xparsecolor>`_
|
||||||
|
for full details.
|
||||||
|
|
||||||
|
If a ``?`` is given rather than a color specification, kitty will respond
|
||||||
|
with the current value for the specified color.
|
||||||
|
|
||||||
|
|
||||||
How do I specify command line options for kitty on macOS?
|
How do I specify command line options for kitty on macOS?
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
@@ -130,7 +169,32 @@ only monospace fonts, since every cell in the grid has to be the same size. If
|
|||||||
your font is not listed in ``kitty list-fonts`` it means that it is not
|
your font is not listed in ``kitty list-fonts`` it means that it is not
|
||||||
monospace. On Linux you can list all monospace fonts with::
|
monospace. On Linux you can list all monospace fonts with::
|
||||||
|
|
||||||
fc-list : family spacing | grep spacing=100
|
fc-list : family spacing | grep -e spacing=100 -e spacing=90
|
||||||
|
|
||||||
|
Note that the spacing property is calculated by fontconfig based on actual
|
||||||
|
glyph widths in the font. If for some reason fontconfig concludes your favorite
|
||||||
|
monospace font does not have ``spacing=100`` you can override it by using the
|
||||||
|
following :file:`~/.config/fontconfig/fonts.conf`::
|
||||||
|
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
||||||
|
<fontconfig>
|
||||||
|
<match target="scan">
|
||||||
|
<test name="family">
|
||||||
|
<string>Your Font Family Name</string>
|
||||||
|
</test>
|
||||||
|
<edit name="spacing">
|
||||||
|
<int>100</int>
|
||||||
|
</edit>
|
||||||
|
</match>
|
||||||
|
</fontconfig>
|
||||||
|
|
||||||
|
After creating (or modifying) this file, you may need to run the following
|
||||||
|
command to rebuild your fontconfig cache::
|
||||||
|
|
||||||
|
fc-cache -r
|
||||||
|
|
||||||
|
Then, the font will be available in ``kitty list-fonts``.
|
||||||
|
|
||||||
|
|
||||||
How can I assign a single global shortcut to bring up the kitty terminal?
|
How can I assign a single global shortcut to bring up the kitty terminal?
|
||||||
@@ -140,3 +204,31 @@ Bringing up applications on a single key press is the job of the window
|
|||||||
manager/desktop environment. For ways to do it with kitty (or indeed any
|
manager/desktop environment. For ways to do it with kitty (or indeed any
|
||||||
terminal) in different environments,
|
terminal) in different environments,
|
||||||
see `here <https://github.com/kovidgoyal/kitty/issues/45>`_.
|
see `here <https://github.com/kovidgoyal/kitty/issues/45>`_.
|
||||||
|
|
||||||
|
|
||||||
|
How do I map key presses in kitty to different keys in the terminal program?
|
||||||
|
--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
This is accomplished by using ``map`` with :sc:`send_text <send_text>` in :file:`kitty.conf`.
|
||||||
|
For example::
|
||||||
|
|
||||||
|
map alt+s send_text all \x13
|
||||||
|
|
||||||
|
This maps :kbd:`alt+s` to :kbd:`ctrl+s`. To figure out what bytes to use for
|
||||||
|
the :sc:`send_text <send_text>` you can use the ``showkey`` utility. Run::
|
||||||
|
|
||||||
|
showkey -a
|
||||||
|
|
||||||
|
Then press the key you want to emulate. On macOS, this utility is currently not
|
||||||
|
available. The manual way to figure it out is:
|
||||||
|
|
||||||
|
1. Look up your key's decimal value in the table at the bottom of `this
|
||||||
|
page <http://ascii-table.com/ansi-escape-sequences.php>`_ or any
|
||||||
|
ANSI escape sequence table. There are different modifiers for :kbd:`ctrl`,
|
||||||
|
:kbd:`alt`, etc. For e.g., for :kbd:`ctrl+s`, find the ``S`` row and look at
|
||||||
|
the third column value, ``19``.
|
||||||
|
|
||||||
|
2. Convert the decimal value to hex with ``kitty +runpy "print(hex(19))"``.
|
||||||
|
This shows the hex value, ``13`` in this case.
|
||||||
|
|
||||||
|
3. Use ``\x(hexval)`` in your ``send_text`` command in kitty. So in this example, ``\x13``
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ features of the graphics protocol:
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
cmd.clear()
|
cmd.clear()
|
||||||
|
|
||||||
write_chunked({'a': 'T', 'f': 100}, open(sys.argv[-1], 'rb').read())
|
with open(sys.argv[-1], 'rb') as f:
|
||||||
|
write_chunked({'a': 'T', 'f': 100}, f.read())
|
||||||
|
|
||||||
|
|
||||||
Save this script as :file:`png.py`, then you can use it to display any PNG
|
Save this script as :file:`png.py`, then you can use it to display any PNG
|
||||||
@@ -255,7 +256,10 @@ sequence of escape codes to the terminal emulator::
|
|||||||
Note that only the first escape code needs to have the full set of control
|
Note that only the first escape code needs to have the full set of control
|
||||||
codes such as width, height, format etc. Subsequent chunks must have
|
codes such as width, height, format etc. Subsequent chunks must have
|
||||||
only the ``m`` key. The client **must** finish sending all chunks for a single image
|
only the ``m`` key. The client **must** finish sending all chunks for a single image
|
||||||
before sending any other graphics related escape codes.
|
before sending any other graphics related escape codes. Note that the cursor
|
||||||
|
position used to display the image **must** be the position when the final chunk is
|
||||||
|
received. Finally, terminals must not display anything, until the entire sequence is
|
||||||
|
received and validated.
|
||||||
|
|
||||||
|
|
||||||
Detecting available transmission mediums
|
Detecting available transmission mediums
|
||||||
@@ -330,7 +334,9 @@ Finally, you can specify the image *z-index*, i.e. the vertical stacking order.
|
|||||||
placed in the same location with different z-index values will be blended if
|
placed in the same location with different z-index values will be blended if
|
||||||
they are semi-transparent. You can specify z-index values using the ``z`` key.
|
they are semi-transparent. You can specify z-index values using the ``z`` key.
|
||||||
Negative z-index values mean that the images will be drawn under the text. This
|
Negative z-index values mean that the images will be drawn under the text. This
|
||||||
allows rendering of text on top of images.
|
allows rendering of text on top of images. Negative z-index values below
|
||||||
|
INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background
|
||||||
|
colors.
|
||||||
|
|
||||||
Deleting images
|
Deleting images
|
||||||
---------------------
|
---------------------
|
||||||
@@ -413,7 +419,7 @@ Key Value Default Description
|
|||||||
``Y`` Positive integer ``0`` The y-offset within the first cell at which to start displaying the image
|
``Y`` Positive integer ``0`` The y-offset within the first cell at which to start displaying the image
|
||||||
``c`` Positive integer ``0`` The number of columns to display the image over
|
``c`` Positive integer ``0`` The number of columns to display the image over
|
||||||
``r`` Positive integer ``0`` The number of rows to display the image over
|
``r`` Positive integer ``0`` The number of rows to display the image over
|
||||||
``z`` Integer ``0`` The *z-index* vertical stacking order of the image
|
``z`` 32-bit integer ``0`` The *z-index* vertical stacking order of the image
|
||||||
**Keys for deleting images**
|
**Keys for deleting images**
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
``d`` Single character. ``a`` What to delete.
|
``d`` Single character. ``a`` What to delete.
|
||||||
|
|||||||
105
docs/index.rst
105
docs/index.rst
@@ -53,13 +53,13 @@ Quickstart
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
Pre-built binaries of |kitty| are available for both macOS and Linux.
|
Pre-built binaries of |kitty| are available for both macOS and Linux.
|
||||||
See the :doc:`binary install instructions </binary>`. You can also
|
See the :doc:`binary install instructions </binary>`. You can
|
||||||
:doc:`build from source </build>`.
|
:doc:`build from source </build>`.
|
||||||
|
|
||||||
You can also use your favorite package manager to install the |kitty| package.
|
You can also use your favorite package manager to install the |kitty| package.
|
||||||
|kitty| packages are available for:
|
|kitty| packages are available for:
|
||||||
`macOS with Homebrew (Cask) <https://formulae.brew.sh/cask/kitty>`_,
|
`macOS with Homebrew (Cask) <https://formulae.brew.sh/cask/kitty>`_,
|
||||||
`macOS and Linux with Nix <https://nixos.org/nixos/packages.html#kitty>`_,
|
`macOS and Linux with Nix <https://nixos.org/nixos/packages.html?channel=nixpkgs-unstable&query=kitty>`_,
|
||||||
`Ubuntu <https://launchpad.net/ubuntu/+source/kitty>`_,
|
`Ubuntu <https://launchpad.net/ubuntu/+source/kitty>`_,
|
||||||
`Debian <https://packages.debian.org/buster/kitty>`_,
|
`Debian <https://packages.debian.org/buster/kitty>`_,
|
||||||
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
`openSUSE <https://build.opensuse.org/package/show/X11:terminals/kitty>`_,
|
||||||
@@ -173,6 +173,30 @@ You can also define a shortcut to switch to the previously active window::
|
|||||||
``nth_window`` will focus the nth window for positive numbers and the
|
``nth_window`` will focus the nth window for positive numbers and the
|
||||||
previously active windows for negative numbers.
|
previously active windows for negative numbers.
|
||||||
|
|
||||||
|
.. _detach_window:
|
||||||
|
|
||||||
|
You can define shortcuts to detach the current window and
|
||||||
|
move it to another tab or another OS window::
|
||||||
|
|
||||||
|
# moves the window into a new OS window
|
||||||
|
map ctrl+f2 detach_window
|
||||||
|
# moves the window into a new Tab
|
||||||
|
map ctrl+f3 detach_window new-tab
|
||||||
|
# asks which tab to move the window into
|
||||||
|
map ctrl+f4 detach_window ask
|
||||||
|
|
||||||
|
Similarly, you can detach the current tab, with::
|
||||||
|
|
||||||
|
# moves the tab into a new OS window
|
||||||
|
map ctrl+f2 detach_tab
|
||||||
|
# asks which OS Window to move the tab into
|
||||||
|
map ctrl+f4 detach_tab ask
|
||||||
|
|
||||||
|
Finally, you can define a shortcut to close all windows in a tab other than
|
||||||
|
the currently active window::
|
||||||
|
|
||||||
|
map f9 close_other_windows_in_tab
|
||||||
|
|
||||||
|
|
||||||
Other keyboard shortcuts
|
Other keyboard shortcuts
|
||||||
----------------------------------
|
----------------------------------
|
||||||
@@ -206,55 +230,26 @@ Reset background opacity :sc:`reset_background_opacity`
|
|||||||
Layouts
|
Layouts
|
||||||
----------
|
----------
|
||||||
|
|
||||||
A layout is an arrangement of multiple *windows*. You can create a new window
|
A layout is an arrangement of multiple kitty *windows* inside a top-level OS window. You can create a new window
|
||||||
using the :sc:`new_window` key combination.
|
using the :sc:`new_window` key combination.
|
||||||
|
|
||||||
Currently, there are five layouts available,
|
Currently, there are six layouts available:
|
||||||
|
|
||||||
* **Stack** -- Only a single maximized window is shown at a time
|
* **Fat** -- One (or optionally more) windows are shown full width on the top, the rest of the windows are shown side-by-side on the bottom
|
||||||
* **Tall** -- One window is shown full height on the left, the rest of the windows are shown one below the other on the right
|
|
||||||
* **Fat** -- One window is shown full width on the top, the rest of the windows are shown side-by-side on the bottom
|
|
||||||
* **Grid** -- All windows are shown in a grid
|
* **Grid** -- All windows are shown in a grid
|
||||||
* **Horizontal** -- All windows are shown side-by-side
|
* **Horizontal** -- All windows are shown side-by-side
|
||||||
|
* **Splits** -- Windows arranged in arbitrary patterns created using horizontal and vertical splits
|
||||||
|
* **Stack** -- Only a single maximized window is shown at a time
|
||||||
|
* **Tall** -- One (or optionally more) windows are shown full height on the left, the rest of the windows are shown one below the other on the right
|
||||||
* **Vertical** -- All windows are shown one below the other
|
* **Vertical** -- All windows are shown one below the other
|
||||||
|
|
||||||
You can switch between layouts using the :sc:`next_layout` key combination. You can
|
By default, all layouts are enabled and you can switch between layouts using
|
||||||
also create shortcuts to select particular layouts, and choose which layouts
|
the :sc:`next_layout` key combination. You can also create shortcuts to select
|
||||||
you want to enable/disable, see :ref:`conf-kitty-shortcuts.layout` for examples.
|
particular layouts, and choose which layouts you want to enable/disable, see
|
||||||
|
:ref:`conf-kitty-shortcuts.layout` for examples. The first layout listed in
|
||||||
|
:opt:`enabled_layouts` becomes the default layout.
|
||||||
|
|
||||||
You can resize windows inside layouts. Press :sc:`start_resizing_window` (also :kbd:`⌘+r` on macOS) to
|
For more details on the layouts and how to use them see :doc:`layouts`.
|
||||||
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::
|
|
||||||
|
|
||||||
enabled_layouts tall:bias=70
|
|
||||||
|
|
||||||
This will make the tall window occupy ``70%`` of available width. ``bias`` can be
|
|
||||||
any number between 10 and 90.
|
|
||||||
|
|
||||||
Writing a new layout only requires about a hundred lines of code, so if there
|
|
||||||
is some layout you want, take a look at `layout.py
|
|
||||||
<https://github.com/kovidgoyal/kitty/blob/master/kitty/layout.py>`_ and submit
|
|
||||||
a pull request!
|
|
||||||
|
|
||||||
.. _kittens:
|
.. _kittens:
|
||||||
|
|
||||||
@@ -368,6 +363,8 @@ Mouse features
|
|||||||
columns.
|
columns.
|
||||||
* Selecting text automatically copies it to the primary clipboard (on
|
* Selecting text automatically copies it to the primary clipboard (on
|
||||||
platforms with a primary clipboard).
|
platforms with a primary clipboard).
|
||||||
|
* You can select text with kitty even when a terminal program has grabbed
|
||||||
|
the mouse by holding down the :kbd:`shift` key.
|
||||||
|
|
||||||
|
|
||||||
Font control
|
Font control
|
||||||
@@ -400,7 +397,7 @@ comfortably within the pager.
|
|||||||
Additionally, you can pipe the contents of the scrollback buffer to an
|
Additionally, you can pipe the contents of the scrollback buffer to an
|
||||||
arbitrary, command running in a new window, tab or overlay, for example::
|
arbitrary, command running in a new window, tab or overlay, for example::
|
||||||
|
|
||||||
map f1 pipe @ansi window less +G -R
|
map f1 launch --stdin-source=@screen_scrollback --stdin-add-formatting less +G -R
|
||||||
|
|
||||||
Would open the scrollback buffer in a new window when you press the :kbd:`F1`
|
Would open the scrollback buffer in a new window when you press the :kbd:`F1`
|
||||||
key. See :sc:`show_scrollback` for details.
|
key. See :sc:`show_scrollback` for details.
|
||||||
@@ -426,6 +423,14 @@ 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
|
names are arbitrary strings, so you can define as many such buffers as you
|
||||||
need.
|
need.
|
||||||
|
|
||||||
|
Marks
|
||||||
|
-------------
|
||||||
|
|
||||||
|
kitty has the ability to mark text on the screen based on regular expressions.
|
||||||
|
This can be useful to highlight words or phrases when browsing output from long
|
||||||
|
running programs or similar. To learn how this feature works, see :doc:`marks`.
|
||||||
|
|
||||||
|
|
||||||
Frequently Asked Questions
|
Frequently Asked Questions
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
@@ -448,6 +453,14 @@ Add the following to your :file:`~/.bashrc`
|
|||||||
|
|
||||||
source <(kitty + complete setup bash)
|
source <(kitty + complete setup bash)
|
||||||
|
|
||||||
|
Older versions of bash (for example, v3.2) do not support
|
||||||
|
process substitution with the source command, in which
|
||||||
|
case you can try an alternative:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
source /dev/stdin <<<"$(kitty + complete setup bash)"
|
||||||
|
|
||||||
|
|
||||||
zsh
|
zsh
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
@@ -468,7 +481,8 @@ completions happens after the call to :file:`compinit`.
|
|||||||
fish
|
fish
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
Add the following to your :file:`~/.config/fish/config.fish`
|
For versions of fish earlier than 3.0.0, add the following to your
|
||||||
|
:file:`~/.config/fish/config.fish`. Later versions source completions by default.
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
@@ -486,3 +500,4 @@ See :doc:`changelog`.
|
|||||||
|
|
||||||
*
|
*
|
||||||
kittens/*
|
kittens/*
|
||||||
|
generated/rc
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import tempfile
|
|||||||
py3 = sys.version_info[0] > 2
|
py3 = sys.version_info[0] > 2
|
||||||
is64bit = platform.architecture()[0] == '64bit'
|
is64bit = platform.architecture()[0] == '64bit'
|
||||||
is_macos = 'darwin' in sys.platform.lower()
|
is_macos = 'darwin' in sys.platform.lower()
|
||||||
|
if is_macos:
|
||||||
|
mac_ver = tuple(map(int, platform.mac_ver()[0].split('.')))
|
||||||
|
if mac_ver[:2] < (10, 12):
|
||||||
|
raise SystemExit('Your version of macOS is too old, at least 10.12 is required')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__file__
|
__file__
|
||||||
@@ -225,7 +229,8 @@ def script_launch():
|
|||||||
|
|
||||||
def update_intaller_wrapper():
|
def update_intaller_wrapper():
|
||||||
# To run: python3 -c "import runpy; runpy.run_path('installer.py', run_name='update_wrapper')" installer.sh
|
# To run: python3 -c "import runpy; runpy.run_path('installer.py', run_name='update_wrapper')" installer.sh
|
||||||
src = open(__file__, 'rb').read().decode('utf-8')
|
with open(__file__, 'rb') as f:
|
||||||
|
src = f.read().decode('utf-8')
|
||||||
wrapper = sys.argv[-1]
|
wrapper = sys.argv[-1]
|
||||||
with open(wrapper, 'r+b') as f:
|
with open(wrapper, 'r+b') as f:
|
||||||
raw = f.read().decode('utf-8')
|
raw = f.read().decode('utf-8')
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ your machine).
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def main(args):
|
def main(args: List[str]) -> str:
|
||||||
# this is the main entry point of the kitten, it will be executed in
|
# this is the main entry point of the kitten, it will be executed in
|
||||||
# the overlay window when the kitten is launched
|
# the overlay window when the kitten is launched
|
||||||
answer = input('Enter some text: ')
|
answer = input('Enter some text: ')
|
||||||
@@ -28,7 +28,7 @@ your machine).
|
|||||||
# handle_result() function
|
# handle_result() function
|
||||||
return answer
|
return answer
|
||||||
|
|
||||||
def handle_result(args, answer, target_window_id, boss):
|
def handle_result(args: List[str], answer: str, target_window_id: int, boss: kitty.boss.Boss) -> None:
|
||||||
# get the kitty window into which to paste answer
|
# get the kitty window into which to paste answer
|
||||||
w = boss.window_id_map.get(target_window_id)
|
w = boss.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
@@ -77,10 +77,11 @@ function, telling kitty what kind of input your kitten would like. For example:
|
|||||||
|
|
||||||
# in handle_result, STDIN is for the kitty process itself, rather
|
# in handle_result, STDIN is for the kitty process itself, rather
|
||||||
# than the kitten process and should not be read from.
|
# than the kitten process and should not be read from.
|
||||||
|
from kittens.tui.handler import result_handler
|
||||||
|
@result_handler(type_of_input='text')
|
||||||
def handle_result(args, stdin_data, target_window_id, boss):
|
def handle_result(args, stdin_data, target_window_id, boss):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
handle_result.type_of_input = 'text'
|
|
||||||
|
|
||||||
This will send the plain text of the active window to the kitten's
|
This will send the plain text of the active window to the kitten's
|
||||||
:file:`STDIN`. For text with formatting escape codes, use ``ansi``
|
:file:`STDIN`. For text with formatting escape codes, use ``ansi``
|
||||||
@@ -106,6 +107,8 @@ Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
|||||||
def main(args):
|
def main(args):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
from kittens.tui.handler import result_handler
|
||||||
|
@result_handler(no_ui=True)
|
||||||
def handle_result(args, answer, target_window_id, boss):
|
def handle_result(args, answer, target_window_id, boss):
|
||||||
tab = boss.active_tab
|
tab = boss.active_tab
|
||||||
if tab is not None:
|
if tab is not None:
|
||||||
@@ -114,8 +117,6 @@ Create a file in the kitty config folder, :file:`~/.config/kitty/zoom_toggle.py`
|
|||||||
else:
|
else:
|
||||||
tab.goto_layout('stack')
|
tab.goto_layout('stack')
|
||||||
|
|
||||||
handle_result.no_ui = True
|
|
||||||
|
|
||||||
|
|
||||||
Now in kitty.conf add::
|
Now in kitty.conf add::
|
||||||
|
|
||||||
@@ -128,7 +129,27 @@ layout, by simply adding the line::
|
|||||||
boss.toggle_fullscreen()
|
boss.toggle_fullscreen()
|
||||||
|
|
||||||
|
|
||||||
to the ``handle_result()`` function, above.
|
To the ``handle_result()`` function, above.
|
||||||
|
|
||||||
|
|
||||||
|
Debugging kittens
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The part of the kitten that runs in ``main()`` is just a normal program and
|
||||||
|
the output of print statements will be visible in the kitten window. Or
|
||||||
|
alternately, you can use::
|
||||||
|
|
||||||
|
from kittens.tui.loop import debug
|
||||||
|
debug('whatever')
|
||||||
|
|
||||||
|
The ``debug()`` function is just like ``print()`` except that the output
|
||||||
|
will appear in the ``STDOUT`` of the kitty process inside which the kitten is
|
||||||
|
running.
|
||||||
|
|
||||||
|
The ``handle_result()`` part of the kitten runs inside the kitty process.
|
||||||
|
The output of print statements will go to the ``STDOUT`` of the kitty process.
|
||||||
|
So if you run kitty from another kitty instance, the output will be visible
|
||||||
|
in the first kitty instance.
|
||||||
|
|
||||||
.. _external_kittens:
|
.. _external_kittens:
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,71 @@ select anything that looks like a path or filename and then insert it into the
|
|||||||
terminal, very useful for picking files from the output of a ``git`` or ``ls`` command and
|
terminal, very useful for picking files from the output of a ``git`` or ``ls`` command and
|
||||||
adding them to the command line for the next command.
|
adding them to the command line for the next command.
|
||||||
|
|
||||||
|
You can also press :sc:`goto_file_line` to select anything that looks
|
||||||
|
like a path or filename followed by a colon and a line number and open
|
||||||
|
the file in vim at the specified line number. The patterns and editor
|
||||||
|
to be used can be modified using options passed to the kitten. For example::
|
||||||
|
|
||||||
|
map ctrl+g kitten hints --type=linenum --linenum-action=tab nvim +{line} +{path}
|
||||||
|
|
||||||
|
will open the selected file in a new tab inside neovim when you press
|
||||||
|
:kbd:`ctrl+g`.
|
||||||
|
|
||||||
The hints kitten is very powerful to see more detailed help on its various
|
The hints kitten is very powerful to see more detailed help on its various
|
||||||
options and modes of operation, see below. You can use these options to
|
options and modes of operation, see below. You can use these options to
|
||||||
create mappings in :file:`kitty.conf` to select various different text
|
create mappings in :file:`kitty.conf` to select various different text
|
||||||
snippets. See :sc:`insert_selected_path` for examples.
|
snippets. See :sc:`insert_selected_path` for examples.
|
||||||
|
|
||||||
|
Completely customizing the matching and actions of the kitten
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
The hints kitten supports writing simple python scripts that can be used to
|
||||||
|
completely customize how it finds matches and what happens when a match is
|
||||||
|
selected. This allows the hints kitten to provide the user interface, while
|
||||||
|
you can provide the logic for finding matches and performing actions on them.
|
||||||
|
This is best illustrated with an example. Create the file
|
||||||
|
:file:`custom-hints.py` in the kitty config directory with the following
|
||||||
|
contents:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
def mark(text, args, Mark, extra_cli_args, *a):
|
||||||
|
# This function is responsible for finding all
|
||||||
|
# matching text. extra_cli_args are any extra arguments
|
||||||
|
# passed on the command line when invoking the kitten.
|
||||||
|
# We mark all individual word for potential selection
|
||||||
|
for idx, m in enumerate(re.finditer(r'\w+', text)):
|
||||||
|
start, end = m.span()
|
||||||
|
mark_text = text[start:end].replace('\n', '').replace('\0', '')
|
||||||
|
# The empty dictionary below will be available as groupdicts
|
||||||
|
# in handle_result() and can contain arbitrary data.
|
||||||
|
yield Mark(idx, start, end, mark_text, {})
|
||||||
|
|
||||||
|
|
||||||
|
def handle_result(args, data, target_window_id, boss, extra_cli_args, *a):
|
||||||
|
# This function is responsible for performing some
|
||||||
|
# action on the selected text.
|
||||||
|
# matches is a list of the selected entries and groupdicts contains
|
||||||
|
# the arbitrary data associated with each entry in mark() above
|
||||||
|
matches, groupdicts = [], []
|
||||||
|
for m, g in zip(data['match'], data['groupdicts']):
|
||||||
|
if m:
|
||||||
|
matches.append(m), groupdicts.append(g)
|
||||||
|
for word, match_data in zip(matches, groupdicts):
|
||||||
|
# Lookup the word in a dictionary, the open_url function
|
||||||
|
# will open the provided url in the system browser
|
||||||
|
boss.open_url(f'https://www.google.com/search?q=define:{word}')
|
||||||
|
|
||||||
|
Now run kitty with::
|
||||||
|
|
||||||
|
kitty -o 'map f1 kitten hints --customize-processing custom-hints.py'
|
||||||
|
|
||||||
|
When you press the :kbd:`F1` key you will be able to select a word to
|
||||||
|
look it up in the Google dictionary.
|
||||||
|
|
||||||
|
|
||||||
Command Line Interface
|
Command Line Interface
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,12 @@ In :guilabel:`Name` mode you instead type words from the character name and use
|
|||||||
keys/tab to select the character from the displayed matches. You can also type
|
keys/tab to select the character from the displayed matches. You can also type
|
||||||
a leading period and the index for the match if you don't like to use arrow
|
a leading period and the index for the match if you don't like to use arrow
|
||||||
keys.
|
keys.
|
||||||
|
|
||||||
|
You can switch between modes using either the function keys or by pressing
|
||||||
|
:kbd:`Ctrl+Tab` and :kbd:`Ctrl+Shift+Tab`.
|
||||||
|
|
||||||
|
|
||||||
|
Command Line Interface
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
.. include:: ../generated/cli-kitten-unicode_input.rst
|
||||||
|
|||||||
96
docs/launch.rst
Normal file
96
docs/launch.rst
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
Launching programs in new windows/tabs
|
||||||
|
========================================
|
||||||
|
|
||||||
|
.. program:: launch
|
||||||
|
|
||||||
|
|
||||||
|
|kitty| has a :code:`launch` action that can be used to run arbitrary programs
|
||||||
|
in news windows/tabs. It can be mapped to user defined shortcuts in kitty.conf.
|
||||||
|
It is very powerful and allows sending the contents of
|
||||||
|
the current window to the launched program, as well as many other options.
|
||||||
|
|
||||||
|
In the simplest form, you can use it to open a new kitty window running the
|
||||||
|
shell, as shown below::
|
||||||
|
|
||||||
|
map f1 launch
|
||||||
|
|
||||||
|
To run a different program simply pass the command line as arguments to
|
||||||
|
launch::
|
||||||
|
|
||||||
|
map f1 launch vim path/to/some/file
|
||||||
|
|
||||||
|
|
||||||
|
To open a new window with the same working directory as the currently
|
||||||
|
active window::
|
||||||
|
|
||||||
|
map f1 launch --cwd=current
|
||||||
|
|
||||||
|
To open the new window in a new tab::
|
||||||
|
|
||||||
|
map f1 launch --type=tab
|
||||||
|
|
||||||
|
To pass the contents of the current screen and scrollback to the started process::
|
||||||
|
|
||||||
|
map f1 launch --stdin-source=@screen_scrollback less
|
||||||
|
|
||||||
|
There are many more powerful options, refer to the complete list below.
|
||||||
|
|
||||||
|
The piping environment
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
When using :option:`launch --stdin-source`, 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.
|
||||||
|
|
||||||
|
|
||||||
|
Special arguments
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
There are a few special placeholder arguments that can be specified as part of
|
||||||
|
the command line. Namely ``@selection`` which is replaced by the current
|
||||||
|
selection and ``@active-kitty-window-id`` which is replaced by the id of the
|
||||||
|
currently active kitty window. For example::
|
||||||
|
|
||||||
|
map f1 launch my-program @active-kitty-window-id
|
||||||
|
|
||||||
|
|
||||||
|
Watching launched windows
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
The :option:`launch --watcher` option allows you to specify python functions
|
||||||
|
that will be called at specific events, such as when the window is resized or
|
||||||
|
closed. Simply specify the path to a python module that specifies callback
|
||||||
|
functions for the events you are interested in, for example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def on_resize(boss, window, data):
|
||||||
|
# Here data will contain old_geometry and new_geometry
|
||||||
|
|
||||||
|
def on_close(boss, window, data):
|
||||||
|
# called when window is closed, typically when the program running in
|
||||||
|
# it exits.
|
||||||
|
|
||||||
|
|
||||||
|
Every callback is passed a reference to the global ``Boss`` object as well as
|
||||||
|
the ``Window`` object the action is occurring on. The ``data`` object is
|
||||||
|
mapping that contains event dependent data. Some useful methods and attributes
|
||||||
|
for the ``Window`` object are: ``as_text(as_ans=False, add_history=False,
|
||||||
|
add_wrap_markers=False, alternate_screen=False)`` with which you can get the
|
||||||
|
contents of the window and its scrollback buffer. Similarly,
|
||||||
|
``window.child.pid`` is the PID of the processes that was launched
|
||||||
|
in the window and ``window.id`` is the internal kitty ``id`` of the
|
||||||
|
window.
|
||||||
|
|
||||||
|
|
||||||
|
Syntax reference
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. include:: /generated/launch.rst
|
||||||
247
docs/layouts.rst
Normal file
247
docs/layouts.rst
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
Layouts
|
||||||
|
============
|
||||||
|
|
||||||
|
kitty has the ability to define its own windows that can be tiled next to each
|
||||||
|
other in arbitrary arrangements, based on *Layouts*, see below for examples:
|
||||||
|
|
||||||
|
|
||||||
|
.. figure:: screenshots/screenshot.png
|
||||||
|
:alt: Screenshot, showing three programs in the 'Tall' layout
|
||||||
|
:align: center
|
||||||
|
:scale: 100%
|
||||||
|
|
||||||
|
Screenshot, showing vim, tig and git running in |kitty| with the 'Tall' layout
|
||||||
|
|
||||||
|
|
||||||
|
.. figure:: screenshots/splits.png
|
||||||
|
:alt: Screenshot, showing windows in the 'Splits' layout
|
||||||
|
:align: center
|
||||||
|
:scale: 100%
|
||||||
|
|
||||||
|
Screenshot, showing windows with arbitrary arrangement in the 'Splits'
|
||||||
|
layout
|
||||||
|
|
||||||
|
|
||||||
|
There are many different layouts available. They are all enabled by default,
|
||||||
|
you can switch layouts using :sc:`next_layout`. To control which layouts
|
||||||
|
are available use :opt:`enabled_layouts`, the first listed layout becomes
|
||||||
|
the default. Individual layouts and how to use them are described below.
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
|
The Stack Layout
|
||||||
|
------------------
|
||||||
|
|
||||||
|
This is the simplest layout it displays a single window using all available
|
||||||
|
space, other windows are hidden behind it. It has no options::
|
||||||
|
|
||||||
|
enabled_layouts stack
|
||||||
|
|
||||||
|
|
||||||
|
The Tall Layout
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Displays one (or optionally more) full height windows on the left half of the
|
||||||
|
screen. Remaining windows are tiled vertically on the right half of the screen.
|
||||||
|
There are options to control how the screen is split horizontally ``bias``
|
||||||
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
|
full-height windows there are ``full_size`` (a positive integer). The syntax
|
||||||
|
for the options is shown below::
|
||||||
|
|
||||||
|
enabled_layouts tall:bias=50;full_size=1
|
||||||
|
|
||||||
|
┌──────────────┬───────────────┐
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├───────────────┤
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├───────────────┤
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
└──────────────┴───────────────┘
|
||||||
|
|
||||||
|
The Fat Layout
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Displays one (or optionally more) full width windows on the top half of the
|
||||||
|
screen. Remaining windows are tiled horizontally on the bottom half of the screen.
|
||||||
|
There are options to control how the screen is split vertically ``bias``
|
||||||
|
(an integer between ``10`` and ``90``) and options to control how many
|
||||||
|
full-height windows there are ``full_size`` (a positive integer). The syntax
|
||||||
|
for the options is shown below::
|
||||||
|
|
||||||
|
enabled_layouts fat:bias=50;full_size=1
|
||||||
|
|
||||||
|
┌──────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
├─────────┬──────────┬─────────┤
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
└─────────┴──────────┴─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
The Grid Layout
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Display windows in a balanced grid with all windows the same size except the
|
||||||
|
last column if there are not enough windows to fill the grid. Has no options::
|
||||||
|
|
||||||
|
enabled_layouts grid
|
||||||
|
|
||||||
|
┌─────────┬──────────┬─────────┐
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
├─────────┼──────────┼─────────┤
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
└─────────┴──────────┴─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
.. _splits_layout:
|
||||||
|
|
||||||
|
The Splits Layout
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
This is the most flexible layout. You can create any arrangement of windows
|
||||||
|
by splitting exiting windows repeatedly. To best use this layout you should
|
||||||
|
define a few extra keybindings in :file:`kitty.conf`::
|
||||||
|
|
||||||
|
map F5 launch --location=hsplit
|
||||||
|
map F6 launch --location=vsplit
|
||||||
|
map F7 layout_action rotate
|
||||||
|
|
||||||
|
map shift+up move_window up
|
||||||
|
map shift+left move_window left
|
||||||
|
map shift+right move_window right
|
||||||
|
map shift+down move_window down
|
||||||
|
|
||||||
|
map ctrl+left neighboring_window left
|
||||||
|
map ctrl+right neighboring_window right
|
||||||
|
map ctrl+up neighboring_window up
|
||||||
|
map ctrl+down neighboring_window down
|
||||||
|
|
||||||
|
Now you can create horizontal and vertical splits by using :kbd:`F5` and
|
||||||
|
:kbd:`F6`. You can move them around using :kbd:`shift+arrow keys`
|
||||||
|
and you can move focus to neighboring windows using :kbd:`ctrl+arrow keys`.
|
||||||
|
You can switch an existing split from horizontal to vertical and vice versa
|
||||||
|
using :kbd:`F7`. Finally, windows can be resized using :ref:`window_resizing`.
|
||||||
|
|
||||||
|
This layout takes one option, ``split_axis`` that controls whether new windows
|
||||||
|
are placed into vertical or horizontal splits, by default::
|
||||||
|
|
||||||
|
enabled_layouts splits:split_axis=horizontal
|
||||||
|
|
||||||
|
┌──────────────┬───────────────┐
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ ├───────┬───────┤
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ├───────┴───────┤
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
└──────────────┴───────────────┘
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The Horizontal Layout
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
All windows are shown side by side. Has no options::
|
||||||
|
|
||||||
|
enabled_layouts horizontal
|
||||||
|
|
||||||
|
┌─────────┬──────────┬─────────┐
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
└─────────┴──────────┴─────────┘
|
||||||
|
|
||||||
|
|
||||||
|
The Vertical Layout
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
All windows are shown one below the other. Has no options::
|
||||||
|
|
||||||
|
enabled_layouts vertical
|
||||||
|
|
||||||
|
┌──────────────────────────────┐
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
├──────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
├──────────────────────────────┤
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
└──────────────────────────────┘
|
||||||
|
|
||||||
|
|
||||||
|
.. _window_resizing:
|
||||||
|
|
||||||
|
Resizing windows
|
||||||
|
------------------
|
||||||
|
|
||||||
|
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`` and ``full_size`` options to control
|
||||||
|
how the available space is split up.
|
||||||
|
To specify the option, in :opt:`kitty.conf <enabled_layouts>` use::
|
||||||
|
|
||||||
|
enabled_layouts tall:bias=70;full_size=2
|
||||||
|
|
||||||
|
This will have ``2`` instead of a single tall window, that occupy ``70%``
|
||||||
|
instead of ``50%`` of available width. ``bias`` can be any number between 10
|
||||||
|
and 90.
|
||||||
|
|
||||||
|
Writing a new layout only requires about a hundred lines of code, so if there
|
||||||
|
is some layout you want, take a look at `layout.py
|
||||||
|
<https://github.com/kovidgoyal/kitty/blob/master/kitty/layout.py>`_ and submit
|
||||||
|
a pull request!
|
||||||
125
docs/marks.rst
Normal file
125
docs/marks.rst
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
Marks
|
||||||
|
=================
|
||||||
|
|
||||||
|
|
||||||
|
kitty has the ability to mark text on the screen based on regular expressions.
|
||||||
|
This can be useful to highlight words or phrases when browsing output from long
|
||||||
|
running programs or similar. Lets start with a few examples:
|
||||||
|
|
||||||
|
Suppose we want to be able to highlight the word ERROR in the current window.
|
||||||
|
Add the following to :file:`kitty.conf`::
|
||||||
|
|
||||||
|
map f1 toggle_marker text 1 ERROR
|
||||||
|
|
||||||
|
Now when you press :kbd:`F1` all instances of the word :code:`ERROR` will be
|
||||||
|
highlighted. To turn off the highlighting, press :kbd:`F1` again.
|
||||||
|
If you want to make it case-insensitive, use::
|
||||||
|
|
||||||
|
map f1 toggle_marker itext 1 ERROR
|
||||||
|
|
||||||
|
To make it match only complete words, use::
|
||||||
|
|
||||||
|
map f1 toggle_marker regex 1 \bERROR\b
|
||||||
|
|
||||||
|
Suppose you want to highlight both :code:`ERROR` and :code:`WARNING`, case
|
||||||
|
insensitively::
|
||||||
|
|
||||||
|
map f1 toggle_marker iregex 1 \bERROR\b 2 \bWARNING\b
|
||||||
|
|
||||||
|
kitty supports up to 3 mark groups (the numbers in the commands above). You
|
||||||
|
can control the colors used for these groups in :file:`kitty.conf` with::
|
||||||
|
|
||||||
|
mark1_foreground red
|
||||||
|
mark1_background gray
|
||||||
|
mark2_foreground green
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
For performance reasons, matching is done per line only, and only when that line is
|
||||||
|
altered in any way. So you cannot match text that stretches across multiple
|
||||||
|
lines.
|
||||||
|
|
||||||
|
|
||||||
|
Creating markers dynamically
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
If you want to create markers dynamically rather than pre-defining them in
|
||||||
|
:file:`kitty.conf` you can do so as follows::
|
||||||
|
|
||||||
|
map f1 create_marker
|
||||||
|
map f2 remove_marker
|
||||||
|
|
||||||
|
Then pressing :kbd:`F1` will allow you to enter the marker definition and set
|
||||||
|
it and pressing :kbd:`F2` will remove the marker. ``create_marker`` accepts
|
||||||
|
the same syntax as ``toggle_marker`` above. Note that while creating
|
||||||
|
markers, the prompt has history so you can easily re-use previous marker
|
||||||
|
expressions.
|
||||||
|
|
||||||
|
You can also use the facilities for :doc:`remote-control` to dynamically
|
||||||
|
add/remove markers.
|
||||||
|
|
||||||
|
|
||||||
|
Scrolling to marks
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
kitty has an action to scroll to the next line that contains a mark. You can
|
||||||
|
use it by mapping it to some shortcut in :file:`kitty.conf`::
|
||||||
|
|
||||||
|
map ctrl+p scroll_to_mark prev
|
||||||
|
map ctrl+n scroll_to_mark next
|
||||||
|
|
||||||
|
Then pressing :kbd:`ctrl+p` will scroll to the first line in the scrollback
|
||||||
|
buffer above the current top line that contains a mark. Pressing :kbd:`ctrl+n`
|
||||||
|
will scroll to show the first line below the current last line that contains
|
||||||
|
a mark. If you wish to jump to a mark of a specific type, you can add that to
|
||||||
|
the mapping::
|
||||||
|
|
||||||
|
map ctrl+1 scroll_to_mark prev 1
|
||||||
|
|
||||||
|
Which will scroll only to marks of type 1.
|
||||||
|
|
||||||
|
|
||||||
|
The full syntax for creating marks
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
The syntax of the :code:`toggle_marker` command is::
|
||||||
|
|
||||||
|
toggle_marker <marker-type> <specification>
|
||||||
|
|
||||||
|
Here :code:`marker-type` is one of:
|
||||||
|
|
||||||
|
* :code:`text` - simple substring matching
|
||||||
|
* :code:`itext` - case-insensitive substring matching
|
||||||
|
* :code:`regex` - A python regular expression
|
||||||
|
* :code:`iregex` - A case-insensitive python regular expression
|
||||||
|
* :code:`function` - An arbitrary function defined in a python file, see
|
||||||
|
:ref:`marker_funcs`.
|
||||||
|
|
||||||
|
.. _marker_funcs:
|
||||||
|
|
||||||
|
Arbitrary marker functions
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
You can create your own marker functions. Create a python file named
|
||||||
|
:file:`mymarker.py` and in it create a :code:`marker` function. This
|
||||||
|
function receives the text of the line as input and must yield three numbers,
|
||||||
|
the starting character position, the ending character position and the mark
|
||||||
|
group (1-3). For example:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
def marker(text):
|
||||||
|
# Function to highlight the letter X
|
||||||
|
for i, ch in enumerate(text):
|
||||||
|
if ch.lower() == 'x':
|
||||||
|
yield i, i, 3
|
||||||
|
|
||||||
|
|
||||||
|
Save this file somewhere and in :file:`kitty.conf`, use::
|
||||||
|
|
||||||
|
map f1 toggle_marker function /path/to/mymarker.py
|
||||||
|
|
||||||
|
If you save the file in the kitty config directory, you can use::
|
||||||
|
|
||||||
|
map f1 toggle_marker function mymarker.py
|
||||||
@@ -14,12 +14,12 @@ render loop to reduce CPU usage. See :ref:`conf-kitty-performance` for details.
|
|||||||
See also the :opt:`sync_to_monitor` option to further decrease latency at the cost
|
See also the :opt:`sync_to_monitor` option to further decrease latency at the cost
|
||||||
of some `tearing <https://en.wikipedia.org/wiki/Screen_tearing>`_ while scrolling.
|
of some `tearing <https://en.wikipedia.org/wiki/Screen_tearing>`_ while scrolling.
|
||||||
|
|
||||||
You can generate detailed per-function performance data using
|
You can generate detailed per-function performance data using `gperftools
|
||||||
`gperftools <https://github.com/gperftools/gperftools>`_. Build |kitty| with
|
<https://github.com/gperftools/gperftools>`_. Build |kitty| with `make
|
||||||
`make profile` which will create an executable called `kitty-profile`. Run
|
profile`. Run kitty and perform the task you want to analyse, for example,
|
||||||
that and perform the task you want to analyse, for example, scrolling a large
|
scrolling a large file with `less`. After you quit, function call statistics
|
||||||
file with `less`. After you quit, function call statistics will be printed to
|
will be printed to `stdout` and you can use tools like *kcachegrind* for more
|
||||||
`stdout` and you can use tools like *kcachegrind* for more detailed analysis.
|
detailed analysis.
|
||||||
|
|
||||||
Here are some CPU usage numbers for the task of scrolling a file continuously
|
Here are some CPU usage numbers for the task of scrolling a file continuously
|
||||||
in less. The CPU usage is for the terminal process and X together and is
|
in less. The CPU usage is for the terminal process and X together and is
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
Working with the screen and history buffer contents
|
Working with the screen and history buffer contents
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
The pipe action has been deprecated in favor of the
|
||||||
|
:doc:`launch <launch>` action which is more powerful.
|
||||||
|
|
||||||
You can pipe the contents of the current screen and history buffer as
|
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
|
:file:`STDIN` to an arbitrary program using the ``pipe`` function. The program
|
||||||
@@ -56,6 +59,9 @@ Input placeholders
|
|||||||
|
|
||||||
There are various different kinds of placeholders
|
There are various different kinds of placeholders
|
||||||
|
|
||||||
|
``@selection``
|
||||||
|
Plain text, currently selected text
|
||||||
|
|
||||||
``@text``
|
``@text``
|
||||||
Plain text, current screen + scrollback buffer
|
Plain text, current screen + scrollback buffer
|
||||||
|
|
||||||
|
|||||||
@@ -219,6 +219,11 @@ first, for example::
|
|||||||
<ESC>]52;c;!<ESC>\
|
<ESC>]52;c;!<ESC>\
|
||||||
|
|
||||||
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
Here ``!`` is not valid base64 encoded text, so it clears the clipboard.
|
||||||
|
Further, since it is invalid, it should be ignored by terminal emulators
|
||||||
|
that do not support this extension, thereby making it safe to use, simply
|
||||||
|
always send it before starting a new OSC 52 paste, even if you aren't chunking
|
||||||
|
up large pastes, that way kitty wont concatenate your paste, and it will have
|
||||||
|
no ill-effects in other terminal emulators.
|
||||||
|
|
||||||
In case you're using software that can't be easily adapted to this
|
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
|
protocol extension, it can be disabled by specifying ``no-append`` to the
|
||||||
|
|||||||
29
docs/rc_protocol.rst
Normal file
29
docs/rc_protocol.rst
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
Documentation for the kitty remote control protocol
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
The kitty remote control protocol is a simple protocol that involves sending
|
||||||
|
data to kitty in the form of JSON. Any individual command of kitty has the
|
||||||
|
form::
|
||||||
|
|
||||||
|
<ESC>P@kitty-cmd<JSON object><ESC>\
|
||||||
|
|
||||||
|
Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form::
|
||||||
|
|
||||||
|
{
|
||||||
|
'cmd': "command name",
|
||||||
|
'version': "kitty version",
|
||||||
|
'no_response': Optional Boolean,
|
||||||
|
'payload': <Optional JSON object>,
|
||||||
|
}
|
||||||
|
|
||||||
|
The ``version`` above is a string of the form :code:`0.14.2`. If you are developing a
|
||||||
|
standalone client, use the kitty version that you are developing against. Using
|
||||||
|
a version greater than the version of the kitty instance you are talking to,
|
||||||
|
will cause a failure.
|
||||||
|
|
||||||
|
Set ``no_response`` to True if you don't want a response from kitty.
|
||||||
|
|
||||||
|
The optional payload is a JSON object that is specific to the actual command being sent.
|
||||||
|
The fields in the object for every command are documented below.
|
||||||
|
|
||||||
|
.. include:: generated/rc.rst
|
||||||
@@ -126,7 +126,7 @@ If you do not want to allow all programs running in |kitty| to control it, you c
|
|||||||
enable remote control for only some |kitty| windows. Simply create a shortcut
|
enable remote control for only some |kitty| windows. Simply create a shortcut
|
||||||
such as::
|
such as::
|
||||||
|
|
||||||
map ctrl+k new_window @ some_program
|
map ctrl+k launch --allow-remote-control some_program
|
||||||
|
|
||||||
Then programs running in windows created with that shortcut can use ``kitty @``
|
Then programs running in windows created with that shortcut can use ``kitty @``
|
||||||
to control kitty. Note that any program with the right level of permissions can
|
to control kitty. Note that any program with the right level of permissions can
|
||||||
@@ -134,5 +134,10 @@ still write to the pipes of any other program on the same computer and
|
|||||||
therefore can control |kitty|. It can, however, be useful to block programs
|
therefore can control |kitty|. It can, however, be useful to block programs
|
||||||
running on other computers (for example, over ssh) or as other users.
|
running on other computers (for example, over ssh) or as other users.
|
||||||
|
|
||||||
|
Documentation for the remote control protocol
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
If you wish to develop your own client to talk to |kitty|, you
|
||||||
|
can use the :doc:`rc_protocol`.
|
||||||
|
|
||||||
.. include:: generated/cli-kitty-at.rst
|
.. include:: generated/cli-kitty-at.rst
|
||||||
|
|||||||
BIN
docs/screenshots/splits.png
Normal file
BIN
docs/screenshots/splits.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -4,18 +4,23 @@
|
|||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from typing import Any, DefaultDict, Dict, FrozenSet, List, Tuple, Union
|
||||||
|
|
||||||
|
KeymapType = Dict[str, Tuple[str, Union[FrozenSet[str], str]]]
|
||||||
|
|
||||||
|
|
||||||
def resolve_keys(keymap):
|
def resolve_keys(keymap: KeymapType) -> DefaultDict[str, List[str]]:
|
||||||
ans = defaultdict(list)
|
ans: DefaultDict[str, List[str]] = defaultdict(list)
|
||||||
for ch, (attr, atype) in keymap.items():
|
for ch, (attr, atype) in keymap.items():
|
||||||
if atype not in ('int', 'uint'):
|
if isinstance(atype, str) and atype in ('int', 'uint'):
|
||||||
atype = 'flag'
|
q = atype
|
||||||
ans[atype].append(ch)
|
else:
|
||||||
|
q = 'flag'
|
||||||
|
ans[q].append(ch)
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def enum(keymap):
|
def enum(keymap: KeymapType) -> str:
|
||||||
lines = []
|
lines = []
|
||||||
for ch, (attr, atype) in keymap.items():
|
for ch, (attr, atype) in keymap.items():
|
||||||
lines.append(f"{attr}='{ch}'")
|
lines.append(f"{attr}='{ch}'")
|
||||||
@@ -26,15 +31,15 @@ def enum(keymap):
|
|||||||
'''.format(',\n'.join(lines))
|
'''.format(',\n'.join(lines))
|
||||||
|
|
||||||
|
|
||||||
def parse_key(keymap):
|
def parse_key(keymap: KeymapType) -> str:
|
||||||
lines = []
|
lines = []
|
||||||
for attr, atype in keymap.values():
|
for attr, atype in keymap.values():
|
||||||
vs = atype.upper() if atype in ('uint', 'int') else 'FLAG'
|
vs = atype.upper() if isinstance(atype, str) and atype in ('uint', 'int') else 'FLAG'
|
||||||
lines.append(f'case {attr}: value_state = {vs}; break;')
|
lines.append(f'case {attr}: value_state = {vs}; break;')
|
||||||
return ' \n'.join(lines)
|
return ' \n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
def parse_flag(keymap, type_map, command_class):
|
def parse_flag(keymap: KeymapType, type_map: Dict[str, Any], command_class: str) -> str:
|
||||||
lines = []
|
lines = []
|
||||||
for ch in type_map['flag']:
|
for ch in type_map['flag']:
|
||||||
attr, allowed_values = keymap[ch]
|
attr, allowed_values = keymap[ch]
|
||||||
@@ -52,14 +57,14 @@ def parse_flag(keymap, type_map, command_class):
|
|||||||
return ' \n'.join(lines)
|
return ' \n'.join(lines)
|
||||||
|
|
||||||
|
|
||||||
def parse_number(keymap):
|
def parse_number(keymap: KeymapType) -> Tuple[str, str]:
|
||||||
int_keys = [f'I({attr})' for attr, atype in keymap.values() if atype == 'int']
|
int_keys = [f'I({attr})' for attr, atype in keymap.values() if atype == 'int']
|
||||||
uint_keys = [f'U({attr})' for attr, atype in keymap.values() if atype == 'uint']
|
uint_keys = [f'U({attr})' for attr, atype in keymap.values() if atype == 'uint']
|
||||||
return '; '.join(int_keys), '; '.join(uint_keys)
|
return '; '.join(int_keys), '; '.join(uint_keys)
|
||||||
|
|
||||||
|
|
||||||
def cmd_for_report(report_name, keymap, type_map, payload_allowed):
|
def cmd_for_report(report_name: str, keymap: KeymapType, type_map: Dict[str, Any], payload_allowed: bool) -> str:
|
||||||
def group(atype, conv):
|
def group(atype: str, conv: str) -> Tuple[str, str]:
|
||||||
flag_fmt, flag_attrs = [], []
|
flag_fmt, flag_attrs = [], []
|
||||||
cv = {'flag': 'c', 'int': 'i', 'uint': 'I'}[atype]
|
cv = {'flag': 'c', 'int': 'i', 'uint': 'I'}[atype]
|
||||||
for ch in type_map[atype]:
|
for ch in type_map[atype]:
|
||||||
@@ -84,7 +89,15 @@ def cmd_for_report(report_name, keymap, type_map, payload_allowed):
|
|||||||
return '\n'.join(ans)
|
return '\n'.join(ans)
|
||||||
|
|
||||||
|
|
||||||
def generate(function_name, callback_name, report_name, keymap, command_class, initial_key='a', payload_allowed=True):
|
def generate(
|
||||||
|
function_name: str,
|
||||||
|
callback_name: str,
|
||||||
|
report_name: str,
|
||||||
|
keymap: KeymapType,
|
||||||
|
command_class: str,
|
||||||
|
initial_key: str = 'a',
|
||||||
|
payload_allowed: bool = True
|
||||||
|
) -> str:
|
||||||
type_map = resolve_keys(keymap)
|
type_map = resolve_keys(keymap)
|
||||||
keys_enum = enum(keymap)
|
keys_enum = enum(keymap)
|
||||||
handle_key = parse_key(keymap)
|
handle_key = parse_key(keymap)
|
||||||
@@ -225,7 +238,7 @@ static inline void
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def write_header(text, path):
|
def write_header(text: str, path: str) -> None:
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
print(f'// This file is generated by {__file__} do not edit!', file=f, end='\n\n')
|
print(f'// This file is generated by {__file__} do not edit!', file=f, end='\n\n')
|
||||||
print('#pragma once', file=f)
|
print('#pragma once', file=f)
|
||||||
@@ -233,9 +246,9 @@ def write_header(text, path):
|
|||||||
subprocess.check_call(['clang-format', '-i', path])
|
subprocess.check_call(['clang-format', '-i', path])
|
||||||
|
|
||||||
|
|
||||||
def graphics_parser():
|
def graphics_parser() -> None:
|
||||||
flag = frozenset
|
flag = frozenset
|
||||||
keymap = {
|
keymap: KeymapType = {
|
||||||
'a': ('action', flag('tTqpd')),
|
'a': ('action', flag('tTqpd')),
|
||||||
'd': ('delete_action', flag('aAiIcCpPqQxXyYzZ')),
|
'd': ('delete_action', flag('aAiIcCpPqQxXyYzZ')),
|
||||||
't': ('transmission_type', flag('dfts')),
|
't': ('transmission_type', flag('dfts')),
|
||||||
|
|||||||
158
gen-wcwidth.py
158
gen-wcwidth.py
@@ -12,6 +12,10 @@ from functools import partial
|
|||||||
from html.entities import html5
|
from html.entities import html5
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
from typing import (
|
||||||
|
Callable, DefaultDict, Dict, FrozenSet, Generator, Iterable, List,
|
||||||
|
Optional, Set, Tuple, Union
|
||||||
|
)
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||||
@@ -24,15 +28,17 @@ if len(non_characters) != 66:
|
|||||||
emoji_skin_tone_modifiers = frozenset(range(0x1f3fb, 0x1F3FF + 1))
|
emoji_skin_tone_modifiers = frozenset(range(0x1f3fb, 0x1F3FF + 1))
|
||||||
|
|
||||||
|
|
||||||
def get_data(fname, folder='UCD'):
|
def get_data(fname: str, folder: str = 'UCD') -> Iterable[str]:
|
||||||
url = f'https://www.unicode.org/Public/{folder}/latest/{fname}'
|
url = f'https://www.unicode.org/Public/{folder}/latest/{fname}'
|
||||||
bn = os.path.basename(url)
|
bn = os.path.basename(url)
|
||||||
local = os.path.join('/tmp', bn)
|
local = os.path.join('/tmp', bn)
|
||||||
if os.path.exists(local):
|
if os.path.exists(local):
|
||||||
data = open(local, 'rb').read()
|
with open(local, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
else:
|
else:
|
||||||
data = urlopen(url).read()
|
data = urlopen(url).read()
|
||||||
open(local, 'wb').write(data)
|
with open(local, 'wb') as f:
|
||||||
|
f.write(data)
|
||||||
for line in data.decode('utf-8').splitlines():
|
for line in data.decode('utf-8').splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line and not line.startswith('#'):
|
if line and not line.startswith('#'):
|
||||||
@@ -40,23 +46,24 @@ def get_data(fname, folder='UCD'):
|
|||||||
|
|
||||||
|
|
||||||
# Map of class names to set of codepoints in class
|
# Map of class names to set of codepoints in class
|
||||||
class_maps = {}
|
class_maps: Dict[str, Set[int]] = {}
|
||||||
name_map = {}
|
all_symbols: Set[int] = set()
|
||||||
word_search_map = defaultdict(set)
|
name_map: Dict[int, str] = {}
|
||||||
|
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
|
||||||
zwj = 0x200d
|
zwj = 0x200d
|
||||||
marks = set(emoji_skin_tone_modifiers) | {zwj}
|
marks = set(emoji_skin_tone_modifiers) | {zwj}
|
||||||
not_assigned = set(range(0, sys.maxunicode))
|
not_assigned = set(range(0, sys.maxunicode))
|
||||||
|
|
||||||
|
|
||||||
def parse_ucd():
|
def parse_ucd() -> None:
|
||||||
|
|
||||||
def add_word(w, c):
|
def add_word(w: str, c: int) -> None:
|
||||||
if c <= 32 or c == 127 or 128 <= c <= 159:
|
if c <= 32 or c == 127 or 128 <= c <= 159:
|
||||||
return
|
return
|
||||||
if len(w) > 1:
|
if len(w) > 1:
|
||||||
word_search_map[w.lower()].add(c)
|
word_search_map[w.lower()].add(c)
|
||||||
|
|
||||||
first = None
|
first: Optional[int] = None
|
||||||
for word, c in html5.items():
|
for word, c in html5.items():
|
||||||
if len(c) == 1:
|
if len(c) == 1:
|
||||||
add_word(word.rstrip(';'), ord(c))
|
add_word(word.rstrip(';'), ord(c))
|
||||||
@@ -74,7 +81,7 @@ def parse_ucd():
|
|||||||
category = parts[2]
|
category = parts[2]
|
||||||
s = class_maps.setdefault(category, set())
|
s = class_maps.setdefault(category, set())
|
||||||
desc = parts[1]
|
desc = parts[1]
|
||||||
codepoints = (codepoint,)
|
codepoints: Union[Tuple[int, ...], Iterable[int]] = (codepoint,)
|
||||||
if first is None:
|
if first is None:
|
||||||
if desc.endswith(', First>'):
|
if desc.endswith(', First>'):
|
||||||
first = codepoint
|
first = codepoint
|
||||||
@@ -87,6 +94,8 @@ def parse_ucd():
|
|||||||
not_assigned.discard(codepoint)
|
not_assigned.discard(codepoint)
|
||||||
if category.startswith('M'):
|
if category.startswith('M'):
|
||||||
marks.add(codepoint)
|
marks.add(codepoint)
|
||||||
|
elif category.startswith('S'):
|
||||||
|
all_symbols.add(codepoint)
|
||||||
|
|
||||||
# Some common synonyms
|
# Some common synonyms
|
||||||
word_search_map['bee'] |= word_search_map['honeybee']
|
word_search_map['bee'] |= word_search_map['honeybee']
|
||||||
@@ -94,43 +103,45 @@ def parse_ucd():
|
|||||||
word_search_map['lamda'] |= word_search_map['lambda']
|
word_search_map['lamda'] |= word_search_map['lambda']
|
||||||
|
|
||||||
|
|
||||||
def split_two(line):
|
def split_two(line: str) -> Tuple[Set[int], str]:
|
||||||
spec, rest = line.split(';', 1)
|
spec, rest = line.split(';', 1)
|
||||||
spec, rest = spec.strip(), rest.strip().split(' ', 1)[0].strip()
|
spec, rest = spec.strip(), rest.strip().split(' ', 1)[0].strip()
|
||||||
if '..' in spec:
|
if '..' in spec:
|
||||||
chars = tuple(map(lambda x: int(x, 16), filter(None, spec.split('.'))))
|
chars_ = tuple(map(lambda x: int(x, 16), filter(None, spec.split('.'))))
|
||||||
chars = set(range(chars[0], chars[1] + 1))
|
chars = set(range(chars_[0], chars_[1] + 1))
|
||||||
else:
|
else:
|
||||||
chars = {int(spec, 16)}
|
chars = {int(spec, 16)}
|
||||||
return chars, rest
|
return chars, rest
|
||||||
|
|
||||||
|
|
||||||
all_emoji = set()
|
all_emoji: Set[int] = set()
|
||||||
emoji_categories = {}
|
emoji_categories: Dict[str, Set[int]] = {}
|
||||||
emoji_presentation_bases = set()
|
emoji_presentation_bases: Set[int] = set()
|
||||||
|
|
||||||
|
|
||||||
def parse_emoji():
|
def parse_emoji() -> None:
|
||||||
for line in get_data('emoji-data.txt', 'emoji'):
|
for line in get_data('emoji-data.txt', 'emoji'):
|
||||||
chars, rest = split_two(line)
|
chars, rest = split_two(line)
|
||||||
s = emoji_categories.setdefault(rest, set())
|
s = emoji_categories.setdefault(rest, set())
|
||||||
s.update(chars)
|
s.update(chars)
|
||||||
all_emoji.update(chars)
|
all_emoji.update(chars)
|
||||||
for line in get_data('emoji-variation-sequences.txt', 'emoji'):
|
for line in get_data('emoji-variation-sequences.txt', 'emoji'):
|
||||||
base, var, *rest = line.split()
|
parts = line.split()
|
||||||
|
base, var = parts[0], parts[1]
|
||||||
if base.startswith('#'):
|
if base.startswith('#'):
|
||||||
continue
|
continue
|
||||||
base = int(base, 16)
|
|
||||||
if var.upper() == 'FE0F':
|
if var.upper() == 'FE0F':
|
||||||
emoji_presentation_bases.add(base)
|
ibase = int(base, 16)
|
||||||
|
emoji_presentation_bases.add(ibase)
|
||||||
|
|
||||||
|
|
||||||
doublewidth, ambiguous = set(), set()
|
doublewidth: Set[int] = set()
|
||||||
|
ambiguous: Set[int] = set()
|
||||||
|
|
||||||
|
|
||||||
def parse_eaw():
|
def parse_eaw() -> None:
|
||||||
global doublewidth, ambiguous
|
global doublewidth, ambiguous
|
||||||
seen = set()
|
seen: Set[int] = set()
|
||||||
for line in get_data('ucd/EastAsianWidth.txt'):
|
for line in get_data('ucd/EastAsianWidth.txt'):
|
||||||
chars, eaw = split_two(line)
|
chars, eaw = split_two(line)
|
||||||
if eaw == 'A':
|
if eaw == 'A':
|
||||||
@@ -146,7 +157,7 @@ def parse_eaw():
|
|||||||
doublewidth |= set(range(0x30000, 0x3FFFD + 1)) - seen
|
doublewidth |= set(range(0x30000, 0x3FFFD + 1)) - seen
|
||||||
|
|
||||||
|
|
||||||
def get_ranges(items):
|
def get_ranges(items: List[int]) -> Generator[Union[int, Tuple[int, int]], None, None]:
|
||||||
items.sort()
|
items.sort()
|
||||||
for k, g in groupby(enumerate(items), lambda m: m[0]-m[1]):
|
for k, g in groupby(enumerate(items), lambda m: m[0]-m[1]):
|
||||||
group = tuple(map(itemgetter(1), g))
|
group = tuple(map(itemgetter(1), g))
|
||||||
@@ -157,7 +168,7 @@ def get_ranges(items):
|
|||||||
yield a, b
|
yield a, b
|
||||||
|
|
||||||
|
|
||||||
def write_case(spec, p):
|
def write_case(spec: Union[Tuple, int], p: Callable) -> None:
|
||||||
if isinstance(spec, tuple):
|
if isinstance(spec, tuple):
|
||||||
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
|
p('\t\tcase 0x{:x} ... 0x{:x}:'.format(*spec))
|
||||||
else:
|
else:
|
||||||
@@ -165,25 +176,24 @@ def write_case(spec, p):
|
|||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def create_header(path, include_data_types=True):
|
def create_header(path: str, include_data_types: bool = True) -> Generator[Callable, None, None]:
|
||||||
f = open(path, 'w')
|
with open(path, 'w') as f:
|
||||||
p = partial(print, file=f)
|
p = partial(print, file=f)
|
||||||
p('// unicode data, built from the unicode standard on:', date.today())
|
p('// unicode data, built from the unicode standard on:', date.today())
|
||||||
p('// see gen-wcwidth.py')
|
p('// see gen-wcwidth.py')
|
||||||
if path.endswith('.h'):
|
if path.endswith('.h'):
|
||||||
p('#pragma once')
|
p('#pragma once')
|
||||||
if include_data_types:
|
if include_data_types:
|
||||||
p('#include "data-types.h"\n')
|
p('#include "data-types.h"\n')
|
||||||
p('START_ALLOW_CASE_RANGE')
|
p('START_ALLOW_CASE_RANGE')
|
||||||
p()
|
p()
|
||||||
yield p
|
yield p
|
||||||
p()
|
p()
|
||||||
if include_data_types:
|
if include_data_types:
|
||||||
p('END_ALLOW_CASE_RANGE')
|
p('END_ALLOW_CASE_RANGE')
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
def gen_emoji():
|
def gen_emoji() -> None:
|
||||||
with create_header('kitty/emoji.h') as p:
|
with create_header('kitty/emoji.h') as p:
|
||||||
p('static inline bool\nis_emoji(char_type code) {')
|
p('static inline bool\nis_emoji(char_type code) {')
|
||||||
p('\tswitch(code) {')
|
p('\tswitch(code) {')
|
||||||
@@ -193,6 +203,7 @@ def gen_emoji():
|
|||||||
p('\t\tdefault: return false;')
|
p('\t\tdefault: return false;')
|
||||||
p('\t}')
|
p('\t}')
|
||||||
p('\treturn false;\n}')
|
p('\treturn false;\n}')
|
||||||
|
|
||||||
p('static inline bool\nis_emoji_modifier(char_type code) {')
|
p('static inline bool\nis_emoji_modifier(char_type code) {')
|
||||||
p('\tswitch(code) {')
|
p('\tswitch(code) {')
|
||||||
for spec in get_ranges(list(emoji_categories['Emoji_Modifier'])):
|
for spec in get_ranges(list(emoji_categories['Emoji_Modifier'])):
|
||||||
@@ -202,10 +213,27 @@ def gen_emoji():
|
|||||||
p('\t}')
|
p('\t}')
|
||||||
p('\treturn false;\n}')
|
p('\treturn false;\n}')
|
||||||
|
|
||||||
|
p('static inline bool\nis_symbol(char_type code) {')
|
||||||
|
p('\tswitch(code) {')
|
||||||
|
for spec in get_ranges(list(all_symbols)):
|
||||||
|
write_case(spec, p)
|
||||||
|
p('\t\t\treturn true;')
|
||||||
|
p('\t\tdefault: return false;')
|
||||||
|
p('\t}')
|
||||||
|
p('\treturn false;\n}')
|
||||||
|
|
||||||
def category_test(name, p, classes, comment, static=False, extra_chars=frozenset(), exclude=frozenset()):
|
|
||||||
static = 'static inline ' if static else ''
|
def category_test(
|
||||||
chars = set()
|
name: str,
|
||||||
|
p: Callable,
|
||||||
|
classes: Iterable[str],
|
||||||
|
comment: str,
|
||||||
|
use_static: bool = False,
|
||||||
|
extra_chars: Union[FrozenSet[int], Set[int]] = frozenset(),
|
||||||
|
exclude: Union[Set[int], FrozenSet[int]] = frozenset()
|
||||||
|
) -> None:
|
||||||
|
static = 'static inline ' if use_static else ''
|
||||||
|
chars: Set[int] = set()
|
||||||
for c in classes:
|
for c in classes:
|
||||||
chars |= class_maps[c]
|
chars |= class_maps[c]
|
||||||
chars |= extra_chars
|
chars |= extra_chars
|
||||||
@@ -220,7 +248,7 @@ def category_test(name, p, classes, comment, static=False, extra_chars=frozenset
|
|||||||
p('\treturn false;\n}\n')
|
p('\treturn false;\n}\n')
|
||||||
|
|
||||||
|
|
||||||
def codepoint_to_mark_map(p, mark_map):
|
def codepoint_to_mark_map(p: Callable, mark_map: List[int]) -> Dict[int, int]:
|
||||||
p('\tswitch(c) { // {{{')
|
p('\tswitch(c) { // {{{')
|
||||||
rmap = {c: m for m, c in enumerate(mark_map)}
|
rmap = {c: m for m, c in enumerate(mark_map)}
|
||||||
for spec in get_ranges(mark_map):
|
for spec in get_ranges(mark_map):
|
||||||
@@ -235,14 +263,14 @@ def codepoint_to_mark_map(p, mark_map):
|
|||||||
return rmap
|
return rmap
|
||||||
|
|
||||||
|
|
||||||
def classes_to_regex(classes, exclude=''):
|
def classes_to_regex(classes: Iterable[str], exclude: str = '') -> Iterable[str]:
|
||||||
chars = set()
|
chars: Set[int] = set()
|
||||||
for c in classes:
|
for c in classes:
|
||||||
chars |= class_maps[c]
|
chars |= class_maps[c]
|
||||||
for c in map(ord, exclude):
|
for x in map(ord, exclude):
|
||||||
chars.discard(c)
|
chars.discard(x)
|
||||||
|
|
||||||
def as_string(codepoint):
|
def as_string(codepoint: int) -> str:
|
||||||
if codepoint < 256:
|
if codepoint < 256:
|
||||||
return r'\x{:02x}'.format(codepoint)
|
return r'\x{:02x}'.format(codepoint)
|
||||||
if codepoint <= 0xffff:
|
if codepoint <= 0xffff:
|
||||||
@@ -256,7 +284,7 @@ def classes_to_regex(classes, exclude=''):
|
|||||||
yield as_string(spec)
|
yield as_string(spec)
|
||||||
|
|
||||||
|
|
||||||
def gen_ucd():
|
def gen_ucd() -> None:
|
||||||
cz = {c for c in class_maps if c[0] in 'CZ'}
|
cz = {c for c in class_maps if c[0] in 'CZ'}
|
||||||
with create_header('kitty/unicode-data.c') as p:
|
with create_header('kitty/unicode-data.c') as p:
|
||||||
p('#include "unicode-data.h"')
|
p('#include "unicode-data.h"')
|
||||||
@@ -282,7 +310,11 @@ def gen_ucd():
|
|||||||
p('combining_type mark_for_codepoint(char_type c) {')
|
p('combining_type mark_for_codepoint(char_type c) {')
|
||||||
rmap = codepoint_to_mark_map(p, mark_map)
|
rmap = codepoint_to_mark_map(p, mark_map)
|
||||||
p('}\n')
|
p('}\n')
|
||||||
expected = int(re.search(r'^#define VS15 (\d+)', open('kitty/unicode-data.h').read(), re.M).group(1))
|
with open('kitty/unicode-data.h') as f:
|
||||||
|
unicode_data = f.read()
|
||||||
|
m = re.search(r'^#define VS15 (\d+)', unicode_data, re.M)
|
||||||
|
if m is not None:
|
||||||
|
expected = int(m.group(1))
|
||||||
if rmap[0xfe0e] != expected:
|
if rmap[0xfe0e] != expected:
|
||||||
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
|
raise ValueError('The mark for 0xfe0e has changed, you have to update VS15 to {} and VS16 to {} in unicode-data.h'.format(
|
||||||
rmap[0xfe0e], rmap[0xfe0f]
|
rmap[0xfe0e], rmap[0xfe0f]
|
||||||
@@ -291,7 +323,7 @@ def gen_ucd():
|
|||||||
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n'))))
|
f.write("url_delimiters = '{}' # noqa".format(''.join(classes_to_regex(cz, exclude='\n'))))
|
||||||
|
|
||||||
|
|
||||||
def gen_names():
|
def gen_names() -> None:
|
||||||
with create_header('kittens/unicode_input/names.h') as p:
|
with create_header('kittens/unicode_input/names.h') as p:
|
||||||
mark_to_cp = list(sorted(name_map))
|
mark_to_cp = list(sorted(name_map))
|
||||||
cp_to_mark = {cp: m for m, cp in enumerate(mark_to_cp)}
|
cp_to_mark = {cp: m for m, cp in enumerate(mark_to_cp)}
|
||||||
@@ -346,28 +378,28 @@ def gen_names():
|
|||||||
|
|
||||||
# The trie
|
# The trie
|
||||||
p(f'typedef struct {{ uint32_t children_offset; uint32_t match_offset; }} word_trie;\n')
|
p(f'typedef struct {{ uint32_t children_offset; uint32_t match_offset; }} word_trie;\n')
|
||||||
all_trie_nodes = []
|
all_trie_nodes: List['TrieNode'] = []
|
||||||
|
|
||||||
class TrieNode:
|
class TrieNode:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self) -> None:
|
||||||
self.match_offset = 0
|
self.match_offset = 0
|
||||||
self.children_offset = 0
|
self.children_offset = 0
|
||||||
self.children = {}
|
self.children: Dict[int, int] = {}
|
||||||
|
|
||||||
def add_letter(self, letter):
|
def add_letter(self, letter: int) -> int:
|
||||||
if letter not in self.children:
|
if letter not in self.children:
|
||||||
self.children[letter] = len(all_trie_nodes)
|
self.children[letter] = len(all_trie_nodes)
|
||||||
all_trie_nodes.append(TrieNode())
|
all_trie_nodes.append(TrieNode())
|
||||||
return self.children[letter]
|
return self.children[letter]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self) -> str:
|
||||||
return f'{{ .children_offset={self.children_offset}, .match_offset={self.match_offset} }}'
|
return f'{{ .children_offset={self.children_offset}, .match_offset={self.match_offset} }}'
|
||||||
|
|
||||||
root = TrieNode()
|
root = TrieNode()
|
||||||
all_trie_nodes.append(root)
|
all_trie_nodes.append(root)
|
||||||
|
|
||||||
def add_word(word_idx, word):
|
def add_word(word_idx: int, word: str) -> None:
|
||||||
parent = root
|
parent = root
|
||||||
for letter in map(ord, word):
|
for letter in map(ord, word):
|
||||||
idx = parent.add_letter(letter)
|
idx = parent.add_letter(letter)
|
||||||
@@ -392,10 +424,10 @@ def gen_names():
|
|||||||
p('}; // }}}\n')
|
p('}; // }}}\n')
|
||||||
|
|
||||||
|
|
||||||
def gen_wcwidth():
|
def gen_wcwidth() -> None:
|
||||||
seen = set()
|
seen: Set[int] = set()
|
||||||
|
|
||||||
def add(p, comment, chars_, ret):
|
def add(p: Callable, comment: str, chars_: Set[int], ret: int) -> None:
|
||||||
chars = chars_ - seen
|
chars = chars_ - seen
|
||||||
seen.update(chars)
|
seen.update(chars)
|
||||||
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import shlex
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
cmdline = (
|
cmdline = (
|
||||||
'glad --profile core --out-path {dest} --api gl=3.3 --generator {generator} --spec gl'
|
'glad --out-path {dest} --api gl:core=3.3 '
|
||||||
' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug'
|
' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug '
|
||||||
|
'c --header-only --debug'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +25,7 @@ def regenerate():
|
|||||||
clean('out')
|
clean('out')
|
||||||
|
|
||||||
subprocess.check_call(
|
subprocess.check_call(
|
||||||
shlex.split(cmdline.format(dest='out', generator='c-debug'))
|
shlex.split(cmdline.format(dest='out'))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -32,33 +34,12 @@ def strip_trailing_whitespace(c):
|
|||||||
|
|
||||||
|
|
||||||
def export():
|
def export():
|
||||||
c = open('out/src/glad.c', 'rb').read().decode('utf-8')
|
with open('out/include/glad/gl.h', 'r', encoding='utf-8') as source:
|
||||||
functions = []
|
data = source.read()
|
||||||
|
data = strip_trailing_whitespace(data)
|
||||||
|
|
||||||
def sub(m):
|
with open('../kitty/gl-wrapper.h', 'w', encoding='utf-8') as dest:
|
||||||
functions.append(m.group(2))
|
dest.write(data)
|
||||||
return m.group()
|
|
||||||
|
|
||||||
c = re.sub(r'^([A-Z0-9]+) glad_debug_([a-zA-Z0-9]+) = glad_debug_impl_\2;$', sub, c, flags=re.M)
|
|
||||||
switch = ['glad_debug_{0} = glad_{0}'.format(f) for f in functions]
|
|
||||||
c = c.replace('<glad/glad.h>', '"gl-wrapper.h"', 1)
|
|
||||||
c = '#pragma GCC diagnostic ignored "-Wpedantic"\n' + c
|
|
||||||
c += '''
|
|
||||||
int
|
|
||||||
init_glad(GLADloadproc load, int debug) {
|
|
||||||
int ret = gladLoadGLLoader(load);
|
|
||||||
if (ret && !debug) {
|
|
||||||
SUB;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}'''.replace('SUB', ';\n '.join(switch), 1)
|
|
||||||
open('../kitty/gl-wrapper.c', 'w').write(strip_trailing_whitespace(c))
|
|
||||||
raw = open('out/include/glad/glad.h').read()
|
|
||||||
raw = raw.replace('<KHR/khrplatform.h>', '"khrplatform.h"')
|
|
||||||
raw += '\nint init_glad(GLADloadproc, int);\n'
|
|
||||||
open('../kitty/gl-wrapper.h', 'w').write(strip_trailing_whitespace(raw))
|
|
||||||
raw = open('out/include/KHR/khrplatform.h', 'rb').read().decode('utf-8')
|
|
||||||
open('../kitty/khrplatform.h', 'w').write(strip_trailing_whitespace(raw))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
0
glfw/__init__.py
Normal file
0
glfw/__init__.py
Normal file
193
glfw/backend_utils.c
vendored
193
glfw/backend_utils.c
vendored
@@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
@@ -20,19 +22,6 @@
|
|||||||
#define ppoll pollts
|
#define ppoll pollts
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline double
|
|
||||||
monotonic(void) {
|
|
||||||
struct timespec ts = {0};
|
|
||||||
#ifdef CLOCK_HIGHRES
|
|
||||||
clock_gettime(CLOCK_HIGHRES, &ts);
|
|
||||||
#elif CLOCK_MONOTONIC_RAW
|
|
||||||
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
|
||||||
#else
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
#endif
|
|
||||||
return (((double)ts.tv_nsec) / 1e9) + (double)ts.tv_sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
update_fds(EventLoopData *eld) {
|
update_fds(EventLoopData *eld) {
|
||||||
for (nfds_t i = 0; i < eld->watches_count; i++) {
|
for (nfds_t i = 0; i < eld->watches_count; i++) {
|
||||||
@@ -107,7 +96,7 @@ update_timers(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
id_type
|
id_type
|
||||||
addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free) {
|
addTimer(EventLoopData *eld, const char *name, monotonic_t interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free) {
|
||||||
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
if (eld->timers_count >= sizeof(eld->timers)/sizeof(eld->timers[0])) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -115,7 +104,7 @@ addTimer(EventLoopData *eld, const char *name, double interval, int enabled, boo
|
|||||||
Timer *t = eld->timers + eld->timers_count++;
|
Timer *t = eld->timers + eld->timers_count++;
|
||||||
t->interval = interval;
|
t->interval = interval;
|
||||||
t->name = name;
|
t->name = name;
|
||||||
t->trigger_at = enabled ? monotonic() + interval : DBL_MAX;
|
t->trigger_at = enabled ? monotonic() + interval : MONOTONIC_T_MAX;
|
||||||
t->repeats = repeats;
|
t->repeats = repeats;
|
||||||
t->callback = cb;
|
t->callback = cb;
|
||||||
t->callback_data = cb_data;
|
t->callback_data = cb_data;
|
||||||
@@ -142,7 +131,7 @@ void
|
|||||||
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
||||||
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||||
if (eld->timers[i].id == timer_id) {
|
if (eld->timers[i].id == timer_id) {
|
||||||
double trigger_at = enabled ? (monotonic() + eld->timers[i].interval) : DBL_MAX;
|
monotonic_t trigger_at = enabled ? (monotonic() + eld->timers[i].interval) : MONOTONIC_T_MAX;
|
||||||
if (trigger_at != eld->timers[i].trigger_at) {
|
if (trigger_at != eld->timers[i].trigger_at) {
|
||||||
eld->timers[i].trigger_at = trigger_at;
|
eld->timers[i].trigger_at = trigger_at;
|
||||||
update_timers(eld);
|
update_timers(eld);
|
||||||
@@ -153,7 +142,7 @@ toggleTimer(EventLoopData *eld, id_type timer_id, int enabled) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval) {
|
changeTimerInterval(EventLoopData *eld, id_type timer_id, monotonic_t interval) {
|
||||||
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
for (nfds_t i = 0; i < eld->timers_count; i++) {
|
||||||
if (eld->timers[i].id == timer_id) {
|
if (eld->timers[i].id == timer_id) {
|
||||||
eld->timers[i].interval = interval;
|
eld->timers[i].interval = interval;
|
||||||
@@ -163,22 +152,28 @@ changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double
|
monotonic_t
|
||||||
prepareForPoll(EventLoopData *eld, double timeout) {
|
prepareForPoll(EventLoopData *eld, monotonic_t timeout) {
|
||||||
for (nfds_t i = 0; i < eld->watches_count; i++) eld->fds[i].revents = 0;
|
for (nfds_t i = 0; i < eld->watches_count; i++) eld->fds[i].revents = 0;
|
||||||
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return timeout;
|
if (!eld->timers_count || eld->timers[0].trigger_at == MONOTONIC_T_MAX) return timeout;
|
||||||
double now = monotonic(), next_repeat_at = eld->timers[0].trigger_at;
|
monotonic_t now = monotonic(), next_repeat_at = eld->timers[0].trigger_at;
|
||||||
if (timeout < 0 || now + timeout > next_repeat_at) {
|
if (timeout < 0 || now + timeout > next_repeat_at) {
|
||||||
timeout = next_repeat_at <= now ? 0 : next_repeat_at - now;
|
timeout = next_repeat_at <= now ? 0 : next_repeat_at - now;
|
||||||
}
|
}
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct timespec
|
||||||
|
calc_time(monotonic_t nsec) {
|
||||||
|
struct timespec result;
|
||||||
|
result.tv_sec = nsec / (1000LL * 1000LL * 1000LL);
|
||||||
|
result.tv_nsec = nsec % (1000LL * 1000LL * 1000LL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout) {
|
pollWithTimeout(struct pollfd *fds, nfds_t nfds, monotonic_t timeout) {
|
||||||
const long seconds = (long) timeout;
|
struct timespec tv = calc_time(timeout);
|
||||||
const long nanoseconds = (long) ((timeout - seconds) * 1e9);
|
|
||||||
struct timespec tv = { seconds, nanoseconds };
|
|
||||||
return ppoll(fds, nfds, &tv, NULL);
|
return ppoll(fds, nfds, &tv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,10 +191,10 @@ dispatchEvents(EventLoopData *eld) {
|
|||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
dispatchTimers(EventLoopData *eld) {
|
dispatchTimers(EventLoopData *eld) {
|
||||||
if (!eld->timers_count || eld->timers[0].trigger_at == DBL_MAX) return 0;
|
if (!eld->timers_count || eld->timers[0].trigger_at == MONOTONIC_T_MAX) return 0;
|
||||||
static struct { timer_callback_func func; id_type id; void* data; bool repeats; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
|
static struct { timer_callback_func func; id_type id; void* data; bool repeats; } dispatches[sizeof(eld->timers)/sizeof(eld->timers[0])];
|
||||||
unsigned num_dispatches = 0;
|
unsigned num_dispatches = 0;
|
||||||
double now = monotonic();
|
monotonic_t now = monotonic();
|
||||||
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at <= now; i++) {
|
for (nfds_t i = 0; i < eld->timers_count && eld->timers[i].trigger_at <= now; i++) {
|
||||||
eld->timers[i].trigger_at = now + eld->timers[i].interval;
|
eld->timers[i].trigger_at = now + eld->timers[i].interval;
|
||||||
dispatches[num_dispatches].func = eld->timers[i].callback;
|
dispatches[num_dispatches].func = eld->timers[i].callback;
|
||||||
@@ -220,30 +215,97 @@ dispatchTimers(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drain_wakeup_fd(int fd, int events, void* data) {
|
drain_wakeup_fd(int fd, EventLoopData* eld) {
|
||||||
static char drain_buf[64];
|
static char drain_buf[64];
|
||||||
while(read(fd, drain_buf, sizeof(drain_buf)) < 0 && errno == EINTR);
|
eld->wakeup_data_read = false;
|
||||||
|
while(true) {
|
||||||
|
ssize_t ret = read(fd, drain_buf, sizeof(drain_buf));
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret > 0) { eld->wakeup_data_read = true; continue; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mark_wakep_fd_ready(int fd UNUSED, int events UNUSED, void *data) {
|
||||||
|
((EventLoopData*)(data))->wakeup_fd_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
initPollData(EventLoopData *eld, int display_fd) {
|
||||||
|
if (!addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL)) return false;
|
||||||
|
#ifdef HAS_EVENT_FD
|
||||||
|
eld->wakeupFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
|
||||||
|
if (eld->wakeupFd == -1) return false;
|
||||||
|
const int wakeup_fd = eld->wakeupFd;
|
||||||
|
#else
|
||||||
|
if (pipe2(eld->wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0) return false;
|
||||||
|
const int wakeup_fd = eld->wakeupFds[0];
|
||||||
|
#endif
|
||||||
|
if (!addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, mark_wakep_fd_ready, eld)) return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
initPollData(EventLoopData *eld, int wakeup_fd, int display_fd) {
|
check_for_wakeup_events(EventLoopData *eld) {
|
||||||
addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL);
|
#ifdef HAS_EVENT_FD
|
||||||
addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, drain_wakeup_fd, NULL);
|
int fd = eld->wakeupFd;
|
||||||
|
#else
|
||||||
|
int fd = eld->wakeupFds[0];
|
||||||
|
#endif
|
||||||
|
drain_wakeup_fd(fd, eld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wakeupEventLoop(EventLoopData *eld) {
|
||||||
|
#ifdef HAS_EVENT_FD
|
||||||
|
static const uint64_t value = 1;
|
||||||
|
while (write(eld->wakeupFd, &value, sizeof value) < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
#else
|
||||||
|
while (write(eld->wakeupFds[1], "w", 1) < 0 && (errno == EINTR || errno == EAGAIN));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAS_EVENT_FD
|
||||||
|
static inline void
|
||||||
|
closeFds(int *fds, size_t count) {
|
||||||
|
while(count--) {
|
||||||
|
if (*fds > 0) {
|
||||||
|
close(*fds);
|
||||||
|
*fds = -1;
|
||||||
|
}
|
||||||
|
fds++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
finalizePollData(EventLoopData *eld) {
|
||||||
|
#ifdef HAS_EVENT_FD
|
||||||
|
close(eld->wakeupFd); eld->wakeupFd = -1;
|
||||||
|
#else
|
||||||
|
closeFds(eld->wakeupFds, arraysz(eld->wakeupFds));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pollForEvents(EventLoopData *eld, double timeout) {
|
pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func display_callback) {
|
||||||
int read_ok = 0;
|
int read_ok = 0;
|
||||||
timeout = prepareForPoll(eld, timeout);
|
timeout = prepareForPoll(eld, timeout);
|
||||||
|
EVDBG("pollForEvents final timeout: %.3f", monotonic_t_to_s_double(timeout));
|
||||||
int result;
|
int result;
|
||||||
double end_time = monotonic() + timeout;
|
monotonic_t end_time = monotonic() + timeout;
|
||||||
|
eld->wakeup_fd_ready = false;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
result = pollWithTimeout(eld->fds, eld->watches_count, timeout);
|
result = pollWithTimeout(eld->fds, eld->watches_count, timeout);
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
|
if (display_callback) display_callback(result, eld->fds[0].revents && eld->watches[0].events, NULL);
|
||||||
dispatchTimers(eld);
|
dispatchTimers(eld);
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
dispatchEvents(eld);
|
dispatchEvents(eld);
|
||||||
@@ -258,6 +320,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
result = poll(eld->fds, eld->watches_count, -1);
|
result = poll(eld->fds, eld->watches_count, -1);
|
||||||
int saved_errno = errno;
|
int saved_errno = errno;
|
||||||
|
if (display_callback) display_callback(result, eld->fds[0].revents && eld->watches[0].events, NULL);
|
||||||
dispatchTimers(eld);
|
dispatchTimers(eld);
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
dispatchEvents(eld);
|
dispatchEvents(eld);
|
||||||
@@ -269,65 +332,3 @@ pollForEvents(EventLoopData *eld, double timeout) {
|
|||||||
}
|
}
|
||||||
return read_ok;
|
return read_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
closeFds(int *fds, size_t count) {
|
|
||||||
while(count--) {
|
|
||||||
if (*fds > 0) {
|
|
||||||
close(*fds);
|
|
||||||
*fds = -1;
|
|
||||||
}
|
|
||||||
fds++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Splits and translates a text/uri-list into separate file paths
|
|
||||||
// NOTE: This function destroys the provided string
|
|
||||||
//
|
|
||||||
char** parseUriList(char* text, int* count)
|
|
||||||
{
|
|
||||||
const char* prefix = "file://";
|
|
||||||
char** paths = NULL;
|
|
||||||
char* line;
|
|
||||||
|
|
||||||
*count = 0;
|
|
||||||
|
|
||||||
while ((line = strtok(text, "\r\n")))
|
|
||||||
{
|
|
||||||
text = NULL;
|
|
||||||
|
|
||||||
if (line[0] == '#')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strncmp(line, prefix, strlen(prefix)) == 0)
|
|
||||||
{
|
|
||||||
line += strlen(prefix);
|
|
||||||
// TODO: Validate hostname
|
|
||||||
while (*line != '/')
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*count)++;
|
|
||||||
|
|
||||||
char* path = calloc(strlen(line) + 1, 1);
|
|
||||||
paths = realloc(paths, *count * sizeof(char*));
|
|
||||||
paths[*count - 1] = path;
|
|
||||||
|
|
||||||
while (*line)
|
|
||||||
{
|
|
||||||
if (line[0] == '%' && line[1] && line[2])
|
|
||||||
{
|
|
||||||
const char digits[3] = { line[1], line[2], '\0' };
|
|
||||||
*path = strtol(digits, NULL, 16);
|
|
||||||
line += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*path = *line;
|
|
||||||
|
|
||||||
path++;
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|||||||
37
glfw/backend_utils.h
vendored
37
glfw/backend_utils.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Wayland - www.glfw.org
|
// GLFW 3.4 Wayland - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -25,10 +25,21 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<sys/eventfd.h>)
|
||||||
|
#define HAS_EVENT_FD
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define HAS_EVENT_FD
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef unsigned long long id_type;
|
typedef unsigned long long id_type;
|
||||||
typedef void(*watch_callback_func)(int, int, void*);
|
typedef void(*watch_callback_func)(int, int, void*);
|
||||||
typedef void(*timer_callback_func)(id_type, void*);
|
typedef void(*timer_callback_func)(id_type, void*);
|
||||||
@@ -45,7 +56,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
id_type id;
|
id_type id;
|
||||||
double interval, trigger_at;
|
monotonic_t interval, trigger_at;
|
||||||
timer_callback_func callback;
|
timer_callback_func callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
GLFWuserdatafreefun free;
|
GLFWuserdatafreefun free;
|
||||||
@@ -56,25 +67,31 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct pollfd fds[32];
|
struct pollfd fds[32];
|
||||||
|
#ifdef HAS_EVENT_FD
|
||||||
|
int wakeupFd;
|
||||||
|
#else
|
||||||
int wakeupFds[2];
|
int wakeupFds[2];
|
||||||
|
#endif
|
||||||
|
bool wakeup_data_read, wakeup_fd_ready;
|
||||||
nfds_t watches_count, timers_count;
|
nfds_t watches_count, timers_count;
|
||||||
Watch watches[32];
|
Watch watches[32];
|
||||||
Timer timers[128];
|
Timer timers[128];
|
||||||
} EventLoopData;
|
} EventLoopData;
|
||||||
|
|
||||||
|
|
||||||
|
void check_for_wakeup_events(EventLoopData *eld);
|
||||||
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
||||||
void removeWatch(EventLoopData *eld, id_type watch_id);
|
void removeWatch(EventLoopData *eld, id_type watch_id);
|
||||||
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
||||||
id_type addTimer(EventLoopData *eld, const char *name, double interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free);
|
id_type addTimer(EventLoopData *eld, const char *name, monotonic_t interval, int enabled, bool repeats, timer_callback_func cb, void *cb_data, GLFWuserdatafreefun free);
|
||||||
void removeTimer(EventLoopData *eld, id_type timer_id);
|
void removeTimer(EventLoopData *eld, id_type timer_id);
|
||||||
void removeAllTimers(EventLoopData *eld);
|
void removeAllTimers(EventLoopData *eld);
|
||||||
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
|
void toggleTimer(EventLoopData *eld, id_type timer_id, int enabled);
|
||||||
void changeTimerInterval(EventLoopData *eld, id_type timer_id, double interval);
|
void changeTimerInterval(EventLoopData *eld, id_type timer_id, monotonic_t interval);
|
||||||
double prepareForPoll(EventLoopData *eld, double timeout);
|
monotonic_t prepareForPoll(EventLoopData *eld, monotonic_t timeout);
|
||||||
int pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout);
|
int pollWithTimeout(struct pollfd *fds, nfds_t nfds, monotonic_t timeout);
|
||||||
int pollForEvents(EventLoopData *eld, double timeout);
|
int pollForEvents(EventLoopData *eld, monotonic_t timeout, watch_callback_func);
|
||||||
unsigned dispatchTimers(EventLoopData *eld);
|
unsigned dispatchTimers(EventLoopData *eld);
|
||||||
void closeFds(int *fds, size_t count);
|
void finalizePollData(EventLoopData *eld);
|
||||||
void initPollData(EventLoopData *eld, int wakeup_fd, int display_fd);
|
bool initPollData(EventLoopData *eld, int display_fd);
|
||||||
char** parseUriList(char* text, int* count);
|
void wakeupEventLoop(EventLoopData *eld);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.4 macOS - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -23,9 +23,16 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
// Needed for _NSGetProgname
|
||||||
|
#include <crt_externs.h>
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
@@ -63,14 +70,119 @@ static void changeToResourcesDirectory(void)
|
|||||||
chdir(resourcesPath);
|
chdir(resourcesPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up the menu bar (manually)
|
||||||
|
// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
|
||||||
|
// could go away at any moment, lots of stuff that really should be
|
||||||
|
// localize(d|able), etc. Add a nib to save us this horror.
|
||||||
|
//
|
||||||
|
static void createMenuBar(void)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
NSString* appName = nil;
|
||||||
|
NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
|
||||||
|
NSString* nameKeys[] =
|
||||||
|
{
|
||||||
|
@"CFBundleDisplayName",
|
||||||
|
@"CFBundleName",
|
||||||
|
@"CFBundleExecutable",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Try to figure out what the calling application is called
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(nameKeys) / sizeof(nameKeys[0]); i++)
|
||||||
|
{
|
||||||
|
id name = bundleInfo[nameKeys[i]];
|
||||||
|
if (name &&
|
||||||
|
[name isKindOfClass:[NSString class]] &&
|
||||||
|
![name isEqualToString:@""])
|
||||||
|
{
|
||||||
|
appName = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!appName)
|
||||||
|
{
|
||||||
|
char** progname = _NSGetProgname();
|
||||||
|
if (progname && *progname)
|
||||||
|
appName = @(*progname);
|
||||||
|
else
|
||||||
|
appName = @"GLFW Application";
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMenu* bar = [[NSMenu alloc] init];
|
||||||
|
[NSApp setMainMenu:bar];
|
||||||
|
|
||||||
|
NSMenuItem* appMenuItem =
|
||||||
|
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||||
|
NSMenu* appMenu = [[NSMenu alloc] init];
|
||||||
|
[appMenuItem setSubmenu:appMenu];
|
||||||
|
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
|
||||||
|
action:@selector(orderFrontStandardAboutPanel:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
NSMenu* servicesMenu = [[NSMenu alloc] init];
|
||||||
|
[NSApp setServicesMenu:servicesMenu];
|
||||||
|
[[appMenu addItemWithTitle:@"Services"
|
||||||
|
action:NULL
|
||||||
|
keyEquivalent:@""] setSubmenu:servicesMenu];
|
||||||
|
[servicesMenu release];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
|
||||||
|
action:@selector(hide:)
|
||||||
|
keyEquivalent:@"h"];
|
||||||
|
[[appMenu addItemWithTitle:@"Hide Others"
|
||||||
|
action:@selector(hideOtherApplications:)
|
||||||
|
keyEquivalent:@"h"]
|
||||||
|
setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
|
||||||
|
[appMenu addItemWithTitle:@"Show All"
|
||||||
|
action:@selector(unhideAllApplications:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[appMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
|
||||||
|
action:@selector(terminate:)
|
||||||
|
keyEquivalent:@"q"];
|
||||||
|
|
||||||
|
NSMenuItem* windowMenuItem =
|
||||||
|
[bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
|
||||||
|
[bar release];
|
||||||
|
NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||||
|
[NSApp setWindowsMenu:windowMenu];
|
||||||
|
[windowMenuItem setSubmenu:windowMenu];
|
||||||
|
|
||||||
|
[windowMenu addItemWithTitle:@"Minimize"
|
||||||
|
action:@selector(performMiniaturize:)
|
||||||
|
keyEquivalent:@"m"];
|
||||||
|
[windowMenu addItemWithTitle:@"Zoom"
|
||||||
|
action:@selector(performZoom:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[windowMenu addItemWithTitle:@"Bring All to Front"
|
||||||
|
action:@selector(arrangeInFront:)
|
||||||
|
keyEquivalent:@""];
|
||||||
|
|
||||||
|
// TODO: Make this appear at the bottom of the menu (for consistency)
|
||||||
|
[windowMenu addItem:[NSMenuItem separatorItem]];
|
||||||
|
[[windowMenu addItemWithTitle:@"Enter Full Screen"
|
||||||
|
action:@selector(toggleFullScreen:)
|
||||||
|
keyEquivalent:@"f"]
|
||||||
|
setKeyEquivalentModifierMask:NSEventModifierFlagControl | NSEventModifierFlagCommand];
|
||||||
|
|
||||||
|
// Prior to Snow Leopard, we need to use this oddly-named semi-private API
|
||||||
|
// to get the application menu working properly.
|
||||||
|
SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
|
||||||
|
[NSApp performSelector:setAppleMenuSelector withObject:appMenu];
|
||||||
|
}
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
//
|
//
|
||||||
static void createKeyTables(void)
|
static void createKeyTables(void)
|
||||||
{
|
{
|
||||||
int scancode;
|
int keycode;
|
||||||
|
|
||||||
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
|
memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
|
||||||
memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
|
memset(_glfw.ns.key_to_keycode, -1, sizeof(_glfw.ns.key_to_keycode));
|
||||||
|
|
||||||
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
|
_glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
|
||||||
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
|
_glfw.ns.keycodes[0x12] = GLFW_KEY_1;
|
||||||
@@ -187,11 +299,11 @@ static void createKeyTables(void)
|
|||||||
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
|
_glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
|
||||||
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
_glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
for (keycode = 0; keycode < 256; keycode++)
|
||||||
{
|
{
|
||||||
// Store the reverse translation for faster key name lookup
|
// Store the reverse translation for faster key name lookup
|
||||||
if (_glfw.ns.keycodes[scancode] >= 0)
|
if (_glfw.ns.keycodes[keycode] >= 0)
|
||||||
_glfw.ns.scancodes[_glfw.ns.keycodes[scancode]] = scancode;
|
_glfw.ns.key_to_keycode[_glfw.ns.keycodes[keycode]] = keycode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,13 +359,13 @@ static bool initializeTIS(void)
|
|||||||
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
CFStringRef* kPropertyUnicodeKeyLayoutData =
|
||||||
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
CFSTR("kTISPropertyUnicodeKeyLayoutData"));
|
||||||
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
*(void **)&_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
|
||||||
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
|
||||||
_glfw.ns.tis.GetInputSourceProperty =
|
*(void **)&_glfw.ns.tis.GetInputSourceProperty =
|
||||||
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("TISGetInputSourceProperty"));
|
CFSTR("TISGetInputSourceProperty"));
|
||||||
_glfw.ns.tis.GetKbdType =
|
*(void **)&_glfw.ns.tis.GetKbdType =
|
||||||
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
|
||||||
CFSTR("LMGetKbdType"));
|
CFSTR("LMGetKbdType"));
|
||||||
|
|
||||||
@@ -273,6 +385,17 @@ static bool initializeTIS(void)
|
|||||||
return updateUnicodeDataNS();
|
return updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFlags flags, void *userInfo UNUSED)
|
||||||
|
{
|
||||||
|
if (flags & kCGDisplayBeginConfigurationFlag) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (flags & kCGDisplaySetModeFlag) {
|
||||||
|
// GPU possibly changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@interface GLFWHelper : NSObject
|
@interface GLFWHelper : NSObject
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -280,14 +403,112 @@ static bool initializeTIS(void)
|
|||||||
|
|
||||||
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
|
||||||
{
|
{
|
||||||
|
(void)object;
|
||||||
updateUnicodeDataNS();
|
updateUnicodeDataNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)doNothing:(id)object
|
- (void)doNothing:(id)object
|
||||||
{
|
{
|
||||||
|
(void)object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end // GLFWHelper
|
@end // GLFWHelper
|
||||||
|
|
||||||
|
// Delegate for application related notifications {{{
|
||||||
|
|
||||||
|
@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GLFWApplicationDelegate
|
||||||
|
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||||
|
{
|
||||||
|
(void)sender;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
|
||||||
|
return NSTerminateCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWapplicationshouldhandlereopenfun handle_reopen_callback = NULL;
|
||||||
|
|
||||||
|
- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag
|
||||||
|
{
|
||||||
|
(void)sender;
|
||||||
|
if (!handle_reopen_callback) return YES;
|
||||||
|
if (handle_reopen_callback(flag)) return YES;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
|
||||||
|
{
|
||||||
|
(void)notification;
|
||||||
|
_GLFWwindow* window;
|
||||||
|
|
||||||
|
for (window = _glfw.windowListHead; window; window = window->next)
|
||||||
|
{
|
||||||
|
if (window->context.client != GLFW_NO_API)
|
||||||
|
[window->context.nsgl.object update];
|
||||||
|
}
|
||||||
|
|
||||||
|
_glfwPollMonitorsNS();
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL;
|
||||||
|
|
||||||
|
- (void)applicationWillFinishLaunching:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
(void)notification;
|
||||||
|
if (_glfw.hints.init.ns.menubar)
|
||||||
|
{
|
||||||
|
// In case we are unbundled, make us a proper UI application
|
||||||
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||||
|
|
||||||
|
// Menu bar setup must go between sharedApplication and finishLaunching
|
||||||
|
// in order to properly emulate the behavior of NSApplicationMain
|
||||||
|
|
||||||
|
if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
|
||||||
|
{
|
||||||
|
[[NSBundle mainBundle] loadNibNamed:@"MainMenu"
|
||||||
|
owner:NSApp
|
||||||
|
topLevelObjects:&_glfw.ns.nibObjects];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
createMenuBar();
|
||||||
|
}
|
||||||
|
if (finish_launching_callback)
|
||||||
|
finish_launching_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
(void)notification;
|
||||||
|
[NSApp stop:nil];
|
||||||
|
|
||||||
|
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
|
||||||
|
_glfwCocoaPostEmptyEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||||
|
{
|
||||||
|
(void)aNotification;
|
||||||
|
CGDisplayRemoveReconfigurationCallback(display_reconfigured, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidHide:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
(void)notification;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < _glfw.monitorCount; i++)
|
||||||
|
_glfwRestoreVideoModeNS(_glfw.monitors[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // GLFWApplicationDelegate
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
|
||||||
@interface GLFWApplication : NSApplication
|
@interface GLFWApplication : NSApplication
|
||||||
- (void)tick_callback;
|
- (void)tick_callback;
|
||||||
@@ -307,6 +528,33 @@ static bool initializeTIS(void)
|
|||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
////// GLFW internal API //////
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void)
|
||||||
|
{
|
||||||
|
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||||
|
if (!bundle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
CFURLRef url =
|
||||||
|
CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
|
||||||
|
if (!url)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
char path[PATH_MAX];
|
||||||
|
void* handle = NULL;
|
||||||
|
|
||||||
|
if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
|
||||||
|
handle = _glfw_dlopen(path);
|
||||||
|
|
||||||
|
CFRelease(url);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -329,17 +577,43 @@ is_cmd_period(NSEvent *event, NSEventModifierFlags modifierFlags) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) {
|
||||||
|
GLFWapplicationshouldhandlereopenfun previous = handle_reopen_callback;
|
||||||
|
handle_reopen_callback = callback;
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWAPI GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) {
|
||||||
|
GLFWapplicationwillfinishlaunchingfun previous = finish_launching_callback;
|
||||||
|
finish_launching_callback = callback;
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
_glfw.ns.helper = [[GLFWHelper alloc] init];
|
||||||
|
|
||||||
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
[NSThread detachNewThreadSelector:@selector(doNothing:)
|
||||||
toTarget:_glfw.ns.helper
|
toTarget:_glfw.ns.helper
|
||||||
withObject:nil];
|
withObject:nil];
|
||||||
|
|
||||||
|
if (NSApp)
|
||||||
|
_glfw.ns.finishedLaunching = true;
|
||||||
|
|
||||||
[GLFWApplication sharedApplication];
|
[GLFWApplication sharedApplication];
|
||||||
|
|
||||||
|
_glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
|
||||||
|
if (_glfw.ns.delegate == nil)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Cocoa: Failed to create application delegate");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NSApp setDelegate:_glfw.ns.delegate];
|
||||||
|
|
||||||
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
NSEvent* (^keydown_block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
|
||||||
{
|
{
|
||||||
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
NSEventModifierFlags modifierFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||||
@@ -374,9 +648,14 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.ns.keyDownMonitor =
|
_glfw.ns.keyDownMonitor =
|
||||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
|
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
|
||||||
handler:keydown_block];
|
handler:keydown_block];
|
||||||
|
|
||||||
if (_glfw.hints.init.ns.chdir)
|
if (_glfw.hints.init.ns.chdir)
|
||||||
changeToResourcesDirectory();
|
changeToResourcesDirectory();
|
||||||
|
|
||||||
|
// Press and Hold prevents some keys from emitting repeated characters
|
||||||
|
NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
|
||||||
|
[[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver:_glfw.ns.helper
|
addObserver:_glfw.ns.helper
|
||||||
selector:@selector(selectedKeyboardInputSourceChanged:)
|
selector:@selector(selectedKeyboardInputSourceChanged:)
|
||||||
@@ -394,24 +673,19 @@ int _glfwPlatformInit(void)
|
|||||||
if (!initializeTIS())
|
if (!initializeTIS())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_glfw.ns.displayLinks.lock = [NSLock new];
|
|
||||||
_glfwInitTimerNS();
|
|
||||||
_glfwInitJoysticksNS();
|
_glfwInitJoysticksNS();
|
||||||
|
|
||||||
_glfwPollMonitorsNS();
|
_glfwPollMonitorsNS();
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
|
||||||
if (_glfw.ns.displayLinks.lock) {
|
_glfwClearDisplayLinks();
|
||||||
_glfwClearDisplayLinks();
|
|
||||||
[_glfw.ns.displayLinks.lock release];
|
|
||||||
_glfw.ns.displayLinks.lock = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.ns.inputSource)
|
if (_glfw.ns.inputSource)
|
||||||
{
|
{
|
||||||
@@ -444,6 +718,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
[_glfw.ns.helper release];
|
[_glfw.ns.helper release];
|
||||||
_glfw.ns.helper = nil;
|
_glfw.ns.helper = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_glfw.ns.keyUpMonitor)
|
if (_glfw.ns.keyUpMonitor)
|
||||||
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
|
||||||
if (_glfw.ns.keyDownMonitor)
|
if (_glfw.ns.keyDownMonitor)
|
||||||
@@ -453,7 +728,8 @@ void _glfwPlatformTerminate(void)
|
|||||||
|
|
||||||
_glfwTerminateNSGL();
|
_glfwTerminateNSGL();
|
||||||
_glfwTerminateJoysticksNS();
|
_glfwTerminateJoysticksNS();
|
||||||
}
|
|
||||||
|
} // autoreleasepool
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
@@ -468,32 +744,56 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
static GLFWtickcallback tick_callback = NULL;
|
static GLFWtickcallback tick_callback = NULL;
|
||||||
static void* tick_callback_data = NULL;
|
static void* tick_callback_data = NULL;
|
||||||
static bool tick_callback_requested = false;
|
static bool tick_callback_requested = false;
|
||||||
|
static pthread_t main_thread;
|
||||||
|
static NSLock *tick_lock = NULL;
|
||||||
|
|
||||||
|
|
||||||
void _glfwDispatchTickCallback() {
|
void _glfwDispatchTickCallback() {
|
||||||
if (tick_callback) {
|
if (tick_lock && tick_callback) {
|
||||||
tick_callback_requested = false;
|
[tick_lock lock];
|
||||||
tick_callback(tick_callback_data);
|
while(tick_callback_requested) {
|
||||||
|
tick_callback_requested = false;
|
||||||
|
tick_callback(tick_callback_data);
|
||||||
|
}
|
||||||
|
[tick_lock unlock];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRequestTickCallback() {
|
static void
|
||||||
|
request_tick_callback() {
|
||||||
if (!tick_callback_requested) {
|
if (!tick_callback_requested) {
|
||||||
tick_callback_requested = true;
|
tick_callback_requested = true;
|
||||||
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
|
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
|
{
|
||||||
|
if (pthread_equal(pthread_self(), main_thread)) {
|
||||||
|
request_tick_callback();
|
||||||
|
} else if (tick_lock) {
|
||||||
|
[tick_lock lock];
|
||||||
|
request_tick_callback();
|
||||||
|
[tick_lock unlock];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _glfwPlatformStopMainLoop(void) {
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
tick_callback = NULL;
|
|
||||||
[NSApp stop:nil];
|
[NSApp stop:nil];
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwCocoaPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
|
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
|
||||||
|
main_thread = pthread_self();
|
||||||
tick_callback = callback;
|
tick_callback = callback;
|
||||||
tick_callback_data = data;
|
tick_callback_data = data;
|
||||||
|
tick_lock = [NSLock new];
|
||||||
[NSApp run];
|
[NSApp run];
|
||||||
|
[tick_lock release];
|
||||||
|
tick_lock = NULL;
|
||||||
|
tick_callback = NULL;
|
||||||
|
tick_callback_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -501,7 +801,7 @@ typedef struct {
|
|||||||
NSTimer *os_timer;
|
NSTimer *os_timer;
|
||||||
unsigned long long id;
|
unsigned long long id;
|
||||||
bool repeats;
|
bool repeats;
|
||||||
double interval;
|
monotonic_t interval;
|
||||||
GLFWuserdatafun callback;
|
GLFWuserdatafun callback;
|
||||||
void *callback_data;
|
void *callback_data;
|
||||||
GLFWuserdatafun free_callback_data;
|
GLFWuserdatafun free_callback_data;
|
||||||
@@ -521,7 +821,7 @@ remove_timer_at(size_t idx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void schedule_timer(Timer *t) {
|
static void schedule_timer(Timer *t) {
|
||||||
t->os_timer = [NSTimer scheduledTimerWithTimeInterval:t->interval repeats:(t->repeats ? YES: NO) block:^(NSTimer *os_timer) {
|
t->os_timer = [NSTimer scheduledTimerWithTimeInterval:monotonic_t_to_s_double(t->interval) repeats:(t->repeats ? YES: NO) block:^(NSTimer *os_timer) {
|
||||||
for (size_t i = 0; i < num_timers; i++) {
|
for (size_t i = 0; i < num_timers; i++) {
|
||||||
if (timers[i].os_timer == os_timer) {
|
if (timers[i].os_timer == os_timer) {
|
||||||
timers[i].callback(timers[i].id, timers[i].callback_data);
|
timers[i].callback(timers[i].id, timers[i].callback_data);
|
||||||
@@ -532,7 +832,7 @@ static void schedule_timer(Timer *t) {
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) {
|
unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) {
|
||||||
static unsigned long long timer_counter = 0;
|
static unsigned long long timer_counter = 0;
|
||||||
if (num_timers >= sizeof(timers)/sizeof(timers[0]) - 1) {
|
if (num_timers >= sizeof(timers)/sizeof(timers[0]) - 1) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Too many timers added");
|
||||||
@@ -558,7 +858,7 @@ void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
|
||||||
for (size_t i = 0; i < num_timers; i++) {
|
for (size_t i = 0; i < num_timers; i++) {
|
||||||
if (timers[i].id == timer_id) {
|
if (timers[i].id == timer_id) {
|
||||||
Timer *t = timers + i;
|
Timer *t = timers + i;
|
||||||
|
|||||||
4
glfw/cocoa_joystick.h
vendored
4
glfw/cocoa_joystick.h
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Cocoa - www.glfw.org
|
// GLFW 3.4 Cocoa - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Cocoa - www.glfw.org
|
// GLFW 3.4 Cocoa - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -75,7 +77,7 @@ static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
|
|||||||
//
|
//
|
||||||
static CFComparisonResult compareElements(const void* fp,
|
static CFComparisonResult compareElements(const void* fp,
|
||||||
const void* sp,
|
const void* sp,
|
||||||
void* user)
|
void* user UNUSED)
|
||||||
{
|
{
|
||||||
const _GLFWjoyelementNS* fe = fp;
|
const _GLFWjoyelementNS* fe = fp;
|
||||||
const _GLFWjoyelementNS* se = sp;
|
const _GLFWjoyelementNS* se = sp;
|
||||||
@@ -117,9 +119,9 @@ static void closeJoystick(_GLFWjoystick* js)
|
|||||||
|
|
||||||
// Callback for user-initiated joystick addition
|
// Callback for user-initiated joystick addition
|
||||||
//
|
//
|
||||||
static void matchCallback(void* context,
|
static void matchCallback(void* context UNUSED,
|
||||||
IOReturn result,
|
IOReturn result UNUSED,
|
||||||
void* sender,
|
void* sender UNUSED,
|
||||||
IOHIDDeviceRef device)
|
IOHIDDeviceRef device)
|
||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
@@ -270,9 +272,9 @@ static void matchCallback(void* context,
|
|||||||
|
|
||||||
// Callback for user-initiated joystick removal
|
// Callback for user-initiated joystick removal
|
||||||
//
|
//
|
||||||
static void removeCallback(void* context,
|
static void removeCallback(void* context UNUSED,
|
||||||
IOReturn result,
|
IOReturn result UNUSED,
|
||||||
void* sender,
|
void* sender UNUSED,
|
||||||
IOHIDDeviceRef device)
|
IOHIDDeviceRef device)
|
||||||
{
|
{
|
||||||
int jid;
|
int jid;
|
||||||
@@ -316,7 +318,7 @@ void _glfwInitJoysticksNS(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(usages) / sizeof(long); i++)
|
for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
|
||||||
{
|
{
|
||||||
const long page = kHIDPage_GenericDesktop;
|
const long page = kHIDPage_GenericDesktop;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.4 macOS - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -144,7 +146,7 @@ static bool modeIsGood(CGDisplayModeRef mode)
|
|||||||
// Convert Core Graphics display mode to GLFW video mode
|
// Convert Core Graphics display mode to GLFW video mode
|
||||||
//
|
//
|
||||||
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
||||||
CVDisplayLinkRef link)
|
double fallbackRefreshRate)
|
||||||
{
|
{
|
||||||
GLFWvidmode result;
|
GLFWvidmode result;
|
||||||
result.width = (int) CGDisplayModeGetWidth(mode);
|
result.width = (int) CGDisplayModeGetWidth(mode);
|
||||||
@@ -152,11 +154,7 @@ static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
|
|||||||
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
|
||||||
|
|
||||||
if (result.refreshRate == 0)
|
if (result.refreshRate == 0)
|
||||||
{
|
result.refreshRate = (int) round(fallbackRefreshRate);
|
||||||
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
|
||||||
if (!(time.flags & kCVTimeIsIndefinite))
|
|
||||||
result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
|
||||||
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
|
||||||
@@ -215,7 +213,7 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
|
|||||||
|
|
||||||
// Finds and caches the NSScreen corresponding to the specified monitor
|
// Finds and caches the NSScreen corresponding to the specified monitor
|
||||||
//
|
//
|
||||||
bool refreshMonitorScreen(_GLFWmonitor* monitor)
|
static bool refreshMonitorScreen(_GLFWmonitor* monitor)
|
||||||
{
|
{
|
||||||
if (monitor->ns.screen)
|
if (monitor->ns.screen)
|
||||||
return true;
|
return true;
|
||||||
@@ -238,54 +236,59 @@ bool refreshMonitorScreen(_GLFWmonitor* monitor)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a fallback refresh rate for when Core Graphics says it is zero
|
||||||
|
//
|
||||||
|
static double getFallbackRefreshRate(_GLFWmonitor* monitor)
|
||||||
|
{
|
||||||
|
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||||
|
double refreshRate = CGDisplayModeGetRefreshRate(mode);
|
||||||
|
CGDisplayModeRelease(mode);
|
||||||
|
|
||||||
|
if (refreshRate == 0.0)
|
||||||
|
{
|
||||||
|
CVDisplayLinkRef link = NULL;
|
||||||
|
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
||||||
|
|
||||||
|
const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
|
||||||
|
if (!(time.flags & kCVTimeIsIndefinite))
|
||||||
|
refreshRate = (int) (time.timeScale / (double) time.timeValue);
|
||||||
|
|
||||||
|
CVDisplayLinkRelease(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW internal API //////
|
////// GLFW internal API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwClearDisplayLinks() {
|
void _glfwClearDisplayLinks() {
|
||||||
[_glfw.ns.displayLinks.lock lock];
|
|
||||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
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) {
|
if (_glfw.ns.displayLinks.entries[i].displayLink) {
|
||||||
|
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
|
||||||
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
_glfw.ns.displayLinks.entries[i].displayLink = nil;
|
||||||
|
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_glfw.ns.displayLinks.count = 0;
|
_glfw.ns.displayLinks.count = 0;
|
||||||
[_glfw.ns.displayLinks.lock unlock];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CVReturn displayLinkCallback(
|
static CVReturn displayLinkCallback(
|
||||||
CVDisplayLinkRef displayLink,
|
CVDisplayLinkRef displayLink UNUSED,
|
||||||
const CVTimeStamp* now, const CVTimeStamp* outputTime,
|
const CVTimeStamp* now UNUSED, const CVTimeStamp* outputTime UNUSED,
|
||||||
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* userInfo)
|
CVOptionFlags flagsIn UNUSED, CVOptionFlags* flagsOut UNUSED, void* userInfo)
|
||||||
{
|
{
|
||||||
CGDirectDisplayID displayID = (CGDirectDisplayID)userInfo;
|
CGDirectDisplayID displayID = (CGDirectDisplayID)userInfo;
|
||||||
[_glfw.ns.displayLinks.lock lock];
|
NSNumber *arg = [NSNumber numberWithUnsignedInt:displayID];
|
||||||
bool notify = false;
|
[NSApp performSelectorOnMainThread:@selector(render_frame_received:) withObject:arg waitUntilDone:NO];
|
||||||
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
[arg release];
|
||||||
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;
|
return kCVReturnSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void createDisplayLink(CGDirectDisplayID displayID) {
|
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;
|
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++) {
|
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
|
||||||
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
|
||||||
@@ -295,26 +298,24 @@ static inline void createDisplayLink(CGDirectDisplayID displayID) {
|
|||||||
entry->displayID = displayID;
|
entry->displayID = displayID;
|
||||||
CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink);
|
CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink);
|
||||||
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID);
|
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID);
|
||||||
[_glfw.ns.displayLinks.lock unlock];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll for changes in the set of connected monitors
|
// Poll for changes in the set of connected monitors
|
||||||
//
|
//
|
||||||
void _glfwPollMonitorsNS(void)
|
void _glfwPollMonitorsNS(void)
|
||||||
{
|
{
|
||||||
uint32_t i, j, displayCount, disconnectedCount;
|
uint32_t displayCount;
|
||||||
CGDirectDisplayID* displays;
|
|
||||||
_GLFWmonitor** disconnected = NULL;
|
|
||||||
|
|
||||||
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
CGGetOnlineDisplayList(0, NULL, &displayCount);
|
||||||
displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
|
||||||
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
CGGetOnlineDisplayList(displayCount, displays, &displayCount);
|
||||||
_glfwClearDisplayLinks();
|
_glfwClearDisplayLinks();
|
||||||
|
|
||||||
for (i = 0; i < _glfw.monitorCount; i++)
|
for (int i = 0; i < _glfw.monitorCount; i++)
|
||||||
_glfw.monitors[i]->ns.screen = nil;
|
_glfw.monitors[i]->ns.screen = nil;
|
||||||
|
|
||||||
disconnectedCount = _glfw.monitorCount;
|
_GLFWmonitor** disconnected = NULL;
|
||||||
|
uint32_t disconnectedCount = _glfw.monitorCount;
|
||||||
if (disconnectedCount)
|
if (disconnectedCount)
|
||||||
{
|
{
|
||||||
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
|
||||||
@@ -323,19 +324,18 @@ void _glfwPollMonitorsNS(void)
|
|||||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < displayCount; i++)
|
for (uint32_t i = 0; i < displayCount; i++)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
|
||||||
|
|
||||||
if (CGDisplayIsAsleep(displays[i]))
|
if (CGDisplayIsAsleep(displays[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j = 0; j < disconnectedCount; j++)
|
// HACK: Compare unit numbers instead of display IDs to work around
|
||||||
|
// display replacement on machines with automatic graphics
|
||||||
|
// switching
|
||||||
|
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < disconnectedCount; j++)
|
||||||
{
|
{
|
||||||
// HACK: Compare unit numbers instead of display IDs to work around
|
|
||||||
// display replacement on machines with automatic graphics
|
|
||||||
// switching
|
|
||||||
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
|
||||||
{
|
{
|
||||||
disconnected[j] = NULL;
|
disconnected[j] = NULL;
|
||||||
@@ -348,9 +348,10 @@ void _glfwPollMonitorsNS(void)
|
|||||||
if (!name)
|
if (!name)
|
||||||
name = _glfw_strdup("Unknown");
|
name = _glfw_strdup("Unknown");
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(name, size.width, size.height);
|
_GLFWmonitor* monitor = _glfwAllocMonitor(name, (int)size.width, (int)size.height);
|
||||||
monitor->ns.displayID = displays[i];
|
monitor->ns.displayID = displays[i];
|
||||||
monitor->ns.unitNumber = unitNumber;
|
monitor->ns.unitNumber = unitNumber;
|
||||||
|
monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(monitor);
|
||||||
createDisplayLink(monitor->ns.displayID);
|
createDisplayLink(monitor->ns.displayID);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
@@ -358,7 +359,7 @@ void _glfwPollMonitorsNS(void)
|
|||||||
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
for (uint32_t i = 0; i < disconnectedCount; i++)
|
||||||
{
|
{
|
||||||
if (disconnected[i])
|
if (disconnected[i])
|
||||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
@@ -373,30 +374,25 @@ void _glfwPollMonitorsNS(void)
|
|||||||
//
|
//
|
||||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
|
||||||
CFIndex count, i;
|
|
||||||
CVDisplayLinkRef link;
|
|
||||||
CGDisplayModeRef native = NULL;
|
|
||||||
GLFWvidmode current;
|
GLFWvidmode current;
|
||||||
const GLFWvidmode* best;
|
|
||||||
|
|
||||||
best = _glfwChooseVideoMode(monitor, desired);
|
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
|
|
||||||
|
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
|
const CFIndex count = CFArrayGetCount(modes);
|
||||||
|
CGDisplayModeRef native = NULL;
|
||||||
|
|
||||||
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
for (CFIndex i = 0; i < count; i++)
|
||||||
count = CFArrayGetCount(modes);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||||
if (!modeIsGood(dm))
|
if (!modeIsGood(dm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
if (_glfwCompareVideoModes(best, &mode) == 0)
|
if (_glfwCompareVideoModes(best, &mode) == 0)
|
||||||
{
|
{
|
||||||
native = dm;
|
native = dm;
|
||||||
@@ -415,7 +411,6 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the previously saved (original) video mode
|
// Restore the previously saved (original) video mode
|
||||||
@@ -439,7 +434,7 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +463,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = (float) (pixels.size.height / points.size.height);
|
*yscale = (float) (pixels.size.height / points.size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
if (!refreshMonitorScreen(monitor))
|
if (!refreshMonitorScreen(monitor))
|
||||||
return;
|
return;
|
||||||
@@ -476,40 +473,34 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos
|
|||||||
const NSRect frameRect = [monitor->ns.screen visibleFrame];
|
const NSRect frameRect = [monitor->ns.screen visibleFrame];
|
||||||
|
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = frameRect.origin.x;
|
*xpos = (int)frameRect.origin.x;
|
||||||
if (ypos)
|
if (ypos)
|
||||||
*ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
|
*ypos = (int)_glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
|
||||||
if (width)
|
if (width)
|
||||||
*width = frameRect.size.width;
|
*width = (int)frameRect.size.width;
|
||||||
if (height)
|
if (height)
|
||||||
*height = frameRect.size.height;
|
*height = (int)frameRect.size.height;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
||||||
{
|
{
|
||||||
CFArrayRef modes;
|
|
||||||
CFIndex found, i, j;
|
|
||||||
GLFWvidmode* result;
|
|
||||||
CVDisplayLinkRef link;
|
|
||||||
|
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
||||||
|
const CFIndex found = CFArrayGetCount(modes);
|
||||||
|
GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
|
||||||
|
|
||||||
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
|
for (CFIndex i = 0; i < found; i++)
|
||||||
found = CFArrayGetCount(modes);
|
|
||||||
result = calloc(found, sizeof(GLFWvidmode));
|
|
||||||
|
|
||||||
for (i = 0; i < found; i++)
|
|
||||||
{
|
{
|
||||||
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
|
||||||
if (!modeIsGood(dm))
|
if (!modeIsGood(dm))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
|
const GLFWvidmode mode =
|
||||||
|
vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
|
||||||
|
|
||||||
for (j = 0; j < *count; j++)
|
for (CFIndex j = 0; j < *count; j++)
|
||||||
{
|
{
|
||||||
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
if (_glfwCompareVideoModes(result + j, &mode) == 0)
|
||||||
break;
|
break;
|
||||||
@@ -524,27 +515,19 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CFRelease(modes);
|
CFRelease(modes);
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
|
||||||
{
|
{
|
||||||
CGDisplayModeRef displayMode;
|
CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
||||||
CVDisplayLinkRef link;
|
*mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
|
||||||
|
CGDisplayModeRelease(native);
|
||||||
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
|
|
||||||
|
|
||||||
displayMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
|
|
||||||
*mode = vidmodeFromCGDisplayMode(displayMode, link);
|
|
||||||
CGDisplayModeRelease(displayMode);
|
|
||||||
|
|
||||||
CVDisplayLinkRelease(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
|
||||||
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
|
||||||
|
|
||||||
CGGetDisplayTransferByTable(monitor->ns.displayID,
|
CGGetDisplayTransferByTable(monitor->ns.displayID,
|
||||||
@@ -556,7 +539,7 @@ bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
|
|
||||||
_glfwAllocGammaArrays(ramp, size);
|
_glfwAllocGammaArrays(ramp, size);
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (uint32_t i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
ramp->red[i] = (unsigned short) (values[i] * 65535);
|
ramp->red[i] = (unsigned short) (values[i] * 65535);
|
||||||
ramp->green[i] = (unsigned short) (values[i + size] * 65535);
|
ramp->green[i] = (unsigned short) (values[i + size] * 65535);
|
||||||
@@ -569,10 +552,9 @@ bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
|||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
|
CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
|
||||||
|
|
||||||
for (i = 0; i < ramp->size; i++)
|
for (unsigned int i = 0; i < ramp->size; i++)
|
||||||
{
|
{
|
||||||
values[i] = ramp->red[i] / 65535.f;
|
values[i] = ramp->red[i] / 65535.f;
|
||||||
values[i + ramp->size] = ramp->green[i] / 65535.f;
|
values[i + ramp->size] = ramp->green[i] / 65535.f;
|
||||||
|
|||||||
49
glfw/cocoa_platform.h
vendored
49
glfw/cocoa_platform.h
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.4 macOS - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -36,6 +36,9 @@ typedef void* id;
|
|||||||
typedef void* CVDisplayLinkRef;
|
typedef void* CVDisplayLinkRef;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Many Cocoa enum values have been renamed and we need to build across
|
||||||
|
// SDK versions where one is unavailable or the other deprecated
|
||||||
|
// We use the newer names in code and these macros to handle compatibility
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
|
||||||
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
#define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
|
||||||
#define NSEventMaskAny NSAnyEventMask
|
#define NSEventMaskAny NSAnyEventMask
|
||||||
@@ -62,12 +65,15 @@ typedef void* CVDisplayLinkRef;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long);
|
||||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
||||||
|
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
|
|
||||||
|
typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
|
||||||
|
typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
|
||||||
|
|
||||||
typedef struct VkMacOSSurfaceCreateInfoMVK
|
typedef struct VkMacOSSurfaceCreateInfoMVK
|
||||||
{
|
{
|
||||||
VkStructureType sType;
|
VkStructureType sType;
|
||||||
@@ -76,7 +82,16 @@ typedef struct VkMacOSSurfaceCreateInfoMVK
|
|||||||
const void* pView;
|
const void* pView;
|
||||||
} VkMacOSSurfaceCreateInfoMVK;
|
} VkMacOSSurfaceCreateInfoMVK;
|
||||||
|
|
||||||
|
typedef struct VkMetalSurfaceCreateInfoEXT
|
||||||
|
{
|
||||||
|
VkStructureType sType;
|
||||||
|
const void* pNext;
|
||||||
|
VkMetalSurfaceCreateFlagsEXT flags;
|
||||||
|
const void* pLayer;
|
||||||
|
} VkMetalSurfaceCreateInfoEXT;
|
||||||
|
|
||||||
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
|
||||||
|
|
||||||
#include "posix_thread.h"
|
#include "posix_thread.h"
|
||||||
#include "cocoa_joystick.h"
|
#include "cocoa_joystick.h"
|
||||||
@@ -116,8 +131,8 @@ typedef struct _GLFWwindowNS
|
|||||||
id view;
|
id view;
|
||||||
id layer;
|
id layer;
|
||||||
|
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool retina;
|
bool retina;
|
||||||
|
|
||||||
// Cached window properties to filter out duplicate events
|
// Cached window properties to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -144,8 +159,7 @@ typedef struct _GLFWDisplayLinkNS
|
|||||||
{
|
{
|
||||||
CVDisplayLinkRef displayLink;
|
CVDisplayLinkRef displayLink;
|
||||||
CGDirectDisplayID displayID;
|
CGDirectDisplayID displayID;
|
||||||
bool displayLinkStarted;
|
monotonic_t lastRenderFrameRequestedAt;
|
||||||
bool renderFrameRequested;
|
|
||||||
} _GLFWDisplayLinkNS;
|
} _GLFWDisplayLinkNS;
|
||||||
|
|
||||||
// Cocoa-specific global data
|
// Cocoa-specific global data
|
||||||
@@ -154,18 +168,20 @@ typedef struct _GLFWlibraryNS
|
|||||||
{
|
{
|
||||||
CGEventSourceRef eventSource;
|
CGEventSourceRef eventSource;
|
||||||
id delegate;
|
id delegate;
|
||||||
bool cursorHidden;
|
bool finishedLaunching;
|
||||||
|
bool cursorHidden;
|
||||||
TISInputSourceRef inputSource;
|
TISInputSourceRef inputSource;
|
||||||
IOHIDManagerRef hidManager;
|
IOHIDManagerRef hidManager;
|
||||||
id unicodeData;
|
id unicodeData;
|
||||||
id helper;
|
id helper;
|
||||||
id keyUpMonitor;
|
id keyUpMonitor;
|
||||||
id keyDownMonitor;
|
id keyDownMonitor;
|
||||||
|
id nibObjects;
|
||||||
|
|
||||||
char keyName[64];
|
char keyName[64];
|
||||||
char text[256];
|
char text[256];
|
||||||
short int keycodes[256];
|
short int keycodes[256];
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
short int key_to_keycode[GLFW_KEY_LAST + 1];
|
||||||
char* clipboardString;
|
char* clipboardString;
|
||||||
CGPoint cascadePoint;
|
CGPoint cascadePoint;
|
||||||
// Where to place the cursor when re-enabled
|
// Where to place the cursor when re-enabled
|
||||||
@@ -184,7 +200,6 @@ typedef struct _GLFWlibraryNS
|
|||||||
struct {
|
struct {
|
||||||
_GLFWDisplayLinkNS entries[256];
|
_GLFWDisplayLinkNS entries[256];
|
||||||
size_t count;
|
size_t count;
|
||||||
id lock;
|
|
||||||
} displayLinks;
|
} displayLinks;
|
||||||
|
|
||||||
} _GLFWlibraryNS;
|
} _GLFWlibraryNS;
|
||||||
@@ -197,6 +212,7 @@ typedef struct _GLFWmonitorNS
|
|||||||
CGDisplayModeRef previousMode;
|
CGDisplayModeRef previousMode;
|
||||||
uint32_t unitNumber;
|
uint32_t unitNumber;
|
||||||
id screen;
|
id screen;
|
||||||
|
double fallbackRefreshRate;
|
||||||
|
|
||||||
} _GLFWmonitorNS;
|
} _GLFWmonitorNS;
|
||||||
|
|
||||||
@@ -217,14 +233,17 @@ typedef struct _GLFWtimerNS
|
|||||||
} _GLFWtimerNS;
|
} _GLFWtimerNS;
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerNS(void);
|
|
||||||
|
|
||||||
void _glfwPollMonitorsNS(void);
|
void _glfwPollMonitorsNS(void);
|
||||||
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
|
||||||
|
|
||||||
float _glfwTransformYNS(float y);
|
float _glfwTransformYNS(float y);
|
||||||
|
|
||||||
|
void* _glfwLoadLocalVulkanLoaderNS(void);
|
||||||
|
|
||||||
void _glfwClearDisplayLinks(void);
|
void _glfwClearDisplayLinks(void);
|
||||||
void _glfwRestartDisplayLinks(void);
|
void _glfwRestartDisplayLinks(void);
|
||||||
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
|
|
||||||
void _glfwDispatchTickCallback(void);
|
void _glfwDispatchTickCallback(void);
|
||||||
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
||||||
|
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
||||||
|
void _glfwCocoaPostEmptyEvent(void);
|
||||||
|
|||||||
60
glfw/cocoa_time.c
vendored
60
glfw/cocoa_time.c
vendored
@@ -1,60 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// 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 <mach/mach_time.h>
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialise timer
|
|
||||||
//
|
|
||||||
void _glfwInitTimerNS(void)
|
|
||||||
{
|
|
||||||
mach_timebase_info_data_t info;
|
|
||||||
mach_timebase_info(&info);
|
|
||||||
|
|
||||||
_glfw.timer.ns.frequency = (info.denom * 1e9) / info.numer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
|
||||||
{
|
|
||||||
return mach_absolute_time();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
|
||||||
{
|
|
||||||
return _glfw.timer.ns.frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
1153
glfw/cocoa_window.m
1153
glfw/cocoa_window.m
File diff suppressed because it is too large
Load Diff
4
glfw/context.c
vendored
4
glfw/context.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
|||||||
19
glfw/dbus_glfw.c
vendored
19
glfw/dbus_glfw.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "dbus_glfw.h"
|
#include "dbus_glfw.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_dbus_watch_ready(int fd, int events, void *data) {
|
on_dbus_watch_ready(int fd UNUSED, int events, void *data) {
|
||||||
DBusWatch *watch = (DBusWatch*)data;
|
DBusWatch *watch = (DBusWatch*)data;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
if (events & POLLERR) flags |= DBUS_WATCH_ERROR;
|
if (events & POLLERR) flags |= DBUS_WATCH_ERROR;
|
||||||
@@ -84,19 +85,19 @@ add_dbus_watch(DBusWatch *watch, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_dbus_watch(DBusWatch *watch, void *data) {
|
remove_dbus_watch(DBusWatch *watch, void *data UNUSED) {
|
||||||
id_type *idp = dbus_watch_get_data(watch);
|
id_type *idp = dbus_watch_get_data(watch);
|
||||||
if (idp) removeWatch(dbus_data->eld, *idp);
|
if (idp) removeWatch(dbus_data->eld, *idp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
toggle_dbus_watch(DBusWatch *watch, void *data) {
|
toggle_dbus_watch(DBusWatch *watch, void *data UNUSED) {
|
||||||
id_type *idp = dbus_watch_get_data(watch);
|
id_type *idp = dbus_watch_get_data(watch);
|
||||||
if (idp) toggleWatch(dbus_data->eld, *idp, dbus_watch_get_enabled(watch));
|
if (idp) toggleWatch(dbus_data->eld, *idp, dbus_watch_get_enabled(watch));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_dbus_timer_ready(id_type timer_id, void *data) {
|
on_dbus_timer_ready(id_type timer_id UNUSED, void *data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
DBusTimeout *t = (DBusTimeout*)data;
|
DBusTimeout *t = (DBusTimeout*)data;
|
||||||
dbus_timeout_handle(t);
|
dbus_timeout_handle(t);
|
||||||
@@ -107,7 +108,7 @@ on_dbus_timer_ready(id_type timer_id, void *data) {
|
|||||||
static dbus_bool_t
|
static dbus_bool_t
|
||||||
add_dbus_timeout(DBusTimeout *timeout, void *data) {
|
add_dbus_timeout(DBusTimeout *timeout, void *data) {
|
||||||
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
|
int enabled = dbus_timeout_get_enabled(timeout) ? 1 : 0;
|
||||||
double interval = ((double)dbus_timeout_get_interval(timeout)) / 1000.0;
|
monotonic_t interval = ms_to_monotonic_t(dbus_timeout_get_interval(timeout));
|
||||||
if (interval < 0) return FALSE;
|
if (interval < 0) return FALSE;
|
||||||
id_type timer_id = addTimer(dbus_data->eld, data, interval, enabled, true, on_dbus_timer_ready, timeout, NULL);
|
id_type timer_id = addTimer(dbus_data->eld, data, interval, enabled, true, on_dbus_timer_ready, timeout, NULL);
|
||||||
if (!timer_id) return FALSE;
|
if (!timer_id) return FALSE;
|
||||||
@@ -123,13 +124,13 @@ add_dbus_timeout(DBusTimeout *timeout, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_dbus_timeout(DBusTimeout *timeout, void *data) {
|
remove_dbus_timeout(DBusTimeout *timeout, void *data UNUSED) {
|
||||||
id_type *idp = dbus_timeout_get_data(timeout);
|
id_type *idp = dbus_timeout_get_data(timeout);
|
||||||
if (idp) removeTimer(dbus_data->eld, *idp);
|
if (idp) removeTimer(dbus_data->eld, *idp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
toggle_dbus_timeout(DBusTimeout *timeout, void *data) {
|
toggle_dbus_timeout(DBusTimeout *timeout, void *data UNUSED) {
|
||||||
id_type *idp = dbus_timeout_get_data(timeout);
|
id_type *idp = dbus_timeout_get_data(timeout);
|
||||||
if (idp) toggleTimer(dbus_data->eld, *idp, dbus_timeout_get_enabled(timeout));
|
if (idp) toggleTimer(dbus_data->eld, *idp, dbus_timeout_get_enabled(timeout));
|
||||||
}
|
}
|
||||||
@@ -178,7 +179,7 @@ glfw_dbus_session_bus_dispatch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_dbus_terminate(_GLFWDBUSData *dbus) {
|
glfw_dbus_terminate(_GLFWDBUSData *dbus UNUSED) {
|
||||||
if (dbus_data) {
|
if (dbus_data) {
|
||||||
dbus_data->eld = NULL;
|
dbus_data->eld = NULL;
|
||||||
dbus_data = NULL;
|
dbus_data = NULL;
|
||||||
|
|||||||
2
glfw/dbus_glfw.h
vendored
2
glfw/dbus_glfw.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
|
|||||||
93
glfw/egl_context.c
vendored
93
glfw/egl_context.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 EGL - www.glfw.org
|
// GLFW 3.4 EGL - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -121,23 +123,24 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
XVisualInfo vi = {0};
|
|
||||||
|
|
||||||
// Only consider EGLConfigs with associated Visuals
|
|
||||||
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
|
||||||
if (!vi.visualid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (desired->transparent)
|
|
||||||
{
|
{
|
||||||
int count;
|
XVisualInfo vi = {0};
|
||||||
XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display,
|
|
||||||
VisualIDMask, &vi,
|
// Only consider EGLConfigs with associated Visuals
|
||||||
&count);
|
vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
|
||||||
if (vis)
|
if (!vi.visualid)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (desired->transparent)
|
||||||
{
|
{
|
||||||
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
int count;
|
||||||
XFree(vis);
|
XVisualInfo* vis =
|
||||||
|
XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
|
||||||
|
if (vis)
|
||||||
|
{
|
||||||
|
u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
|
||||||
|
XFree(vis);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // _GLFW_X11
|
#endif // _GLFW_X11
|
||||||
@@ -253,8 +256,8 @@ static GLFWglproc getProcAddressEGL(const char* procname)
|
|||||||
|
|
||||||
if (window->context.egl.client)
|
if (window->context.egl.client)
|
||||||
{
|
{
|
||||||
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
|
GLFWglproc proc = NULL;
|
||||||
procname);
|
glfw_dlsym(proc, window->context.egl.client, procname);
|
||||||
if (proc)
|
if (proc)
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
@@ -335,38 +338,22 @@ bool _glfwInitEGL(void)
|
|||||||
|
|
||||||
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
|
||||||
|
|
||||||
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib)
|
glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
|
glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs");
|
||||||
_glfw.egl.GetConfigs = (PFN_eglGetConfigs)
|
glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
|
glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError");
|
||||||
_glfw.egl.GetDisplay = (PFN_eglGetDisplay)
|
glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
|
glfw_dlsym(_glfw.egl.Terminate, _glfw.egl.handle, "eglTerminate");
|
||||||
_glfw.egl.GetError = (PFN_eglGetError)
|
glfw_dlsym(_glfw.egl.BindAPI, _glfw.egl.handle, "eglBindAPI");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetError");
|
glfw_dlsym(_glfw.egl.CreateContext, _glfw.egl.handle, "eglCreateContext");
|
||||||
_glfw.egl.Initialize = (PFN_eglInitialize)
|
glfw_dlsym(_glfw.egl.DestroySurface, _glfw.egl.handle, "eglDestroySurface");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglInitialize");
|
glfw_dlsym(_glfw.egl.DestroyContext, _glfw.egl.handle, "eglDestroyContext");
|
||||||
_glfw.egl.Terminate = (PFN_eglTerminate)
|
glfw_dlsym(_glfw.egl.CreateWindowSurface, _glfw.egl.handle, "eglCreateWindowSurface");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglTerminate");
|
glfw_dlsym(_glfw.egl.MakeCurrent, _glfw.egl.handle, "eglMakeCurrent");
|
||||||
_glfw.egl.BindAPI = (PFN_eglBindAPI)
|
glfw_dlsym(_glfw.egl.SwapBuffers, _glfw.egl.handle, "eglSwapBuffers");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
|
glfw_dlsym(_glfw.egl.SwapInterval, _glfw.egl.handle, "eglSwapInterval");
|
||||||
_glfw.egl.CreateContext = (PFN_eglCreateContext)
|
glfw_dlsym(_glfw.egl.QueryString, _glfw.egl.handle, "eglQueryString");
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
|
glfw_dlsym(_glfw.egl.GetProcAddress, _glfw.egl.handle, "eglGetProcAddress");
|
||||||
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
|
|
||||||
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
|
|
||||||
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
|
|
||||||
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
|
|
||||||
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
|
|
||||||
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
|
|
||||||
_glfw.egl.QueryString = (PFN_eglQueryString)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
|
|
||||||
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
|
|
||||||
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
|
|
||||||
|
|
||||||
if (!_glfw.egl.GetConfigAttrib ||
|
if (!_glfw.egl.GetConfigAttrib ||
|
||||||
!_glfw.egl.GetConfigs ||
|
!_glfw.egl.GetConfigs ||
|
||||||
@@ -446,7 +433,7 @@ void _glfwTerminateEGL(void)
|
|||||||
|
|
||||||
#define setAttrib(a, v) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = a; \
|
attribs[index++] = a; \
|
||||||
attribs[index++] = v; \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
@@ -714,7 +701,7 @@ bool _glfwCreateContextEGL(_GLFWwindow* window,
|
|||||||
// Returns the Visual and depth of the chosen EGLConfig
|
// Returns the Visual and depth of the chosen EGLConfig
|
||||||
//
|
//
|
||||||
#if defined(_GLFW_X11)
|
#if defined(_GLFW_X11)
|
||||||
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig UNUSED,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
|
|||||||
16
glfw/egl_context.h
vendored
16
glfw/egl_context.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 EGL - www.glfw.org
|
// GLFW 3.4 EGL - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -173,13 +173,13 @@ typedef struct _GLFWlibraryEGL
|
|||||||
{
|
{
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
bool prefix;
|
bool prefix;
|
||||||
|
|
||||||
bool KHR_create_context;
|
bool KHR_create_context;
|
||||||
bool KHR_create_context_no_error;
|
bool KHR_create_context_no_error;
|
||||||
bool KHR_gl_colorspace;
|
bool KHR_gl_colorspace;
|
||||||
bool KHR_get_all_proc_addresses;
|
bool KHR_get_all_proc_addresses;
|
||||||
bool KHR_context_flush_control;
|
bool KHR_context_flush_control;
|
||||||
|
|
||||||
void* handle;
|
void* handle;
|
||||||
|
|
||||||
|
|||||||
125
glfw/glfw.py
125
glfw/glfw.py
@@ -6,52 +6,73 @@ import json
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Callable, List, Optional, Tuple
|
||||||
|
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos = 'darwin' in _plat
|
is_linux = 'linux' in _plat
|
||||||
is_freebsd = 'freebsd' in _plat
|
|
||||||
is_netbsd = 'netbsd' in _plat
|
|
||||||
is_dragonflybsd = 'dragonfly' in _plat
|
|
||||||
is_bsd = is_freebsd or is_netbsd or is_dragonflybsd
|
|
||||||
base = os.path.dirname(os.path.abspath(__file__))
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
def wayland_protocol_file_name(base, ext='c'):
|
class Env:
|
||||||
|
|
||||||
|
cc: str = ''
|
||||||
|
cppflags: List[str] = []
|
||||||
|
cflags: List[str] = []
|
||||||
|
ldflags: List[str] = []
|
||||||
|
ldpaths: List[str] = []
|
||||||
|
ccver: Tuple[int, int]
|
||||||
|
|
||||||
|
# glfw stuff
|
||||||
|
all_headers: List[str] = []
|
||||||
|
sources: List[str] = []
|
||||||
|
wayland_packagedir: str = ''
|
||||||
|
wayland_scanner: str = ''
|
||||||
|
wayland_scanner_code: str = ''
|
||||||
|
wayland_protocols: Tuple[str, ...] = ()
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
|
||||||
|
ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
|
||||||
|
):
|
||||||
|
self.cc, self.cppflags, self.cflags, self.ldflags, self.ldpaths = cc, cppflags, cflags, ldflags, [] if ldpaths is None else ldpaths
|
||||||
|
self.ccver = ccver
|
||||||
|
|
||||||
|
def copy(self) -> 'Env':
|
||||||
|
ans = Env(self.cc, list(self.cppflags), list(self.cflags), list(self.ldflags), list(self.ldpaths), self.ccver)
|
||||||
|
ans.all_headers = list(self.all_headers)
|
||||||
|
ans.sources = list(self.sources)
|
||||||
|
ans.wayland_packagedir = self.wayland_packagedir
|
||||||
|
ans.wayland_scanner = self.wayland_scanner
|
||||||
|
ans.wayland_scanner_code = self.wayland_scanner_code
|
||||||
|
ans.wayland_protocols = self.wayland_protocols
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
|
def wayland_protocol_file_name(base: str, ext: str = 'c') -> str:
|
||||||
base = os.path.basename(base).rpartition('.')[0]
|
base = os.path.basename(base).rpartition('.')[0]
|
||||||
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
return 'wayland-{}-client-protocol.{}'.format(base, ext)
|
||||||
|
|
||||||
|
|
||||||
def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
|
def init_env(env: Env, pkg_config: Callable, at_least_version: Callable, test_compile: Callable, module: str = 'x11') -> Env:
|
||||||
ans = env.copy()
|
ans = env.copy()
|
||||||
ans.cflags = [
|
|
||||||
x for x in ans.cflags
|
|
||||||
if x not in '-Wpedantic -Wextra -pedantic-errors'.split()
|
|
||||||
]
|
|
||||||
if not is_macos:
|
|
||||||
ans.cflags.append('-pthread')
|
|
||||||
ans.ldpaths.append('-pthread')
|
|
||||||
ans.cflags.append('-fpic')
|
ans.cflags.append('-fpic')
|
||||||
ans.cppflags.append('-D_GLFW_' + module.upper())
|
ans.cppflags.append('-D_GLFW_' + module.upper())
|
||||||
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
ans.cppflags.append('-D_GLFW_BUILD_DLL')
|
||||||
|
|
||||||
if is_macos:
|
with open(os.path.join(base, 'source-info.json')) as f:
|
||||||
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
|
sinfo = json.load(f)
|
||||||
ans.ldpaths.extend(
|
|
||||||
"-framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo".
|
|
||||||
split()
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
ans.ldpaths.extend('-lrt -lm -ldl'.split())
|
|
||||||
sinfo = json.load(open(os.path.join(base, 'source-info.json')))
|
|
||||||
module_sources = list(sinfo[module]['sources'])
|
module_sources = list(sinfo[module]['sources'])
|
||||||
if module in ('x11', 'wayland'):
|
if module in ('x11', 'wayland'):
|
||||||
remove = 'linux_joystick.c' if is_bsd else 'null_joystick.c'
|
remove = 'null_joystick.c' if is_linux else 'linux_joystick.c'
|
||||||
module_sources.remove(remove)
|
module_sources.remove(remove)
|
||||||
|
|
||||||
ans.sources = sinfo['common']['sources'] + module_sources
|
ans.sources = sinfo['common']['sources'] + module_sources
|
||||||
ans.all_headers = [x for x in os.listdir(base) if x.endswith('.h')]
|
ans.all_headers = [x for x in os.listdir(base) if x.endswith('.h')]
|
||||||
|
|
||||||
if module in ('x11', 'wayland'):
|
if module in ('x11', 'wayland'):
|
||||||
|
ans.cflags.append('-pthread')
|
||||||
|
ans.ldpaths.append('-pthread')
|
||||||
|
ans.ldpaths.extend('-lrt -lm -ldl'.split())
|
||||||
at_least_version('xkbcommon', 0, 5)
|
at_least_version('xkbcommon', 0, 5)
|
||||||
|
|
||||||
if module == 'x11':
|
if module == 'x11':
|
||||||
@@ -60,8 +81,9 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
|
|||||||
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
ans.ldpaths.extend(pkg_config(dep, '--libs'))
|
||||||
|
|
||||||
elif module == 'cocoa':
|
elif module == 'cocoa':
|
||||||
for f in 'Cocoa IOKit CoreFoundation CoreVideo'.split():
|
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
|
||||||
ans.ldpaths.extend(('-framework', f))
|
for f_ in 'Cocoa IOKit CoreFoundation CoreVideo'.split():
|
||||||
|
ans.ldpaths.extend(('-framework', f_))
|
||||||
|
|
||||||
elif module == 'wayland':
|
elif module == 'wayland':
|
||||||
at_least_version('wayland-protocols', *sinfo['wayland_protocols'])
|
at_least_version('wayland-protocols', *sinfo['wayland_protocols'])
|
||||||
@@ -88,7 +110,8 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir):
|
def build_wayland_protocols(env: Env, Command: Callable, parallel_run: Callable, emphasis: Callable, newer: Callable, dest_dir: str) -> None:
|
||||||
|
items = []
|
||||||
for protocol in env.wayland_protocols:
|
for protocol in env.wayland_protocols:
|
||||||
src = os.path.join(env.wayland_packagedir, protocol)
|
src = os.path.join(env.wayland_packagedir, protocol)
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
@@ -98,13 +121,17 @@ def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir):
|
|||||||
dest = os.path.join(dest_dir, dest)
|
dest = os.path.join(dest_dir, dest)
|
||||||
if newer(dest, src):
|
if newer(dest, src):
|
||||||
q = 'client-header' if ext == 'h' else env.wayland_scanner_code
|
q = 'client-header' if ext == 'h' else env.wayland_scanner_code
|
||||||
run_tool([env.wayland_scanner, q, src, dest],
|
items.append(Command(
|
||||||
desc='Generating {} ...'.format(emphasis(os.path.basename(dest))))
|
'Generating {} ...'.format(emphasis(os.path.basename(dest))),
|
||||||
|
[env.wayland_scanner, q, src, dest],
|
||||||
|
lambda: True, None, None, None))
|
||||||
|
if items:
|
||||||
|
parallel_run(items)
|
||||||
|
|
||||||
|
|
||||||
class Arg:
|
class Arg:
|
||||||
|
|
||||||
def __init__(self, decl):
|
def __init__(self, decl: str):
|
||||||
self.type, self.name = decl.rsplit(' ', 1)
|
self.type, self.name = decl.rsplit(' ', 1)
|
||||||
self.type = self.type.strip()
|
self.type = self.type.strip()
|
||||||
self.name = self.name.strip()
|
self.name = self.name.strip()
|
||||||
@@ -112,13 +139,13 @@ class Arg:
|
|||||||
self.name = self.name[1:]
|
self.name = self.name[1:]
|
||||||
self.type = self.type + '*'
|
self.type = self.type + '*'
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return 'Arg({}, {})'.format(self.type, self.name)
|
return 'Arg({}, {})'.format(self.type, self.name)
|
||||||
|
|
||||||
|
|
||||||
class Function:
|
class Function:
|
||||||
|
|
||||||
def __init__(self, declaration, check_fail=True):
|
def __init__(self, declaration: str, check_fail: bool = True):
|
||||||
self.check_fail = check_fail
|
self.check_fail = check_fail
|
||||||
m = re.match(
|
m = re.match(
|
||||||
r'(.+?)\s+(glfw[A-Z][a-zA-Z0-9]+)[(](.+)[)]$', declaration
|
r'(.+?)\s+(glfw[A-Z][a-zA-Z0-9]+)[(](.+)[)]$', declaration
|
||||||
@@ -137,14 +164,14 @@ class Function:
|
|||||||
if not self.args:
|
if not self.args:
|
||||||
self.args = [Arg('void v')]
|
self.args = [Arg('void v')]
|
||||||
|
|
||||||
def declaration(self):
|
def declaration(self) -> str:
|
||||||
return 'typedef {restype} (*{name}_func)({args});\n{name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
return 'typedef {restype} (*{name}_func)({args});\nGFW_EXTERN {name}_func {name}_impl;\n#define {name} {name}_impl'.format(
|
||||||
restype=self.restype,
|
restype=self.restype,
|
||||||
name=self.name,
|
name=self.name,
|
||||||
args=', '.join(a.type for a in self.args)
|
args=', '.join(a.type for a in self.args)
|
||||||
)
|
)
|
||||||
|
|
||||||
def load(self):
|
def load(self) -> str:
|
||||||
ans = '*(void **) (&{name}_impl) = dlsym(handle, "{name}");'.format(
|
ans = '*(void **) (&{name}_impl) = dlsym(handle, "{name}");'.format(
|
||||||
name=self.name
|
name=self.name
|
||||||
)
|
)
|
||||||
@@ -155,8 +182,9 @@ class Function:
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def generate_wrappers(glfw_header):
|
def generate_wrappers(glfw_header: str) -> None:
|
||||||
src = open(glfw_header).read()
|
with open(glfw_header) as f:
|
||||||
|
src = f.read()
|
||||||
functions = []
|
functions = []
|
||||||
first = None
|
first = None
|
||||||
for m in re.finditer(r'^GLFWAPI\s+(.+[)]);\s*$', src, flags=re.MULTILINE):
|
for m in re.finditer(r'^GLFWAPI\s+(.+[)]);\s*$', src, flags=re.MULTILINE):
|
||||||
@@ -173,13 +201,14 @@ def generate_wrappers(glfw_header):
|
|||||||
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
GLFWcocoatextinputfilterfun glfwSetCocoaTextInputFilter(GLFWwindow* window, GLFWcocoatextinputfilterfun callback)
|
||||||
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback)
|
||||||
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback)
|
||||||
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, void* cocoa_key, void* cocoa_mods)
|
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
|
||||||
|
void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char* cocoa_key, size_t key_sz, int* cocoa_mods)
|
||||||
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
|
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
|
||||||
void* glfwGetX11Display(void)
|
void* glfwGetX11Display(void)
|
||||||
int32_t glfwGetX11Window(GLFWwindow* window)
|
int32_t glfwGetX11Window(GLFWwindow* window)
|
||||||
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
|
||||||
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
const char* glfwGetPrimarySelectionString(GLFWwindow* window, void)
|
||||||
int glfwGetXKBScancode(const char* key_name, int case_sensitive)
|
int glfwGetNativeKeyForName(const char* key_name, int case_sensitive)
|
||||||
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
void glfwRequestWaylandFrameEvent(GLFWwindow *handle, unsigned long long id, GLFWwaylandframecallbackfunc callback)
|
||||||
unsigned long long glfwDBusUserNotify(const char *app_name, const char* icon, const char *summary, const char *body, \
|
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)
|
const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callback, void *data)
|
||||||
@@ -193,15 +222,26 @@ const char *action_text, int32_t timeout, GLFWDBusnotificationcreatedfun callbac
|
|||||||
p = src.find('*/', p)
|
p = src.find('*/', p)
|
||||||
preamble = src[p + 2:first]
|
preamble = src[p + 2:first]
|
||||||
header = '''\
|
header = '''\
|
||||||
|
//
|
||||||
|
// THIS FILE IS GENERATED BY glfw.py
|
||||||
|
//
|
||||||
|
// SAVE YOURSELF SOME TIME, DO NOT MANUALLY EDIT
|
||||||
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "monotonic.h"
|
||||||
|
|
||||||
|
#ifndef GFW_EXTERN
|
||||||
|
#define GFW_EXTERN extern
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long);
|
||||||
typedef int (* GLFWapplicationshouldhandlereopenfun)(int);
|
typedef bool (* GLFWapplicationshouldhandlereopenfun)(int);
|
||||||
typedef int (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
typedef void (* GLFWapplicationwillfinishlaunchingfun)(void);
|
||||||
|
typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*);
|
||||||
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
typedef void (* GLFWcocoarenderframefun)(GLFWwindow*);
|
||||||
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
|
typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id);
|
||||||
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
|
typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*);
|
||||||
@@ -214,6 +254,7 @@ const char* load_glfw(const char* path);
|
|||||||
f.write(header)
|
f.write(header)
|
||||||
|
|
||||||
code = '''
|
code = '''
|
||||||
|
#define GFW_EXTERN
|
||||||
#include "data-types.h"
|
#include "data-types.h"
|
||||||
#include "glfw-wrapper.h"
|
#include "glfw-wrapper.h"
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -243,7 +284,7 @@ unload_glfw(void) {
|
|||||||
f.write(code)
|
f.write(code)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||||
generate_wrappers('glfw3.h')
|
generate_wrappers('glfw3.h')
|
||||||
|
|
||||||
|
|||||||
946
glfw/glfw3.h
vendored
946
glfw/glfw3.h
vendored
File diff suppressed because it is too large
Load Diff
66
glfw/glx_context.c
vendored
66
glfw/glx_context.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 GLX - www.glfw.org
|
// GLFW 3.4 GLX - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -142,7 +144,7 @@ static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
|
|||||||
|
|
||||||
// Create the OpenGL context using legacy API
|
// Create the OpenGL context using legacy API
|
||||||
//
|
//
|
||||||
static GLXContext createLegacyContextGLX(_GLFWwindow* window,
|
static GLXContext createLegacyContextGLX(_GLFWwindow* window UNUSED,
|
||||||
GLXFBConfig fbconfig,
|
GLXFBConfig fbconfig,
|
||||||
GLXContext share)
|
GLXContext share)
|
||||||
{
|
{
|
||||||
@@ -222,8 +224,11 @@ static GLFWglproc getProcAddressGLX(const char* procname)
|
|||||||
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
|
return _glfw.glx.GetProcAddress((const GLubyte*) procname);
|
||||||
else if (_glfw.glx.GetProcAddressARB)
|
else if (_glfw.glx.GetProcAddressARB)
|
||||||
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
|
||||||
else
|
else {
|
||||||
return _glfw_dlsym(_glfw.glx.handle, procname);
|
GLFWglproc ans = NULL;
|
||||||
|
glfw_dlsym(ans, _glfw.glx.handle, procname);
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroyContextGLX(_GLFWwindow* window)
|
static void destroyContextGLX(_GLFWwindow* window)
|
||||||
@@ -280,36 +285,21 @@ bool _glfwInitGLX(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.glx.GetFBConfigs =
|
glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
|
glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib");
|
||||||
_glfw.glx.GetFBConfigAttrib =
|
glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
|
glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension");
|
||||||
_glfw.glx.GetClientString =
|
glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
|
glfw_dlsym(_glfw.glx.DestroyContext, _glfw.glx.handle, "glXDestroyContext");
|
||||||
_glfw.glx.QueryExtension =
|
glfw_dlsym(_glfw.glx.MakeCurrent, _glfw.glx.handle, "glXMakeCurrent");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
|
glfw_dlsym(_glfw.glx.SwapBuffers, _glfw.glx.handle, "glXSwapBuffers");
|
||||||
_glfw.glx.QueryVersion =
|
glfw_dlsym(_glfw.glx.QueryExtensionsString, _glfw.glx.handle, "glXQueryExtensionsString");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
|
glfw_dlsym(_glfw.glx.CreateNewContext, _glfw.glx.handle, "glXCreateNewContext");
|
||||||
_glfw.glx.DestroyContext =
|
glfw_dlsym(_glfw.glx.CreateWindow, _glfw.glx.handle, "glXCreateWindow");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
|
glfw_dlsym(_glfw.glx.DestroyWindow, _glfw.glx.handle, "glXDestroyWindow");
|
||||||
_glfw.glx.MakeCurrent =
|
glfw_dlsym(_glfw.glx.GetProcAddress, _glfw.glx.handle, "glXGetProcAddress");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
|
glfw_dlsym(_glfw.glx.GetProcAddressARB, _glfw.glx.handle, "glXGetProcAddressARB");
|
||||||
_glfw.glx.SwapBuffers =
|
glfw_dlsym(_glfw.glx.GetVisualFromFBConfig, _glfw.glx.handle, "glXGetVisualFromFBConfig");
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
|
|
||||||
_glfw.glx.QueryExtensionsString =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
|
|
||||||
_glfw.glx.CreateNewContext =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
|
|
||||||
_glfw.glx.CreateWindow =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
|
|
||||||
_glfw.glx.DestroyWindow =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
|
|
||||||
_glfw.glx.GetProcAddress =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
|
|
||||||
_glfw.glx.GetProcAddressARB =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
|
|
||||||
_glfw.glx.GetVisualFromFBConfig =
|
|
||||||
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
|
|
||||||
|
|
||||||
if (!_glfw.glx.GetFBConfigs ||
|
if (!_glfw.glx.GetFBConfigs ||
|
||||||
!_glfw.glx.GetFBConfigAttrib ||
|
!_glfw.glx.GetFBConfigAttrib ||
|
||||||
@@ -433,7 +423,7 @@ void _glfwTerminateGLX(void)
|
|||||||
|
|
||||||
#define setAttrib(a, v) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = a; \
|
attribs[index++] = a; \
|
||||||
attribs[index++] = v; \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
@@ -631,8 +621,8 @@ bool _glfwCreateContextGLX(_GLFWwindow* window,
|
|||||||
|
|
||||||
// Returns the Visual and depth of the chosen GLXFBConfig
|
// Returns the Visual and depth of the chosen GLXFBConfig
|
||||||
//
|
//
|
||||||
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig UNUSED,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig UNUSED,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth)
|
Visual** visual, int* depth)
|
||||||
{
|
{
|
||||||
|
|||||||
33
glfw/glx_context.h
vendored
33
glfw/glx_context.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 GLX - www.glfw.org
|
// GLFW 3.4 GLX - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -107,8 +107,8 @@ typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLX
|
|||||||
#define glXCreateWindow _glfw.glx.CreateWindow
|
#define glXCreateWindow _glfw.glx.CreateWindow
|
||||||
#define glXDestroyWindow _glfw.glx.DestroyWindow
|
#define glXDestroyWindow _glfw.glx.DestroyWindow
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx;
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
|
||||||
|
|
||||||
|
|
||||||
// GLX-specific per-context data
|
// GLX-specific per-context data
|
||||||
@@ -153,18 +153,18 @@ typedef struct _GLFWlibraryGLX
|
|||||||
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
|
||||||
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
||||||
bool SGI_swap_control;
|
bool SGI_swap_control;
|
||||||
bool EXT_swap_control;
|
bool EXT_swap_control;
|
||||||
bool MESA_swap_control;
|
bool MESA_swap_control;
|
||||||
bool ARB_multisample;
|
bool ARB_multisample;
|
||||||
bool ARB_framebuffer_sRGB;
|
bool ARB_framebuffer_sRGB;
|
||||||
bool EXT_framebuffer_sRGB;
|
bool EXT_framebuffer_sRGB;
|
||||||
bool ARB_create_context;
|
bool ARB_create_context;
|
||||||
bool ARB_create_context_profile;
|
bool ARB_create_context_profile;
|
||||||
bool ARB_create_context_robustness;
|
bool ARB_create_context_robustness;
|
||||||
bool EXT_create_context_es2_profile;
|
bool EXT_create_context_es2_profile;
|
||||||
bool ARB_create_context_no_error;
|
bool ARB_create_context_no_error;
|
||||||
bool ARB_context_flush_control;
|
bool ARB_context_flush_control;
|
||||||
|
|
||||||
} _GLFWlibraryGLX;
|
} _GLFWlibraryGLX;
|
||||||
|
|
||||||
@@ -178,4 +178,3 @@ bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig,
|
const _GLFWfbconfig* fbconfig,
|
||||||
Visual** visual, int* depth);
|
Visual** visual, int* depth);
|
||||||
|
|
||||||
|
|||||||
37
glfw/ibus_glfw.c
vendored
37
glfw/ibus_glfw.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
@@ -57,7 +57,7 @@ test_env_var(const char *name, const char *val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
MIN(size_t a, size_t b) {
|
GLFW_MIN(size_t a, size_t b) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,17 +107,21 @@ get_ibus_text_from_message(DBusMessage *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
send_text(const char *text, int state) {
|
send_text(const char *text, int ime_state) {
|
||||||
_GLFWwindow *w = _glfwFocusedWindow();
|
_GLFWwindow *w = _glfwFocusedWindow();
|
||||||
if (w && w->callbacks.keyboard) {
|
if (w && w->callbacks.keyboard) {
|
||||||
w->callbacks.keyboard((GLFWwindow*) w, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, text, state);
|
GLFWkeyevent fake_ev;
|
||||||
|
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
|
||||||
|
fake_ev.text = text;
|
||||||
|
fake_ev.ime_state = ime_state;
|
||||||
|
w->callbacks.keyboard((GLFWwindow*) w, &fake_ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection handling {{{
|
// Connection handling {{{
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) {
|
message_handler(DBusConnection *conn UNUSED, DBusMessage *msg, void *user_data) {
|
||||||
// To monitor signals from IBUS, use
|
// To monitor signals from IBUS, use
|
||||||
// dbus-monitor --address `ibus address` "type='signal',interface='org.freedesktop.IBus.InputContext'"
|
// dbus-monitor --address `ibus address` "type='signal',interface='org.freedesktop.IBus.InputContext'"
|
||||||
_GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data;
|
_GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data;
|
||||||
@@ -151,7 +155,7 @@ get_ibus_address_file_name(void) {
|
|||||||
addr = getenv("IBUS_ADDRESS");
|
addr = getenv("IBUS_ADDRESS");
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
if (addr && addr[0]) {
|
if (addr && addr[0]) {
|
||||||
memcpy(ans, addr, MIN(strlen(addr), sizeof(ans)));
|
memcpy(ans, addr, GLFW_MIN(strlen(addr), sizeof(ans)));
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,31 +397,36 @@ ibus_key_state(unsigned int glfw_modifiers, int action) {
|
|||||||
void
|
void
|
||||||
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
|
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
|
||||||
uint32_t handled = 0;
|
uint32_t handled = 0;
|
||||||
KeyEvent *ev = (KeyEvent*)data;
|
_GLFWIBUSKeyEvent *ev = (_GLFWIBUSKeyEvent*)data;
|
||||||
bool is_release = ev->action == GLFW_RELEASE;
|
// Restore key's text from the text embedded in the structure.
|
||||||
|
ev->glfw_ev.text = ev->__embedded_text;
|
||||||
|
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
if (errmsg) {
|
if (errmsg) {
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
|
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
|
||||||
failed = true;
|
failed = true;
|
||||||
} else {
|
} else {
|
||||||
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
|
glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID);
|
||||||
debug("IBUS processed scancode: 0x%x release: %d handled: %u\n", ev->keycode, is_release, handled);
|
debug("IBUS processed native_key: 0x%x release: %d handled: %u\n", ev->glfw_ev.native_key, is_release, handled);
|
||||||
}
|
}
|
||||||
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
|
glfw_xkb_key_from_ime(ev, handled ? true : false, failed);
|
||||||
free(ev);
|
free(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus) {
|
ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus) {
|
||||||
if (!check_connection(ibus)) return false;
|
if (!check_connection(ibus)) return false;
|
||||||
KeyEvent *ev = malloc(sizeof(KeyEvent));
|
_GLFWIBUSKeyEvent *ev = calloc(1, sizeof(_GLFWIBUSKeyEvent));
|
||||||
if (!ev) return false;
|
if (!ev) return false;
|
||||||
memcpy(ev, ev_, sizeof(KeyEvent));
|
memcpy(ev, ev_, sizeof(_GLFWIBUSKeyEvent));
|
||||||
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
|
// Put the key's text in a field IN the structure, for proper serialization.
|
||||||
|
if (ev->glfw_ev.text) strncpy(ev->__embedded_text, ev->glfw_ev.text, sizeof(ev->__embedded_text) - 1);
|
||||||
|
ev->glfw_ev.text = NULL;
|
||||||
|
uint32_t state = ibus_key_state(ev->glfw_ev.mods, ev->glfw_ev.action);
|
||||||
if (!glfw_dbus_call_method_with_reply(
|
if (!glfw_dbus_call_method_with_reply(
|
||||||
ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
|
ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
|
||||||
3000, key_event_processed, ev,
|
3000, key_event_processed, ev,
|
||||||
DBUS_TYPE_UINT32, &ev->ibus_sym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
|
DBUS_TYPE_UINT32, &ev->ibus_keysym, DBUS_TYPE_UINT32, &ev->ibus_keycode, DBUS_TYPE_UINT32,
|
||||||
&state, DBUS_TYPE_INVALID)) {
|
&state, DBUS_TYPE_INVALID)) {
|
||||||
free(ev);
|
free(ev);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
17
glfw/ibus_glfw.h
vendored
17
glfw/ibus_glfw.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
#include "dbus_glfw.h"
|
#include "dbus_glfw.h"
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
@@ -38,18 +39,16 @@ typedef struct {
|
|||||||
} _GLFWIBUSData;
|
} _GLFWIBUSData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
xkb_keycode_t keycode, ibus_keycode;
|
xkb_keycode_t ibus_keycode;
|
||||||
xkb_keysym_t keysym, ibus_sym;
|
xkb_keysym_t ibus_keysym;
|
||||||
unsigned int glfw_modifiers;
|
|
||||||
int action;
|
|
||||||
GLFWid window_id;
|
GLFWid window_id;
|
||||||
int glfw_keycode;
|
GLFWkeyevent glfw_ev;
|
||||||
char text[64];
|
char __embedded_text[64];
|
||||||
} KeyEvent;
|
} _GLFWIBUSKeyEvent;
|
||||||
|
|
||||||
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
|
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
|
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused);
|
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, bool focused);
|
||||||
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
|
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
|
||||||
bool ibus_process_key(const KeyEvent *ev_, _GLFWIBUSData *ibus);
|
bool ibus_process_key(const _GLFWIBUSKeyEvent *ev_, _GLFWIBUSData *ibus);
|
||||||
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);
|
void glfw_ibus_set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h);
|
||||||
|
|||||||
20
glfw/init.c
vendored
20
glfw/init.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "mappings.h"
|
#include "mappings.h"
|
||||||
@@ -199,7 +201,7 @@ _glfwDebug(const char *format, ...) {
|
|||||||
{
|
{
|
||||||
va_list vl;
|
va_list vl;
|
||||||
|
|
||||||
fprintf(stderr, "[%.4f] ", glfwGetTime());
|
fprintf(stderr, "[%.4f] ", monotonic_t_to_s_double(glfwGetTime()));
|
||||||
va_start(vl, format);
|
va_start(vl, format);
|
||||||
vfprintf(stderr, format, vl);
|
vfprintf(stderr, format, vl);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
@@ -212,10 +214,11 @@ _glfwDebug(const char *format, ...) {
|
|||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GLFWAPI int glfwInit(void)
|
GLFWAPI int glfwInit(monotonic_t start_time)
|
||||||
{
|
{
|
||||||
if (_glfw.initialized)
|
if (_glfw.initialized)
|
||||||
return true;
|
return true;
|
||||||
|
monotonic_start_time = start_time;
|
||||||
|
|
||||||
memset(&_glfw, 0, sizeof(_glfw));
|
memset(&_glfw, 0, sizeof(_glfw));
|
||||||
_glfw.hints.init = _glfwInitHints;
|
_glfw.hints.init = _glfwInitHints;
|
||||||
@@ -237,7 +240,6 @@ GLFWAPI int glfwInit(void)
|
|||||||
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
_glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
|
||||||
|
|
||||||
_glfw.initialized = true;
|
_glfw.initialized = true;
|
||||||
_glfw.timer.offset = _glfwPlatformGetTimerValue();
|
|
||||||
|
|
||||||
glfwDefaultWindowHints();
|
glfwDefaultWindowHints();
|
||||||
|
|
||||||
@@ -342,23 +344,19 @@ GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *data)
|
|||||||
_glfwPlatformRunMainLoop(callback, data);
|
_glfwPlatformRunMainLoop(callback, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwRequestTickCallback(void) {
|
|
||||||
_glfwPlatformRequestTickCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwStopMainLoop(void) {
|
GLFWAPI void glfwStopMainLoop(void) {
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
_glfwPlatformStopMainLoop();
|
_glfwPlatformStopMainLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI unsigned long long glfwAddTimer(
|
GLFWAPI unsigned long long glfwAddTimer(
|
||||||
double interval, bool repeats, GLFWuserdatafun callback,
|
monotonic_t interval, bool repeats, GLFWuserdatafun callback,
|
||||||
void *callback_data, GLFWuserdatafun free_callback)
|
void *callback_data, GLFWuserdatafun free_callback)
|
||||||
{
|
{
|
||||||
return _glfwPlatformAddTimer(interval, repeats, callback, callback_data, free_callback);
|
return _glfwPlatformAddTimer(interval, repeats, callback, callback_data, free_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
|
||||||
_glfwPlatformUpdateTimer(timer_id, interval, enabled);
|
_glfwPlatformUpdateTimer(timer_id, interval, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
418
glfw/input.c
vendored
418
glfw/input.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,8 +24,11 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
@@ -254,33 +257,44 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string)
|
|||||||
////// GLFW event API //////
|
////// GLFW event API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Notifies shared code of a key event
|
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods)
|
||||||
//
|
|
||||||
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state)
|
|
||||||
{
|
{
|
||||||
if (key >= 0 && key <= GLFW_KEY_LAST)
|
ev->key = key;
|
||||||
|
ev->native_key = native_key;
|
||||||
|
ev->action = action;
|
||||||
|
ev->mods = mods;
|
||||||
|
ev->text = NULL;
|
||||||
|
ev->ime_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifies shared code of a physical key event
|
||||||
|
//
|
||||||
|
void _glfwInputKeyboard(_GLFWwindow* window, GLFWkeyevent* ev)
|
||||||
|
{
|
||||||
|
if (ev->key >= 0 && ev->key <= GLFW_KEY_LAST)
|
||||||
{
|
{
|
||||||
bool repeated = false;
|
bool repeated = false;
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
|
if (ev->action == GLFW_RELEASE && window->keys[ev->key] == GLFW_RELEASE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
|
if (ev->action == GLFW_PRESS && window->keys[ev->key] == GLFW_PRESS)
|
||||||
repeated = true;
|
repeated = true;
|
||||||
|
|
||||||
if (action == GLFW_RELEASE && window->stickyKeys)
|
if (ev->action == GLFW_RELEASE && window->stickyKeys)
|
||||||
window->keys[key] = _GLFW_STICK;
|
window->keys[ev->key] = _GLFW_STICK;
|
||||||
else
|
else
|
||||||
window->keys[key] = (char) action;
|
window->keys[ev->key] = (char) ev->action;
|
||||||
|
|
||||||
if (repeated)
|
if (repeated)
|
||||||
action = GLFW_REPEAT;
|
ev->action = GLFW_REPEAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FIXME: will need to update ev->virtual_mods here too?
|
||||||
if (window->callbacks.keyboard) {
|
if (window->callbacks.keyboard) {
|
||||||
if (!window->lockKeyMods) mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
|
if (!window->lockKeyMods) ev->mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
|
||||||
window->callbacks.keyboard((GLFWwindow*) window, key, scancode, action, mods, text, state);
|
window->callbacks.keyboard((GLFWwindow*) window, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,10 +350,11 @@ void _glfwInputCursorEnter(_GLFWwindow* window, bool entered)
|
|||||||
|
|
||||||
// Notifies shared code of files or directories dropped on a window
|
// Notifies shared code of files or directories dropped on a window
|
||||||
//
|
//
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
|
int _glfwInputDrop(_GLFWwindow* window, const char *mime, const char *text, size_t sz)
|
||||||
{
|
{
|
||||||
if (window->callbacks.drop)
|
if (window->callbacks.drop)
|
||||||
window->callbacks.drop((GLFWwindow*) window, count, paths);
|
return window->callbacks.drop((GLFWwindow*) window, mime, text, sz);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifies shared code of a joystick connection or disconnection
|
// Notifies shared code of a joystick connection or disconnection
|
||||||
@@ -409,7 +424,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
|
|||||||
js->present = true;
|
js->present = true;
|
||||||
js->name = _glfw_strdup(name);
|
js->name = _glfw_strdup(name);
|
||||||
js->axes = calloc(axisCount, sizeof(float));
|
js->axes = calloc(axisCount, sizeof(float));
|
||||||
js->buttons = calloc(buttonCount + hatCount * 4, 1);
|
js->buttons = calloc(buttonCount + (size_t) hatCount * 4, 1);
|
||||||
js->hats = calloc(hatCount, 1);
|
js->hats = calloc(hatCount, 1);
|
||||||
js->axisCount = axisCount;
|
js->axisCount = axisCount;
|
||||||
js->buttonCount = buttonCount;
|
js->buttonCount = buttonCount;
|
||||||
@@ -437,144 +452,208 @@ const char* _glfwGetKeyName(int key)
|
|||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
// Printable keys
|
// Printable keys
|
||||||
case GLFW_KEY_A: return "A";
|
case GLFW_KEY_SPACE: return "SPACE";
|
||||||
case GLFW_KEY_B: return "B";
|
case GLFW_KEY_EXCLAM: return "EXCLAM";
|
||||||
case GLFW_KEY_C: return "C";
|
case GLFW_KEY_DOUBLE_QUOTE: return "DOUBLE_QUOTE";
|
||||||
case GLFW_KEY_D: return "D";
|
case GLFW_KEY_NUMBER_SIGN: return "NUMBER_SIGN";
|
||||||
case GLFW_KEY_E: return "E";
|
case GLFW_KEY_DOLLAR: return "DOLLAR";
|
||||||
case GLFW_KEY_F: return "F";
|
case GLFW_KEY_AMPERSAND: return "AMPERSAND";
|
||||||
case GLFW_KEY_G: return "G";
|
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
|
||||||
case GLFW_KEY_H: return "H";
|
case GLFW_KEY_PARENTHESIS_LEFT: return "PARENTHESIS_LEFT";
|
||||||
case GLFW_KEY_I: return "I";
|
case GLFW_KEY_PARENTHESIS_RIGHT: return "PARENTHESIS_RIGHT";
|
||||||
case GLFW_KEY_J: return "J";
|
case GLFW_KEY_PLUS: return "PLUS";
|
||||||
case GLFW_KEY_K: return "K";
|
case GLFW_KEY_COMMA: return "COMMA";
|
||||||
case GLFW_KEY_L: return "L";
|
case GLFW_KEY_MINUS: return "MINUS";
|
||||||
case GLFW_KEY_M: return "M";
|
case GLFW_KEY_PERIOD: return "PERIOD";
|
||||||
case GLFW_KEY_N: return "N";
|
case GLFW_KEY_SLASH: return "SLASH";
|
||||||
case GLFW_KEY_O: return "O";
|
case GLFW_KEY_0: return "0";
|
||||||
case GLFW_KEY_P: return "P";
|
case GLFW_KEY_1: return "1";
|
||||||
case GLFW_KEY_Q: return "Q";
|
case GLFW_KEY_2: return "2";
|
||||||
case GLFW_KEY_R: return "R";
|
case GLFW_KEY_3: return "3";
|
||||||
case GLFW_KEY_S: return "S";
|
case GLFW_KEY_4: return "4";
|
||||||
case GLFW_KEY_T: return "T";
|
case GLFW_KEY_5: return "5";
|
||||||
case GLFW_KEY_U: return "U";
|
case GLFW_KEY_6: return "6";
|
||||||
case GLFW_KEY_V: return "V";
|
case GLFW_KEY_7: return "7";
|
||||||
case GLFW_KEY_W: return "W";
|
case GLFW_KEY_8: return "8";
|
||||||
case GLFW_KEY_X: return "X";
|
case GLFW_KEY_9: return "9";
|
||||||
case GLFW_KEY_Y: return "Y";
|
case GLFW_KEY_COLON: return "COLON";
|
||||||
case GLFW_KEY_Z: return "Z";
|
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
|
||||||
case GLFW_KEY_1: return "1";
|
case GLFW_KEY_LESS: return "LESS";
|
||||||
case GLFW_KEY_2: return "2";
|
case GLFW_KEY_EQUAL: return "EQUAL";
|
||||||
case GLFW_KEY_3: return "3";
|
case GLFW_KEY_GREATER: return "GREATER";
|
||||||
case GLFW_KEY_4: return "4";
|
case GLFW_KEY_AT: return "AT";
|
||||||
case GLFW_KEY_5: return "5";
|
case GLFW_KEY_A: return "A";
|
||||||
case GLFW_KEY_6: return "6";
|
case GLFW_KEY_B: return "B";
|
||||||
case GLFW_KEY_7: return "7";
|
case GLFW_KEY_C: return "C";
|
||||||
case GLFW_KEY_8: return "8";
|
case GLFW_KEY_D: return "D";
|
||||||
case GLFW_KEY_9: return "9";
|
case GLFW_KEY_E: return "E";
|
||||||
case GLFW_KEY_0: return "0";
|
case GLFW_KEY_F: return "F";
|
||||||
case GLFW_KEY_SPACE: return "SPACE";
|
case GLFW_KEY_G: return "G";
|
||||||
case GLFW_KEY_MINUS: return "MINUS";
|
case GLFW_KEY_H: return "H";
|
||||||
case GLFW_KEY_EQUAL: return "EQUAL";
|
case GLFW_KEY_I: return "I";
|
||||||
case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET";
|
case GLFW_KEY_J: return "J";
|
||||||
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET";
|
case GLFW_KEY_K: return "K";
|
||||||
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
|
case GLFW_KEY_L: return "L";
|
||||||
case GLFW_KEY_SEMICOLON: return "SEMICOLON";
|
case GLFW_KEY_M: return "M";
|
||||||
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
|
case GLFW_KEY_N: return "N";
|
||||||
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT";
|
case GLFW_KEY_O: return "O";
|
||||||
case GLFW_KEY_COMMA: return "COMMA";
|
case GLFW_KEY_P: return "P";
|
||||||
case GLFW_KEY_PERIOD: return "PERIOD";
|
case GLFW_KEY_Q: return "Q";
|
||||||
case GLFW_KEY_SLASH: return "SLASH";
|
case GLFW_KEY_R: return "R";
|
||||||
case GLFW_KEY_WORLD_1: return "WORLD 1";
|
case GLFW_KEY_S: return "S";
|
||||||
case GLFW_KEY_WORLD_2: return "WORLD 2";
|
case GLFW_KEY_T: return "T";
|
||||||
case GLFW_KEY_PLUS: return "PLUS";
|
case GLFW_KEY_U: return "U";
|
||||||
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
|
case GLFW_KEY_V: return "V";
|
||||||
|
case GLFW_KEY_W: return "W";
|
||||||
|
case GLFW_KEY_X: return "X";
|
||||||
|
case GLFW_KEY_Y: return "Y";
|
||||||
|
case GLFW_KEY_Z: return "Z";
|
||||||
|
case GLFW_KEY_LEFT_BRACKET: return "LEFT_BRACKET";
|
||||||
|
case GLFW_KEY_BACKSLASH: return "BACKSLASH";
|
||||||
|
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT_BRACKET";
|
||||||
|
case GLFW_KEY_CIRCUMFLEX: return "CIRCUMFLEX";
|
||||||
|
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE";
|
||||||
|
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE_ACCENT";
|
||||||
|
case GLFW_KEY_WORLD_1: return "WORLD_1";
|
||||||
|
case GLFW_KEY_WORLD_2: return "WORLD_2";
|
||||||
|
case GLFW_KEY_PARAGRAPH: return "PARAGRAPH";
|
||||||
|
case GLFW_KEY_MASCULINE: return "MASCULINE";
|
||||||
|
case GLFW_KEY_A_GRAVE: return "A_GRAVE";
|
||||||
|
case GLFW_KEY_A_DIAERESIS: return "A_DIAERESIS";
|
||||||
|
case GLFW_KEY_A_RING: return "A_RING";
|
||||||
|
case GLFW_KEY_AE: return "AE";
|
||||||
|
case GLFW_KEY_C_CEDILLA: return "C_CEDILLA";
|
||||||
|
case GLFW_KEY_E_GRAVE: return "E_GRAVE";
|
||||||
|
case GLFW_KEY_E_ACUTE: return "E_ACUTE";
|
||||||
|
case GLFW_KEY_I_GRAVE: return "I_GRAVE";
|
||||||
|
case GLFW_KEY_N_TILDE: return "N_TILDE";
|
||||||
|
case GLFW_KEY_O_GRAVE: return "O_GRAVE";
|
||||||
|
case GLFW_KEY_O_DIAERESIS: return "O_DIAERESIS";
|
||||||
|
case GLFW_KEY_O_SLASH: return "O_SLASH";
|
||||||
|
case GLFW_KEY_U_GRAVE: return "U_GRAVE";
|
||||||
|
case GLFW_KEY_U_DIAERESIS: return "U_DIAERESIS";
|
||||||
|
case GLFW_KEY_S_SHARP: return "S_SHARP";
|
||||||
|
case GLFW_KEY_CYRILLIC_A: return "CYRILLIC_A";
|
||||||
|
case GLFW_KEY_CYRILLIC_BE: return "CYRILLIC_BE";
|
||||||
|
case GLFW_KEY_CYRILLIC_VE: return "CYRILLIC_VE";
|
||||||
|
case GLFW_KEY_CYRILLIC_GHE: return "CYRILLIC_GHE";
|
||||||
|
case GLFW_KEY_CYRILLIC_DE: return "CYRILLIC_DE";
|
||||||
|
case GLFW_KEY_CYRILLIC_IE: return "CYRILLIC_IE";
|
||||||
|
case GLFW_KEY_CYRILLIC_ZHE: return "CYRILLIC_ZHE";
|
||||||
|
case GLFW_KEY_CYRILLIC_ZE: return "CYRILLIC_ZE";
|
||||||
|
case GLFW_KEY_CYRILLIC_I: return "CYRILLIC_I";
|
||||||
|
case GLFW_KEY_CYRILLIC_SHORT_I: return "CYRILLIC_SHORT_I";
|
||||||
|
case GLFW_KEY_CYRILLIC_KA: return "CYRILLIC_KA";
|
||||||
|
case GLFW_KEY_CYRILLIC_EL: return "CYRILLIC_EL";
|
||||||
|
case GLFW_KEY_CYRILLIC_EM: return "CYRILLIC_EM";
|
||||||
|
case GLFW_KEY_CYRILLIC_EN: return "CYRILLIC_EN";
|
||||||
|
case GLFW_KEY_CYRILLIC_O: return "CYRILLIC_O";
|
||||||
|
case GLFW_KEY_CYRILLIC_PE: return "CYRILLIC_PE";
|
||||||
|
case GLFW_KEY_CYRILLIC_ER: return "CYRILLIC_ER";
|
||||||
|
case GLFW_KEY_CYRILLIC_ES: return "CYRILLIC_ES";
|
||||||
|
case GLFW_KEY_CYRILLIC_TE: return "CYRILLIC_TE";
|
||||||
|
case GLFW_KEY_CYRILLIC_U: return "CYRILLIC_U";
|
||||||
|
case GLFW_KEY_CYRILLIC_EF: return "CYRILLIC_EF";
|
||||||
|
case GLFW_KEY_CYRILLIC_HA: return "CYRILLIC_HA";
|
||||||
|
case GLFW_KEY_CYRILLIC_TSE: return "CYRILLIC_TSE";
|
||||||
|
case GLFW_KEY_CYRILLIC_CHE: return "CYRILLIC_CHE";
|
||||||
|
case GLFW_KEY_CYRILLIC_SHA: return "CYRILLIC_SHA";
|
||||||
|
case GLFW_KEY_CYRILLIC_SHCHA: return "CYRILLIC_SHCHA";
|
||||||
|
case GLFW_KEY_CYRILLIC_HARD_SIGN: return "CYRILLIC_HARD_SIGN";
|
||||||
|
case GLFW_KEY_CYRILLIC_YERU: return "CYRILLIC_YERU";
|
||||||
|
case GLFW_KEY_CYRILLIC_SOFT_SIGN: return "CYRILLIC_SOFT_SIGN";
|
||||||
|
case GLFW_KEY_CYRILLIC_E: return "CYRILLIC_E";
|
||||||
|
case GLFW_KEY_CYRILLIC_YU: return "CYRILLIC_YU";
|
||||||
|
case GLFW_KEY_CYRILLIC_YA: return "CYRILLIC_YA";
|
||||||
|
case GLFW_KEY_CYRILLIC_IO: return "CYRILLIC_IO";
|
||||||
|
|
||||||
// Function keys
|
// Function keys
|
||||||
case GLFW_KEY_ESCAPE: return "ESCAPE";
|
case GLFW_KEY_ESCAPE: return "ESCAPE";
|
||||||
case GLFW_KEY_F1: return "F1";
|
case GLFW_KEY_F1: return "F1";
|
||||||
case GLFW_KEY_F2: return "F2";
|
case GLFW_KEY_F2: return "F2";
|
||||||
case GLFW_KEY_F3: return "F3";
|
case GLFW_KEY_F3: return "F3";
|
||||||
case GLFW_KEY_F4: return "F4";
|
case GLFW_KEY_F4: return "F4";
|
||||||
case GLFW_KEY_F5: return "F5";
|
case GLFW_KEY_F5: return "F5";
|
||||||
case GLFW_KEY_F6: return "F6";
|
case GLFW_KEY_F6: return "F6";
|
||||||
case GLFW_KEY_F7: return "F7";
|
case GLFW_KEY_F7: return "F7";
|
||||||
case GLFW_KEY_F8: return "F8";
|
case GLFW_KEY_F8: return "F8";
|
||||||
case GLFW_KEY_F9: return "F9";
|
case GLFW_KEY_F9: return "F9";
|
||||||
case GLFW_KEY_F10: return "F10";
|
case GLFW_KEY_F10: return "F10";
|
||||||
case GLFW_KEY_F11: return "F11";
|
case GLFW_KEY_F11: return "F11";
|
||||||
case GLFW_KEY_F12: return "F12";
|
case GLFW_KEY_F12: return "F12";
|
||||||
case GLFW_KEY_F13: return "F13";
|
case GLFW_KEY_F13: return "F13";
|
||||||
case GLFW_KEY_F14: return "F14";
|
case GLFW_KEY_F14: return "F14";
|
||||||
case GLFW_KEY_F15: return "F15";
|
case GLFW_KEY_F15: return "F15";
|
||||||
case GLFW_KEY_F16: return "F16";
|
case GLFW_KEY_F16: return "F16";
|
||||||
case GLFW_KEY_F17: return "F17";
|
case GLFW_KEY_F17: return "F17";
|
||||||
case GLFW_KEY_F18: return "F18";
|
case GLFW_KEY_F18: return "F18";
|
||||||
case GLFW_KEY_F19: return "F19";
|
case GLFW_KEY_F19: return "F19";
|
||||||
case GLFW_KEY_F20: return "F20";
|
case GLFW_KEY_F20: return "F20";
|
||||||
case GLFW_KEY_F21: return "F21";
|
case GLFW_KEY_F21: return "F21";
|
||||||
case GLFW_KEY_F22: return "F22";
|
case GLFW_KEY_F22: return "F22";
|
||||||
case GLFW_KEY_F23: return "F23";
|
case GLFW_KEY_F23: return "F23";
|
||||||
case GLFW_KEY_F24: return "F24";
|
case GLFW_KEY_F24: return "F24";
|
||||||
case GLFW_KEY_F25: return "F25";
|
case GLFW_KEY_F25: return "F25";
|
||||||
case GLFW_KEY_UP: return "UP";
|
case GLFW_KEY_UP: return "UP";
|
||||||
case GLFW_KEY_DOWN: return "DOWN";
|
case GLFW_KEY_DOWN: return "DOWN";
|
||||||
case GLFW_KEY_LEFT: return "LEFT";
|
case GLFW_KEY_LEFT: return "LEFT";
|
||||||
case GLFW_KEY_RIGHT: return "RIGHT";
|
case GLFW_KEY_RIGHT: return "RIGHT";
|
||||||
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
|
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
|
||||||
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
|
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
|
||||||
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
|
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
|
||||||
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
|
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
|
||||||
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
|
case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
|
||||||
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
|
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
|
||||||
case GLFW_KEY_TAB: return "TAB";
|
case GLFW_KEY_TAB: return "TAB";
|
||||||
case GLFW_KEY_ENTER: return "ENTER";
|
case GLFW_KEY_ENTER: return "ENTER";
|
||||||
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
|
case GLFW_KEY_BACKSPACE: return "BACKSPACE";
|
||||||
case GLFW_KEY_INSERT: return "INSERT";
|
case GLFW_KEY_INSERT: return "INSERT";
|
||||||
case GLFW_KEY_DELETE: return "DELETE";
|
case GLFW_KEY_DELETE: return "DELETE";
|
||||||
case GLFW_KEY_PAGE_UP: return "PAGE UP";
|
case GLFW_KEY_PAGE_UP: return "PAGE UP";
|
||||||
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
|
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
|
||||||
case GLFW_KEY_HOME: return "HOME";
|
case GLFW_KEY_HOME: return "HOME";
|
||||||
case GLFW_KEY_END: return "END";
|
case GLFW_KEY_END: return "END";
|
||||||
case GLFW_KEY_KP_0: return "KEYPAD 0";
|
case GLFW_KEY_KP_0: return "KEYPAD 0";
|
||||||
case GLFW_KEY_KP_1: return "KEYPAD 1";
|
case GLFW_KEY_KP_1: return "KEYPAD 1";
|
||||||
case GLFW_KEY_KP_2: return "KEYPAD 2";
|
case GLFW_KEY_KP_2: return "KEYPAD 2";
|
||||||
case GLFW_KEY_KP_3: return "KEYPAD 3";
|
case GLFW_KEY_KP_3: return "KEYPAD 3";
|
||||||
case GLFW_KEY_KP_4: return "KEYPAD 4";
|
case GLFW_KEY_KP_4: return "KEYPAD 4";
|
||||||
case GLFW_KEY_KP_5: return "KEYPAD 5";
|
case GLFW_KEY_KP_5: return "KEYPAD 5";
|
||||||
case GLFW_KEY_KP_6: return "KEYPAD 6";
|
case GLFW_KEY_KP_6: return "KEYPAD 6";
|
||||||
case GLFW_KEY_KP_7: return "KEYPAD 7";
|
case GLFW_KEY_KP_7: return "KEYPAD 7";
|
||||||
case GLFW_KEY_KP_8: return "KEYPAD 8";
|
case GLFW_KEY_KP_8: return "KEYPAD 8";
|
||||||
case GLFW_KEY_KP_9: return "KEYPAD 9";
|
case GLFW_KEY_KP_9: return "KEYPAD 9";
|
||||||
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
|
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
|
||||||
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTPLY";
|
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTIPLY";
|
||||||
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
|
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
|
||||||
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
|
case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
|
||||||
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
|
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
|
||||||
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
|
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
|
||||||
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
|
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
|
||||||
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
|
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
|
||||||
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
|
case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
|
||||||
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
|
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
|
||||||
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
|
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
|
||||||
case GLFW_KEY_PAUSE: return "PAUSE";
|
case GLFW_KEY_PAUSE: return "PAUSE";
|
||||||
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
|
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
|
||||||
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
|
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
|
||||||
case GLFW_KEY_MENU: return "MENU";
|
case GLFW_KEY_MENU: return "MENU";
|
||||||
|
|
||||||
default: return "UNKNOWN";
|
default: return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Center the cursor in the middle of the content area of the specified window
|
// Center the cursor in the content area of the specified window
|
||||||
//
|
//
|
||||||
void _glfwCenterCursorInContentArea(_GLFWwindow* window)
|
void _glfwCenterCursorInContentArea(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -672,12 +751,14 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
|
|||||||
window->stickyMouseButtons = value;
|
window->stickyMouseButtons = value;
|
||||||
}
|
}
|
||||||
else if (mode == GLFW_LOCK_KEY_MODS)
|
else if (mode == GLFW_LOCK_KEY_MODS)
|
||||||
|
{
|
||||||
window->lockKeyMods = value ? true : false;
|
window->lockKeyMods = value ? true : false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
GLFWAPI const char* glfwGetKeyName(int key, int native_key)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
|
|
||||||
@@ -685,18 +766,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
|
|||||||
{
|
{
|
||||||
if (key != GLFW_KEY_KP_EQUAL &&
|
if (key != GLFW_KEY_KP_EQUAL &&
|
||||||
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
|
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
|
||||||
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
|
(key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_LAST_PRINTABLE))
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
scancode = _glfwPlatformGetKeyScancode(key);
|
native_key = _glfwPlatformGetNativeKeyForKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetScancodeName(scancode);
|
return _glfwPlatformGetNativeKeyName(native_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetKeyScancode(int key)
|
GLFWAPI int glfwGetNativeKeyForKey(int key)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
|
_GLFW_REQUIRE_INIT_OR_RETURN(-1);
|
||||||
|
|
||||||
@@ -706,7 +787,7 @@ GLFWAPI int glfwGetKeyScancode(int key)
|
|||||||
return GLFW_RELEASE;
|
return GLFW_RELEASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _glfwPlatformGetKeyScancode(key);
|
return _glfwPlatformGetNativeKeyForKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
|
||||||
@@ -1359,15 +1440,17 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
|
|||||||
const unsigned int bit = e->index & 0xf;
|
const unsigned int bit = e->index & 0xf;
|
||||||
if (js->hats[hat] & bit)
|
if (js->hats[hat] & bit)
|
||||||
state->axes[i] = 1.f;
|
state->axes[i] = 1.f;
|
||||||
|
else
|
||||||
|
state->axes[i] = -1.f;
|
||||||
}
|
}
|
||||||
else if (e->type == _GLFW_JOYSTICK_BUTTON)
|
else if (e->type == _GLFW_JOYSTICK_BUTTON)
|
||||||
state->axes[i] = (float) js->buttons[e->index];
|
state->axes[i] = js->buttons[e->index] * 2.f - 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle UNUSED, const char* string)
|
||||||
{
|
{
|
||||||
assert(string != NULL);
|
assert(string != NULL);
|
||||||
|
|
||||||
@@ -1375,14 +1458,14 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
|
|||||||
_glfwPlatformSetClipboardString(string);
|
_glfwPlatformSetClipboardString(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
|
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle UNUSED)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return _glfwPlatformGetClipboardString();
|
return _glfwPlatformGetClipboardString();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
|
||||||
GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle, const char* string)
|
GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle UNUSED, const char* string)
|
||||||
{
|
{
|
||||||
assert(string != NULL);
|
assert(string != NULL);
|
||||||
|
|
||||||
@@ -1390,42 +1473,15 @@ GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle, const char* strin
|
|||||||
_glfwPlatformSetPrimarySelectionString(string);
|
_glfwPlatformSetPrimarySelectionString(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle)
|
GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle UNUSED)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return _glfwPlatformGetPrimarySelectionString();
|
return _glfwPlatformGetPrimarySelectionString();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLFWAPI double glfwGetTime(void)
|
GLFWAPI monotonic_t glfwGetTime(void)
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.0);
|
|
||||||
return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
|
|
||||||
_glfwPlatformGetTimerFrequency();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwSetTime(double time)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT();
|
|
||||||
|
|
||||||
if (time != time || time < 0.0 || time > 18446744073.0)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.timer.offset = _glfwPlatformGetTimerValue() -
|
|
||||||
(uint64_t) (time * _glfwPlatformGetTimerFrequency());
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI uint64_t glfwGetTimerValue(void)
|
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
||||||
return _glfwPlatformGetTimerValue();
|
return monotonic();
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI uint64_t glfwGetTimerFrequency(void)
|
|
||||||
{
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0);
|
|
||||||
return _glfwPlatformGetTimerFrequency();
|
|
||||||
}
|
}
|
||||||
|
|||||||
155
glfw/internal.h
vendored
155
glfw/internal.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#if defined(_GLFW_USE_CONFIG_H)
|
#if defined(_GLFW_USE_CONFIG_H)
|
||||||
#include "glfw_config.h"
|
#include "glfw_config.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -130,6 +132,7 @@ typedef enum VkStructureType
|
|||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
||||||
|
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
|
||||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkStructureType;
|
} VkStructureType;
|
||||||
|
|
||||||
@@ -225,12 +228,32 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
|
|||||||
|
|
||||||
// Swaps the provided pointers
|
// Swaps the provided pointers
|
||||||
#define _GLFW_SWAP_POINTERS(x, y) \
|
#define _GLFW_SWAP_POINTERS(x, y) \
|
||||||
{ \
|
do{ \
|
||||||
void* t; \
|
__typeof__(x) t; \
|
||||||
t = x; \
|
t = x; \
|
||||||
x = y; \
|
x = y; \
|
||||||
y = t; \
|
y = t; \
|
||||||
}
|
}while(0)
|
||||||
|
|
||||||
|
|
||||||
|
// Suppress some pedantic warnings
|
||||||
|
#ifdef __clang__
|
||||||
|
#define START_ALLOW_CASE_RANGE _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wpedantic\"")
|
||||||
|
#define END_ALLOW_CASE_RANGE _Pragma("clang diagnostic pop")
|
||||||
|
#define ALLOW_UNUSED_RESULT _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-result\"")
|
||||||
|
#define END_ALLOW_UNUSED_RESULT _Pragma("clang diagnostic pop")
|
||||||
|
#else
|
||||||
|
#define START_ALLOW_CASE_RANGE _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
|
||||||
|
#define END_ALLOW_CASE_RANGE _Pragma("GCC diagnostic pop")
|
||||||
|
#define ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic ignored \"-Wunused-result\"")
|
||||||
|
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// dlsym that works with -Wpedantic
|
||||||
|
#define glfw_dlsym(dest, handle, name) do {*(void **)&(dest) = _glfw_dlsym(handle, name);}while (0)
|
||||||
|
|
||||||
|
// Mark function arguments as unused
|
||||||
|
#define UNUSED __attribute__ ((unused))
|
||||||
|
|
||||||
// Per-thread error structure
|
// Per-thread error structure
|
||||||
//
|
//
|
||||||
@@ -247,12 +270,12 @@ struct _GLFWerror
|
|||||||
//
|
//
|
||||||
struct _GLFWinitconfig
|
struct _GLFWinitconfig
|
||||||
{
|
{
|
||||||
bool hatButtons;
|
bool hatButtons;
|
||||||
bool debugKeyboard;
|
bool debugKeyboard;
|
||||||
bool enableJoysticks;
|
bool enableJoysticks;
|
||||||
struct {
|
struct {
|
||||||
bool menubar;
|
bool menubar;
|
||||||
bool chdir;
|
bool chdir;
|
||||||
} ns;
|
} ns;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -267,18 +290,18 @@ struct _GLFWwndconfig
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
const char* title;
|
const char* title;
|
||||||
bool resizable;
|
bool resizable;
|
||||||
bool visible;
|
bool visible;
|
||||||
bool decorated;
|
bool decorated;
|
||||||
bool focused;
|
bool focused;
|
||||||
bool autoIconify;
|
bool autoIconify;
|
||||||
bool floating;
|
bool floating;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool centerCursor;
|
bool centerCursor;
|
||||||
bool focusOnShow;
|
bool focusOnShow;
|
||||||
bool scaleToMonitor;
|
bool scaleToMonitor;
|
||||||
struct {
|
struct {
|
||||||
bool retina;
|
bool retina;
|
||||||
char frameName[256];
|
char frameName[256];
|
||||||
} ns;
|
} ns;
|
||||||
struct {
|
struct {
|
||||||
@@ -302,15 +325,15 @@ struct _GLFWctxconfig
|
|||||||
int source;
|
int source;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
bool forward;
|
bool forward;
|
||||||
bool debug;
|
bool debug;
|
||||||
bool noerror;
|
bool noerror;
|
||||||
int profile;
|
int profile;
|
||||||
int robustness;
|
int robustness;
|
||||||
int release;
|
int release;
|
||||||
_GLFWwindow* share;
|
_GLFWwindow* share;
|
||||||
struct {
|
struct {
|
||||||
bool offline;
|
bool offline;
|
||||||
} nsgl;
|
} nsgl;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -335,11 +358,11 @@ struct _GLFWfbconfig
|
|||||||
int accumBlueBits;
|
int accumBlueBits;
|
||||||
int accumAlphaBits;
|
int accumAlphaBits;
|
||||||
int auxBuffers;
|
int auxBuffers;
|
||||||
bool stereo;
|
bool stereo;
|
||||||
int samples;
|
int samples;
|
||||||
bool sRGB;
|
bool sRGB;
|
||||||
bool doublebuffer;
|
bool doublebuffer;
|
||||||
bool transparent;
|
bool transparent;
|
||||||
uintptr_t handle;
|
uintptr_t handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -350,7 +373,7 @@ struct _GLFWcontext
|
|||||||
int client;
|
int client;
|
||||||
int source;
|
int source;
|
||||||
int major, minor, revision;
|
int major, minor, revision;
|
||||||
bool forward, debug, noerror;
|
bool forward, debug, noerror;
|
||||||
int profile;
|
int profile;
|
||||||
int robustness;
|
int robustness;
|
||||||
int release;
|
int release;
|
||||||
@@ -367,7 +390,7 @@ struct _GLFWcontext
|
|||||||
_GLFWdestroycontextfun destroy;
|
_GLFWdestroycontextfun destroy;
|
||||||
|
|
||||||
// This is defined in the context API's context.h
|
// This is defined in the context API's context.h
|
||||||
_GLFW_PLATFORM_CONTEXT_STATE;
|
_GLFW_PLATFORM_CONTEXT_STATE
|
||||||
// This is defined in egl_context.h
|
// This is defined in egl_context.h
|
||||||
_GLFW_EGL_CONTEXT_STATE;
|
_GLFW_EGL_CONTEXT_STATE;
|
||||||
// This is defined in osmesa_context.h
|
// This is defined in osmesa_context.h
|
||||||
@@ -381,12 +404,12 @@ struct _GLFWwindow
|
|||||||
struct _GLFWwindow* next;
|
struct _GLFWwindow* next;
|
||||||
|
|
||||||
// Window settings and state
|
// Window settings and state
|
||||||
bool resizable;
|
bool resizable;
|
||||||
bool decorated;
|
bool decorated;
|
||||||
bool autoIconify;
|
bool autoIconify;
|
||||||
bool floating;
|
bool floating;
|
||||||
bool focusOnShow;
|
bool focusOnShow;
|
||||||
bool shouldClose;
|
bool shouldClose;
|
||||||
void* userPointer;
|
void* userPointer;
|
||||||
GLFWid id;
|
GLFWid id;
|
||||||
GLFWvidmode videoMode;
|
GLFWvidmode videoMode;
|
||||||
@@ -396,10 +419,11 @@ struct _GLFWwindow
|
|||||||
int minwidth, minheight;
|
int minwidth, minheight;
|
||||||
int maxwidth, maxheight;
|
int maxwidth, maxheight;
|
||||||
int numer, denom;
|
int numer, denom;
|
||||||
|
int widthincr, heightincr;
|
||||||
|
|
||||||
bool stickyKeys;
|
bool stickyKeys;
|
||||||
bool stickyMouseButtons;
|
bool stickyMouseButtons;
|
||||||
bool lockKeyMods;
|
bool lockKeyMods;
|
||||||
int cursorMode;
|
int cursorMode;
|
||||||
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
|
||||||
char keys[GLFW_KEY_LAST + 1];
|
char keys[GLFW_KEY_LAST + 1];
|
||||||
@@ -490,7 +514,7 @@ struct _GLFWmapping
|
|||||||
//
|
//
|
||||||
struct _GLFWjoystick
|
struct _GLFWjoystick
|
||||||
{
|
{
|
||||||
bool present;
|
bool present;
|
||||||
float* axes;
|
float* axes;
|
||||||
int axisCount;
|
int axisCount;
|
||||||
unsigned char* buttons;
|
unsigned char* buttons;
|
||||||
@@ -526,7 +550,7 @@ struct _GLFWmutex
|
|||||||
//
|
//
|
||||||
struct _GLFWlibrary
|
struct _GLFWlibrary
|
||||||
{
|
{
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
_GLFWinitconfig init;
|
_GLFWinitconfig init;
|
||||||
@@ -553,29 +577,24 @@ struct _GLFWlibrary
|
|||||||
_GLFWmutex errorLock;
|
_GLFWmutex errorLock;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint64_t offset;
|
bool available;
|
||||||
// This is defined in the platform's time.h
|
|
||||||
_GLFW_PLATFORM_LIBRARY_TIMER_STATE;
|
|
||||||
} timer;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
bool available;
|
|
||||||
void* handle;
|
void* handle;
|
||||||
char* extensions[2];
|
char* extensions[2];
|
||||||
#if !defined(_GLFW_VULKAN_STATIC)
|
#if !defined(_GLFW_VULKAN_STATIC)
|
||||||
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
|
||||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
|
||||||
#endif
|
#endif
|
||||||
bool KHR_surface;
|
bool KHR_surface;
|
||||||
#if defined(_GLFW_WIN32)
|
#if defined(_GLFW_WIN32)
|
||||||
bool KHR_win32_surface;
|
bool KHR_win32_surface;
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
bool MVK_macos_surface;
|
bool MVK_macos_surface;
|
||||||
|
bool EXT_metal_surface;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
bool KHR_xlib_surface;
|
bool KHR_xlib_surface;
|
||||||
bool KHR_xcb_surface;
|
bool KHR_xcb_surface;
|
||||||
#elif defined(_GLFW_WAYLAND)
|
#elif defined(_GLFW_WAYLAND)
|
||||||
bool KHR_wayland_surface;
|
bool KHR_wayland_surface;
|
||||||
#endif
|
#endif
|
||||||
} vk;
|
} vk;
|
||||||
|
|
||||||
@@ -587,9 +606,9 @@ struct _GLFWlibrary
|
|||||||
// This is defined in the window API's platform.h
|
// This is defined in the window API's platform.h
|
||||||
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
|
||||||
// This is defined in the context API's context.h
|
// This is defined in the context API's context.h
|
||||||
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
|
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
|
||||||
// This is defined in the platform's joystick.h
|
// This is defined in the platform's joystick.h
|
||||||
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
|
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
|
||||||
// This is defined in egl_context.h
|
// This is defined in egl_context.h
|
||||||
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
_GLFW_EGL_LIBRARY_CONTEXT_STATE;
|
||||||
// This is defined in osmesa_context.h
|
// This is defined in osmesa_context.h
|
||||||
@@ -618,8 +637,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape
|
|||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
|
||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode);
|
const char* _glfwPlatformGetNativeKeyName(int native_key);
|
||||||
int _glfwPlatformGetKeyScancode(int key);
|
int _glfwPlatformGetNativeKeyForKey(int key);
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
|
||||||
@@ -641,9 +660,6 @@ const char* _glfwPlatformGetPrimarySelectionString(void);
|
|||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
void _glfwPlatformUpdateGamepadGUID(char* guid);
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void);
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void);
|
|
||||||
|
|
||||||
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
int _glfwPlatformCreateWindow(_GLFWwindow* window,
|
||||||
const _GLFWwndconfig* wndconfig,
|
const _GLFWwndconfig* wndconfig,
|
||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
@@ -660,6 +676,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
int minwidth, int minheight,
|
int minwidth, int minheight,
|
||||||
int maxwidth, int maxheight);
|
int maxwidth, int maxheight);
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
|
||||||
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window, int widthincr, int heightincr);
|
||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
|
||||||
void _glfwInputLiveResize(_GLFWwindow* window, bool started);
|
void _glfwInputLiveResize(_GLFWwindow* window, bool started);
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
||||||
@@ -667,7 +684,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
int* right, int* bottom);
|
int* right, int* bottom);
|
||||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
||||||
float* xscale, float* yscale);
|
float* xscale, float* yscale);
|
||||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
|
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window);
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
||||||
@@ -696,7 +713,7 @@ void _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c,
|
|||||||
|
|
||||||
void _glfwPlatformPollEvents(void);
|
void _glfwPlatformPollEvents(void);
|
||||||
void _glfwPlatformWaitEvents(void);
|
void _glfwPlatformWaitEvents(void);
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout);
|
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout);
|
||||||
void _glfwPlatformPostEmptyEvent(void);
|
void _glfwPlatformPostEmptyEvent(void);
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
|
||||||
@@ -736,12 +753,13 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
|
|||||||
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
|
||||||
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
|
||||||
|
|
||||||
void _glfwInputKeyboard(_GLFWwindow* window, int key, int scancode, int action, int mods, const char* text, int state);
|
void _glfwInitializeKeyEvent(GLFWkeyevent *ev, int key, int native_key, int action, int mods);
|
||||||
|
void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev);
|
||||||
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
|
void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags);
|
||||||
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
|
||||||
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
|
||||||
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
void _glfwInputCursorEnter(_GLFWwindow* window, bool entered);
|
||||||
void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
|
int _glfwInputDrop(_GLFWwindow* window, const char *mime, const char *text, size_t sz);
|
||||||
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
void _glfwInputJoystick(_GLFWjoystick* js, int event);
|
||||||
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
|
||||||
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
|
||||||
@@ -802,10 +820,9 @@ const char* _glfwGetVulkanResultString(VkResult result);
|
|||||||
_GLFWwindow* _glfwFocusedWindow(void);
|
_GLFWwindow* _glfwFocusedWindow(void);
|
||||||
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
|
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
|
||||||
void _glfwPlatformRequestTickCallback(void);
|
|
||||||
void _glfwPlatformStopMainLoop(void);
|
void _glfwPlatformStopMainLoop(void);
|
||||||
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
|
unsigned long long _glfwPlatformAddTimer(monotonic_t interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
|
||||||
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled);
|
||||||
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
|
void _glfwPlatformRemoveTimer(unsigned long long timer_id);
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source);
|
char* _glfw_strdup(const char* source);
|
||||||
|
|||||||
72
glfw/linux_joystick.c
vendored
72
glfw/linux_joystick.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Linux - www.glfw.org
|
// GLFW 3.4 Linux - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -104,9 +106,7 @@ static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
|
|||||||
//
|
//
|
||||||
static void pollAbsState(_GLFWjoystick* js)
|
static void pollAbsState(_GLFWjoystick* js)
|
||||||
{
|
{
|
||||||
int code;
|
for (int code = 0; code < ABS_CNT; code++)
|
||||||
|
|
||||||
for (code = 0; code < ABS_CNT; code++)
|
|
||||||
{
|
{
|
||||||
if (js->linjs.absMap[code] < 0)
|
if (js->linjs.absMap[code] < 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -126,18 +126,7 @@ static void pollAbsState(_GLFWjoystick* js)
|
|||||||
//
|
//
|
||||||
static bool openJoystickDevice(const char* path)
|
static bool openJoystickDevice(const char* path)
|
||||||
{
|
{
|
||||||
int jid, code;
|
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
char name[256] = "";
|
|
||||||
char guid[33] = "";
|
|
||||||
char evBits[(EV_CNT + 7) / 8] = {0};
|
|
||||||
char keyBits[(KEY_CNT + 7) / 8] = {0};
|
|
||||||
char absBits[(ABS_CNT + 7) / 8] = {0};
|
|
||||||
int axisCount = 0, buttonCount = 0, hatCount = 0;
|
|
||||||
struct input_id id;
|
|
||||||
_GLFWjoystickLinux linjs = {0};
|
|
||||||
_GLFWjoystick* js = NULL;
|
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
{
|
||||||
if (!_glfw.joysticks[jid].present)
|
if (!_glfw.joysticks[jid].present)
|
||||||
continue;
|
continue;
|
||||||
@@ -145,14 +134,20 @@ static bool openJoystickDevice(const char* path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_GLFWjoystickLinux linjs = {0};
|
||||||
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
|
||||||
if (linjs.fd == -1)
|
if (linjs.fd == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
char evBits[(EV_CNT + 7) / 8] = {0};
|
||||||
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
char keyBits[(KEY_CNT + 7) / 8] = {0};
|
||||||
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
|
char absBits[(ABS_CNT + 7) / 8] = {0};
|
||||||
ioctl(linjs.fd, EVIOCGID, &id) < 0)
|
struct input_id id;
|
||||||
|
|
||||||
|
if (ioctl(linjs.fd, (int32_t)EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, (int32_t)EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, (int32_t)EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
|
||||||
|
ioctl(linjs.fd, (int32_t)EVIOCGID, &id) < 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Linux: Failed to query input device: %s",
|
"Linux: Failed to query input device: %s",
|
||||||
@@ -168,9 +163,13 @@ static bool openJoystickDevice(const char* path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
char name[256] = "";
|
||||||
|
|
||||||
|
if (ioctl(linjs.fd, (int32_t)EVIOCGNAME(sizeof(name)), name) < 0)
|
||||||
strncpy(name, "Unknown", sizeof(name));
|
strncpy(name, "Unknown", sizeof(name));
|
||||||
|
|
||||||
|
char guid[33] = "";
|
||||||
|
|
||||||
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
// Generate a joystick GUID that matches the SDL 2.0.5+ one
|
||||||
if (id.vendor && id.product && id.version)
|
if (id.vendor && id.product && id.version)
|
||||||
{
|
{
|
||||||
@@ -189,7 +188,9 @@ static bool openJoystickDevice(const char* path)
|
|||||||
name[8], name[9], name[10]);
|
name[8], name[9], name[10]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (code = BTN_MISC; code < KEY_CNT; code++)
|
int axisCount = 0, buttonCount = 0, hatCount = 0;
|
||||||
|
|
||||||
|
for (int code = BTN_MISC; code < KEY_CNT; code++)
|
||||||
{
|
{
|
||||||
if (!isBitSet(code, keyBits))
|
if (!isBitSet(code, keyBits))
|
||||||
continue;
|
continue;
|
||||||
@@ -198,7 +199,7 @@ static bool openJoystickDevice(const char* path)
|
|||||||
buttonCount++;
|
buttonCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (code = 0; code < ABS_CNT; code++)
|
for (int code = 0; code < ABS_CNT; code++)
|
||||||
{
|
{
|
||||||
linjs.absMap[code] = -1;
|
linjs.absMap[code] = -1;
|
||||||
if (!isBitSet(code, absBits))
|
if (!isBitSet(code, absBits))
|
||||||
@@ -221,7 +222,8 @@ static bool openJoystickDevice(const char* path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
|
_GLFWjoystick* js =
|
||||||
|
_glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
|
||||||
if (!js)
|
if (!js)
|
||||||
{
|
{
|
||||||
close(linjs.fd);
|
close(linjs.fd);
|
||||||
@@ -266,8 +268,6 @@ static int compareJoysticks(const void* fp, const void* sp)
|
|||||||
//
|
//
|
||||||
bool _glfwInitJoysticksLinux(void)
|
bool _glfwInitJoysticksLinux(void)
|
||||||
{
|
{
|
||||||
DIR* dir;
|
|
||||||
int count = 0;
|
|
||||||
const char* dirname = "/dev/input";
|
const char* dirname = "/dev/input";
|
||||||
|
|
||||||
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
@@ -289,7 +289,9 @@ bool _glfwInitJoysticksLinux(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = opendir(dirname);
|
int count = 0;
|
||||||
|
|
||||||
|
DIR* dir = opendir(dirname);
|
||||||
if (dir)
|
if (dir)
|
||||||
{
|
{
|
||||||
struct dirent* entry;
|
struct dirent* entry;
|
||||||
@@ -314,7 +316,7 @@ bool _glfwInitJoysticksLinux(void)
|
|||||||
|
|
||||||
// Continue with no joysticks if enumeration fails
|
// Continue with no joysticks if enumeration fails
|
||||||
|
|
||||||
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
|
qsort(_glfw.joysticks, count, sizeof(_glfw.joysticks[0]), compareJoysticks);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,12 +346,12 @@ void _glfwTerminateJoysticksLinux(void)
|
|||||||
|
|
||||||
void _glfwDetectJoystickConnectionLinux(void)
|
void _glfwDetectJoystickConnectionLinux(void)
|
||||||
{
|
{
|
||||||
ssize_t offset = 0;
|
|
||||||
char buffer[16384];
|
|
||||||
|
|
||||||
if (_glfw.linjs.inotify <= 0)
|
if (_glfw.linjs.inotify <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ssize_t offset = 0;
|
||||||
|
char buffer[16384];
|
||||||
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
|
||||||
|
|
||||||
while (size > offset)
|
while (size > offset)
|
||||||
@@ -369,9 +371,7 @@ void _glfwDetectJoystickConnectionLinux(void)
|
|||||||
openJoystickDevice(path);
|
openJoystickDevice(path);
|
||||||
else if (e->mask & IN_DELETE)
|
else if (e->mask & IN_DELETE)
|
||||||
{
|
{
|
||||||
int jid;
|
for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
||||||
|
|
||||||
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
|
|
||||||
{
|
{
|
||||||
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
|
||||||
{
|
{
|
||||||
@@ -388,7 +388,7 @@ void _glfwDetectJoystickConnectionLinux(void)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode UNUSED)
|
||||||
{
|
{
|
||||||
// Read all queued events (non-blocking)
|
// Read all queued events (non-blocking)
|
||||||
for (;;)
|
for (;;)
|
||||||
@@ -428,6 +428,6 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
|||||||
return js->present;
|
return js->present;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
void _glfwPlatformUpdateGamepadGUID(char* guid UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
7
glfw/linux_joystick.h
vendored
7
glfw/linux_joystick.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Linux - www.glfw.org
|
// GLFW 3.4 Linux - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs;
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
|
#define _GLFW_PLATFORM_MAPPING_NAME "Linux"
|
||||||
|
|
||||||
@@ -52,11 +52,10 @@ typedef struct _GLFWlibraryLinux
|
|||||||
int inotify;
|
int inotify;
|
||||||
int watch;
|
int watch;
|
||||||
regex_t regex;
|
regex_t regex;
|
||||||
bool dropped;
|
bool dropped;
|
||||||
} _GLFWlibraryLinux;
|
} _GLFWlibraryLinux;
|
||||||
|
|
||||||
|
|
||||||
bool _glfwInitJoysticksLinux(void);
|
bool _glfwInitJoysticksLinux(void);
|
||||||
void _glfwTerminateJoysticksLinux(void);
|
void _glfwTerminateJoysticksLinux(void);
|
||||||
void _glfwDetectJoystickConnectionLinux(void);
|
void _glfwDetectJoystickConnectionLinux(void);
|
||||||
|
|
||||||
|
|||||||
3
glfw/linux_notify.c
vendored
3
glfw/linux_notify.c
vendored
@@ -43,8 +43,7 @@ notification_created(DBusMessage *msg, const char* errmsg, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static DBusHandlerResult
|
static DBusHandlerResult
|
||||||
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) {
|
message_handler(DBusConnection *conn UNUSED, DBusMessage *msg, void *user_data UNUSED) {
|
||||||
(void)(user_data);
|
|
||||||
/* printf("session_bus message_handler invoked interface: %s member: %s\n", dbus_message_get_interface(msg), dbus_message_get_member(msg)); */
|
/* 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")) {
|
if (dbus_message_is_signal(msg, NOTIFICATIONS_IFACE, "ActionInvoked")) {
|
||||||
uint32_t notification_id;
|
uint32_t notification_id;
|
||||||
|
|||||||
18
glfw/main_loop.h
vendored
18
glfw/main_loop.h
vendored
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#ifndef GLFW_LOOP_BACKEND
|
#ifndef GLFW_LOOP_BACKEND
|
||||||
#define GLFW_LOOP_BACKEND x11
|
#define GLFW_LOOP_BACKEND x11
|
||||||
@@ -14,8 +15,6 @@
|
|||||||
|
|
||||||
static bool keep_going = false;
|
static bool keep_going = false;
|
||||||
|
|
||||||
void _glfwPlatformRequestTickCallback() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformStopMainLoop(void) {
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
if (keep_going) {
|
if (keep_going) {
|
||||||
@@ -25,15 +24,20 @@ void _glfwPlatformStopMainLoop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
|
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
|
||||||
keep_going = true;
|
keep_going = 1;
|
||||||
|
EventLoopData *eld = &_glfw.GLFW_LOOP_BACKEND.eventLoopData;
|
||||||
while(keep_going) {
|
while(keep_going) {
|
||||||
_glfwPlatformWaitEvents();
|
_glfwPlatformWaitEvents();
|
||||||
EVDBG("loop tick");
|
EVDBG("--------- loop tick, wakeups_happened: %d ----------", eld->wakeup_data_read);
|
||||||
tick_callback(data);
|
if (eld->wakeup_data_read) {
|
||||||
|
eld->wakeup_data_read = false;
|
||||||
|
tick_callback(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
EVDBG("main loop exiting");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback) {
|
unsigned long long _glfwPlatformAddTimer(monotonic_t 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);
|
return addTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, "user timer", interval, 1, repeats, callback, callback_data, free_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +45,7 @@ void _glfwPlatformRemoveTimer(unsigned long long timer_id) {
|
|||||||
removeTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id);
|
removeTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled) {
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled) {
|
||||||
changeTimerInterval(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, interval);
|
changeTimerInterval(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, interval);
|
||||||
toggleTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, enabled);
|
toggleTimer(&_glfw.GLFW_LOOP_BACKEND.eventLoopData, timer_id, enabled);
|
||||||
}
|
}
|
||||||
|
|||||||
4
glfw/mappings.h
vendored
4
glfw/mappings.h
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
|||||||
25
glfw/monitor.c
vendored
25
glfw/monitor.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -54,6 +56,10 @@ static int compareVideoModes(const void* fp, const void* sp)
|
|||||||
if (farea != sarea)
|
if (farea != sarea)
|
||||||
return farea - sarea;
|
return farea - sarea;
|
||||||
|
|
||||||
|
// Then sort on width
|
||||||
|
if (fm->width != sm->width)
|
||||||
|
return fm->width - sm->width;
|
||||||
|
|
||||||
// Lastly sort on refresh rate
|
// Lastly sort on refresh rate
|
||||||
return fm->refreshRate - sm->refreshRate;
|
return fm->refreshRate - sm->refreshRate;
|
||||||
}
|
}
|
||||||
@@ -72,7 +78,7 @@ static bool refreshVideoModes(_GLFWmonitor* monitor)
|
|||||||
if (!modes)
|
if (!modes)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
|
qsort(modes, modeCount, sizeof(modes[0]), compareVideoModes);
|
||||||
|
|
||||||
free(monitor->modes);
|
free(monitor->modes);
|
||||||
monitor->modes = modes;
|
monitor->modes = modes;
|
||||||
@@ -100,7 +106,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
|
|||||||
{
|
{
|
||||||
memmove(_glfw.monitors + 1,
|
memmove(_glfw.monitors + 1,
|
||||||
_glfw.monitors,
|
_glfw.monitors,
|
||||||
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
|
||||||
_glfw.monitors[0] = monitor;
|
_glfw.monitors[0] = monitor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -327,7 +333,9 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
|
|||||||
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
_glfwPlatformGetMonitorPos(monitor, xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, int* width, int* height)
|
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
|
||||||
assert(monitor != NULL);
|
assert(monitor != NULL);
|
||||||
@@ -448,7 +456,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|||||||
GLFWgammaramp ramp;
|
GLFWgammaramp ramp;
|
||||||
const GLFWgammaramp* original;
|
const GLFWgammaramp* original;
|
||||||
assert(handle != NULL);
|
assert(handle != NULL);
|
||||||
assert(gamma >= 0.f);
|
assert(gamma > 0.f);
|
||||||
assert(gamma <= FLT_MAX);
|
assert(gamma <= FLT_MAX);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
@@ -458,6 +466,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|||||||
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
original = glfwGetGammaRamp(handle);
|
original = glfwGetGammaRamp(handle);
|
||||||
if (!original)
|
if (!original)
|
||||||
return;
|
return;
|
||||||
@@ -472,10 +481,8 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
|
|||||||
value = i / (float) (original->size - 1);
|
value = i / (float) (original->size - 1);
|
||||||
// Apply gamma curve
|
// Apply gamma curve
|
||||||
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
|
||||||
|
|
||||||
// Clamp to value range
|
// Clamp to value range
|
||||||
if (value > 65535.f)
|
value = fminf(value, 65535.f);
|
||||||
value = 65535.f;
|
|
||||||
|
|
||||||
values[i] = (unsigned short) value;
|
values[i] = (unsigned short) value;
|
||||||
}
|
}
|
||||||
|
|||||||
10
glfw/monotonic.c
vendored
Normal file
10
glfw/monotonic.c
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* monotonic.c
|
||||||
|
* Copyright (C) 2019 Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the GPL3 license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#define MONOTONIC_IMPLEMENTATION
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
13
glfw/nsgl_context.h
vendored
13
glfw/nsgl_context.h
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.4 macOS - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,16 +24,16 @@
|
|||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
|
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl;
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
|
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl;
|
||||||
|
|
||||||
|
|
||||||
// NSGL-specific per-context data
|
// NSGL-specific per-context data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWcontextNSGL
|
typedef struct _GLFWcontextNSGL
|
||||||
{
|
{
|
||||||
id pixelFormat;
|
id pixelFormat;
|
||||||
id object;
|
id object;
|
||||||
|
|
||||||
} _GLFWcontextNSGL;
|
} _GLFWcontextNSGL;
|
||||||
|
|
||||||
@@ -53,4 +53,3 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
const _GLFWctxconfig* ctxconfig,
|
const _GLFWctxconfig* ctxconfig,
|
||||||
const _GLFWfbconfig* fbconfig);
|
const _GLFWfbconfig* fbconfig);
|
||||||
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
void _glfwDestroyContextNSGL(_GLFWwindow* window);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 macOS - www.glfw.org
|
// GLFW 3.4 macOS - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -43,15 +45,14 @@ static void swapBuffersNSGL(_GLFWwindow* window)
|
|||||||
[window->context.nsgl.object flushBuffer];
|
[window->context.nsgl.object flushBuffer];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapIntervalNSGL(int interval)
|
static void swapIntervalNSGL(int interval UNUSED)
|
||||||
{
|
{
|
||||||
// As of Mojave this does not work so we use CVDisplayLink instead
|
// As of Mojave this does not work so we use CVDisplayLink instead
|
||||||
(void)(interval);
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
_glfwInputError(GLFW_API_UNAVAILABLE,
|
||||||
"NSGL: Swap intervals do not work on macOS");
|
"NSGL: Swap intervals do not work on macOS");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extensionSupportedNSGL(const char* extension)
|
static int extensionSupportedNSGL(const char* extension UNUSED)
|
||||||
{
|
{
|
||||||
// There are no NSGL extensions
|
// There are no NSGL extensions
|
||||||
return false;
|
return false;
|
||||||
@@ -63,8 +64,9 @@ static GLFWglproc getProcAddressNSGL(const char* procname)
|
|||||||
procname,
|
procname,
|
||||||
kCFStringEncodingASCII);
|
kCFStringEncodingASCII);
|
||||||
|
|
||||||
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
|
GLFWglproc symbol;
|
||||||
symbolName);
|
*(void **) &symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
|
||||||
|
symbolName);
|
||||||
|
|
||||||
CFRelease(symbolName);
|
CFRelease(symbolName);
|
||||||
|
|
||||||
@@ -131,7 +133,6 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
|
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
// Context robustness modes (GL_KHR_robustness) are not yet supported by
|
||||||
@@ -270,7 +271,7 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSOpenGLContext* share = NULL;
|
NSOpenGLContext* share = nil;
|
||||||
|
|
||||||
if (ctxconfig->share)
|
if (ctxconfig->share)
|
||||||
share = ctxconfig->share->context.nsgl.object;
|
share = ctxconfig->share->context.nsgl.object;
|
||||||
@@ -288,11 +289,11 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
if (fbconfig->transparent)
|
if (fbconfig->transparent)
|
||||||
{
|
{
|
||||||
GLint opaque = 0;
|
GLint opaque = 0;
|
||||||
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
[window->context.nsgl.object setValues:&opaque
|
||||||
|
forParameter:NSOpenGLContextParameterSurfaceOpacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window->ns.retina)
|
[window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
|
||||||
[window->ns.view setWantsBestResolutionOpenGLSurface:YES];
|
|
||||||
|
|
||||||
GLint interval = 0;
|
GLint interval = 0;
|
||||||
[window->context.nsgl.object setValues:&interval
|
[window->context.nsgl.object setValues:&interval
|
||||||
@@ -323,7 +324,7 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
|
|||||||
if (window->context.client == GLFW_NO_API)
|
if (window->context.client == GLFW_NO_API)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
||||||
return NULL;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window->context.nsgl.object;
|
return window->context.nsgl.object;
|
||||||
|
|||||||
8
glfw/null_init.c
vendored
8
glfw/null_init.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -34,7 +36,6 @@
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
_glfwInitTimerPOSIX();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,4 +48,3 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
{
|
{
|
||||||
return _GLFW_VERSION_NUMBER " null OSMesa";
|
return _GLFW_VERSION_NUMBER " null OSMesa";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
glfw/null_joystick.c
vendored
10
glfw/null_joystick.c
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -31,12 +33,12 @@
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
|
int _glfwPlatformPollJoystick(_GLFWjoystick* js UNUSED, int mode UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUpdateGamepadGUID(char* guid)
|
void _glfwPlatformUpdateGamepadGUID(char* guid UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
glfw/null_joystick.h
vendored
7
glfw/null_joystick.h
vendored
@@ -1,7 +1,7 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -25,7 +25,6 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
|
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
|
||||||
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs
|
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs;
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_MAPPING_NAME ""
|
#define _GLFW_PLATFORM_MAPPING_NAME ""
|
||||||
|
|
||||||
|
|||||||
25
glfw/null_monitor.c
vendored
25
glfw/null_monitor.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -32,15 +34,15 @@
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
|
||||||
float* xscale, float* yscale)
|
float* xscale, float* yscale)
|
||||||
{
|
{
|
||||||
if (xscale)
|
if (xscale)
|
||||||
@@ -49,24 +51,27 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = 1.f;
|
*yscale = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor UNUSED,
|
||||||
|
int* xpos UNUSED, int* ypos UNUSED,
|
||||||
|
int* width UNUSED, int* height UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
|
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor UNUSED, int* found UNUSED)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor UNUSED, GLFWvidmode* mode UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED, const GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
glfw/null_platform.h
vendored
4
glfw/null_platform.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
|||||||
136
glfw/null_window.c
vendored
136
glfw/null_window.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,8 +24,11 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
|
|
||||||
static int createNativeWindow(_GLFWwindow* window,
|
static int createNativeWindow(_GLFWwindow* window,
|
||||||
@@ -76,28 +79,28 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
window->context.destroy(window);
|
window->context.destroy(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
void _glfwPlatformSetWindowTitle(_GLFWwindow* window UNUSED, const char* title UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED, int count UNUSED,
|
||||||
const GLFWimage* images)
|
const GLFWimage* images UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window UNUSED,
|
||||||
_GLFWmonitor* monitor,
|
_GLFWmonitor* monitor UNUSED,
|
||||||
int xpos, int ypos,
|
int xpos UNUSED, int ypos UNUSED,
|
||||||
int width, int height,
|
int width UNUSED, int height UNUSED,
|
||||||
int refreshRate)
|
int refreshRate UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,13 +118,17 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
window->null.height = height;
|
window->null.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window UNUSED,
|
||||||
int minwidth, int minheight,
|
int minwidth UNUSED, int minheight UNUSED,
|
||||||
int maxwidth, int maxheight)
|
int maxwidth UNUSED, int maxheight UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED, int n UNUSED, int d UNUSED)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED, int widthincr UNUSED, int heightincr UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,13 +140,13 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
|
|||||||
*height = window->null.height;
|
*height = window->null.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window UNUSED,
|
||||||
int* left, int* top,
|
int* left UNUSED, int* top UNUSED,
|
||||||
int* right, int* bottom)
|
int* right UNUSED, int* bottom UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
|
||||||
float* xscale, float* yscale)
|
float* xscale, float* yscale)
|
||||||
{
|
{
|
||||||
if (xscale)
|
if (xscale)
|
||||||
@@ -148,101 +155,101 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|||||||
*yscale = 1.f;
|
*yscale = 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return 0.5;
|
return ms_to_monotonic_t(500ll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
void _glfwPlatformRestoreWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
int _glfwPlatformWindowMaximized(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
int _glfwPlatformWindowHovered(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return 1.f;
|
return 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
|
void _glfwPlatformUnhideWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window)
|
void _glfwPlatformHideWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
int _glfwPlatformWindowFocused(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowVisible(_GLFWwindow* window)
|
int _glfwPlatformWindowVisible(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -255,7 +262,7 @@ void _glfwPlatformWaitEvents(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,39 +270,39 @@ void _glfwPlatformPostEmptyEvent(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window UNUSED, double* xpos UNUSED, double* ypos UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
void _glfwPlatformSetCursorPos(_GLFWwindow* window UNUSED, double x UNUSED, double y UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window UNUSED, int mode UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor UNUSED,
|
||||||
const GLFWimage* image,
|
const GLFWimage* image UNUSED,
|
||||||
int xhot, int yhot, int count)
|
int xhot UNUSED, int yhot UNUSED, int count UNUSED)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor UNUSED, int shape UNUSED)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window UNUSED, _GLFWcursor* cursor UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string)
|
void _glfwPlatformSetClipboardString(const char* string UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,32 +311,33 @@ const char* _glfwPlatformGetClipboardString(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
const char* _glfwPlatformGetNativeKeyName(int native_key UNUSED)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetNativeKeyForKey(int key UNUSED)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
|
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
|
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance UNUSED,
|
||||||
VkPhysicalDevice device,
|
VkPhysicalDevice device UNUSED,
|
||||||
uint32_t queuefamily)
|
uint32_t queuefamily UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance UNUSED,
|
||||||
_GLFWwindow* window,
|
_GLFWwindow* window UNUSED,
|
||||||
const VkAllocationCallbacks* allocator,
|
const VkAllocationCallbacks* allocator UNUSED,
|
||||||
VkSurfaceKHR* surface)
|
VkSurfaceKHR* surface UNUSED)
|
||||||
{
|
{
|
||||||
// This seems like the most appropriate error to return here
|
// This seems like the most appropriate error to return here
|
||||||
return VK_ERROR_INITIALIZATION_FAILED;
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
glfw/osmesa_context.c
vendored
37
glfw/osmesa_context.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 OSMesa - www.glfw.org
|
// GLFW 3.4 OSMesa - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -47,7 +49,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
|
|||||||
free(window->context.osmesa.buffer);
|
free(window->context.osmesa.buffer);
|
||||||
|
|
||||||
// Allocate the new buffer (width * height * 8-bit RGBA)
|
// Allocate the new buffer (width * height * 8-bit RGBA)
|
||||||
window->context.osmesa.buffer = calloc(4, width * height);
|
window->context.osmesa.buffer = calloc(4, (size_t) width * height);
|
||||||
window->context.osmesa.width = width;
|
window->context.osmesa.width = width;
|
||||||
window->context.osmesa.height = height;
|
window->context.osmesa.height = height;
|
||||||
}
|
}
|
||||||
@@ -87,17 +89,17 @@ static void destroyContextOSMesa(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapBuffersOSMesa(_GLFWwindow* window)
|
static void swapBuffersOSMesa(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
// No double buffering on OSMesa
|
// No double buffering on OSMesa
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swapIntervalOSMesa(int interval)
|
static void swapIntervalOSMesa(int interval UNUSED)
|
||||||
{
|
{
|
||||||
// No swap interval on OSMesa
|
// No swap interval on OSMesa
|
||||||
}
|
}
|
||||||
|
|
||||||
static int extensionSupportedOSMesa(const char* extension)
|
static int extensionSupportedOSMesa(const char* extension UNUSED)
|
||||||
{
|
{
|
||||||
// OSMesa does not have extensions
|
// OSMesa does not have extensions
|
||||||
return false;
|
return false;
|
||||||
@@ -145,20 +147,13 @@ bool _glfwInitOSMesa(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
|
glfw_dlsym(_glfw.osmesa.CreateContextExt, _glfw.osmesa.handle, "OSMesaCreateContextExt");
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
|
glfw_dlsym(_glfw.osmesa.CreateContextAttribs, _glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
||||||
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
|
glfw_dlsym(_glfw.osmesa.DestroyContext, _glfw.osmesa.handle, "OSMesaDestroyContext");
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
|
glfw_dlsym(_glfw.osmesa.MakeCurrent, _glfw.osmesa.handle, "OSMesaMakeCurrent");
|
||||||
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
|
glfw_dlsym(_glfw.osmesa.GetColorBuffer, _glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
|
glfw_dlsym(_glfw.osmesa.GetDepthBuffer, _glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
||||||
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
|
glfw_dlsym(_glfw.osmesa.GetProcAddress, _glfw.osmesa.handle, "OSMesaGetProcAddress");
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
|
|
||||||
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
|
|
||||||
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
|
|
||||||
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
|
|
||||||
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
|
|
||||||
|
|
||||||
if (!_glfw.osmesa.CreateContextExt ||
|
if (!_glfw.osmesa.CreateContextExt ||
|
||||||
!_glfw.osmesa.DestroyContext ||
|
!_glfw.osmesa.DestroyContext ||
|
||||||
@@ -188,7 +183,7 @@ void _glfwTerminateOSMesa(void)
|
|||||||
|
|
||||||
#define setAttrib(a, v) \
|
#define setAttrib(a, v) \
|
||||||
{ \
|
{ \
|
||||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
||||||
attribs[index++] = a; \
|
attribs[index++] = a; \
|
||||||
attribs[index++] = v; \
|
attribs[index++] = v; \
|
||||||
}
|
}
|
||||||
|
|||||||
4
glfw/osmesa_context.h
vendored
4
glfw/osmesa_context.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 OSMesa - www.glfw.org
|
// GLFW 3.4 OSMesa - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2016 Google Inc.
|
// Copyright (c) 2016 Google Inc.
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
|||||||
6
glfw/posix_thread.c
vendored
6
glfw/posix_thread.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 POSIX - www.glfw.org
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
|||||||
8
glfw/posix_thread.h
vendored
8
glfw/posix_thread.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 POSIX - www.glfw.org
|
// GLFW 3.4 POSIX - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWtlsPOSIX
|
typedef struct _GLFWtlsPOSIX
|
||||||
{
|
{
|
||||||
bool allocated;
|
bool allocated;
|
||||||
pthread_key_t key;
|
pthread_key_t key;
|
||||||
|
|
||||||
} _GLFWtlsPOSIX;
|
} _GLFWtlsPOSIX;
|
||||||
@@ -44,7 +44,7 @@ typedef struct _GLFWtlsPOSIX
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWmutexPOSIX
|
typedef struct _GLFWmutexPOSIX
|
||||||
{
|
{
|
||||||
bool allocated;
|
bool allocated;
|
||||||
pthread_mutex_t handle;
|
pthread_mutex_t handle;
|
||||||
|
|
||||||
} _GLFWmutexPOSIX;
|
} _GLFWmutexPOSIX;
|
||||||
|
|||||||
85
glfw/posix_time.c
vendored
85
glfw/posix_time.c
vendored
@@ -1,85 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 POSIX - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialise timer
|
|
||||||
//
|
|
||||||
void _glfwInitTimerPOSIX(void)
|
|
||||||
{
|
|
||||||
#if defined(CLOCK_MONOTONIC)
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
|
|
||||||
{
|
|
||||||
_glfw.timer.posix.monotonic = true;
|
|
||||||
_glfw.timer.posix.frequency = 1000000000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
_glfw.timer.posix.monotonic = false;
|
|
||||||
_glfw.timer.posix.frequency = 1000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW platform API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerValue(void)
|
|
||||||
{
|
|
||||||
#if defined(CLOCK_MONOTONIC)
|
|
||||||
if (_glfw.timer.posix.monotonic)
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t _glfwPlatformGetTimerFrequency(void)
|
|
||||||
{
|
|
||||||
return _glfw.timer.posix.frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
44
glfw/posix_time.h
vendored
44
glfw/posix_time.h
vendored
@@ -1,44 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 POSIX - www.glfw.org
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
|
||||||
//
|
|
||||||
// This software is provided 'as-is', without any express or implied
|
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
|
||||||
// arising from the use of this software.
|
|
||||||
//
|
|
||||||
// Permission is granted to anyone to use this software for any purpose,
|
|
||||||
// including commercial applications, and to alter it and redistribute it
|
|
||||||
// freely, subject to the following restrictions:
|
|
||||||
//
|
|
||||||
// 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
// claim that you wrote the original software. If you use this software
|
|
||||||
// in a product, an acknowledgment in the product documentation would
|
|
||||||
// be appreciated but is not required.
|
|
||||||
//
|
|
||||||
// 2. Altered source versions must be plainly marked as such, and must not
|
|
||||||
// be misrepresented as being the original software.
|
|
||||||
//
|
|
||||||
// 3. This notice may not be removed or altered from any source
|
|
||||||
// distribution.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE _GLFWtimerPOSIX posix
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
// POSIX-specific global timer data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWtimerPOSIX
|
|
||||||
{
|
|
||||||
bool monotonic;
|
|
||||||
uint64_t frequency;
|
|
||||||
|
|
||||||
} _GLFWtimerPOSIX;
|
|
||||||
|
|
||||||
|
|
||||||
void _glfwInitTimerPOSIX(void);
|
|
||||||
|
|
||||||
@@ -13,7 +13,6 @@
|
|||||||
"cocoa_joystick.m",
|
"cocoa_joystick.m",
|
||||||
"cocoa_monitor.m",
|
"cocoa_monitor.m",
|
||||||
"cocoa_window.m",
|
"cocoa_window.m",
|
||||||
"cocoa_time.c",
|
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"nsgl_context.m",
|
"nsgl_context.m",
|
||||||
"egl_context.c",
|
"egl_context.c",
|
||||||
@@ -31,6 +30,7 @@
|
|||||||
"input.c",
|
"input.c",
|
||||||
"monitor.c",
|
"monitor.c",
|
||||||
"vulkan.c",
|
"vulkan.c",
|
||||||
|
"monotonic.c",
|
||||||
"window.c"
|
"window.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
"headers": [
|
"headers": [
|
||||||
"null_platform.h",
|
"null_platform.h",
|
||||||
"null_joystick.h",
|
"null_joystick.h",
|
||||||
"posix_time.h",
|
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
"osmesa_context.h"
|
"osmesa_context.h"
|
||||||
],
|
],
|
||||||
@@ -47,7 +46,6 @@
|
|||||||
"null_monitor.c",
|
"null_monitor.c",
|
||||||
"null_window.c",
|
"null_window.c",
|
||||||
"null_joystick.c",
|
"null_joystick.c",
|
||||||
"posix_time.c",
|
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"osmesa_context.c"
|
"osmesa_context.c"
|
||||||
]
|
]
|
||||||
@@ -55,7 +53,6 @@
|
|||||||
"wayland": {
|
"wayland": {
|
||||||
"headers": [
|
"headers": [
|
||||||
"wl_platform.h",
|
"wl_platform.h",
|
||||||
"posix_time.h",
|
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
"xkb_glfw.h",
|
"xkb_glfw.h",
|
||||||
"dbus_glfw.h",
|
"dbus_glfw.h",
|
||||||
@@ -81,7 +78,6 @@
|
|||||||
"wl_init.c",
|
"wl_init.c",
|
||||||
"wl_monitor.c",
|
"wl_monitor.c",
|
||||||
"wl_window.c",
|
"wl_window.c",
|
||||||
"posix_time.c",
|
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"xkb_glfw.c",
|
"xkb_glfw.c",
|
||||||
"dbus_glfw.c",
|
"dbus_glfw.c",
|
||||||
@@ -125,7 +121,6 @@
|
|||||||
"dbus_glfw.h",
|
"dbus_glfw.h",
|
||||||
"ibus_glfw.h",
|
"ibus_glfw.h",
|
||||||
"backend_utils.h",
|
"backend_utils.h",
|
||||||
"posix_time.h",
|
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
"glx_context.h",
|
"glx_context.h",
|
||||||
"egl_context.h",
|
"egl_context.h",
|
||||||
@@ -142,7 +137,6 @@
|
|||||||
"xkb_glfw.c",
|
"xkb_glfw.c",
|
||||||
"dbus_glfw.c",
|
"dbus_glfw.c",
|
||||||
"ibus_glfw.c",
|
"ibus_glfw.c",
|
||||||
"posix_time.c",
|
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"glx_context.c",
|
"glx_context.c",
|
||||||
"egl_context.c",
|
"egl_context.c",
|
||||||
|
|||||||
14
glfw/vulkan.c
vendored
14
glfw/vulkan.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -55,6 +57,8 @@ bool _glfwInitVulkan(int mode)
|
|||||||
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
_glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
|
||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
|
||||||
|
if (!_glfw.vk.handle)
|
||||||
|
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
|
||||||
#else
|
#else
|
||||||
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
_glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
|
||||||
#endif
|
#endif
|
||||||
@@ -66,7 +70,7 @@ bool _glfwInitVulkan(int mode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
|
*(void **) &_glfw.vk.GetInstanceProcAddr =
|
||||||
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
|
||||||
if (!_glfw.vk.GetInstanceProcAddr)
|
if (!_glfw.vk.GetInstanceProcAddr)
|
||||||
{
|
{
|
||||||
@@ -128,6 +132,8 @@ bool _glfwInitVulkan(int mode)
|
|||||||
#elif defined(_GLFW_COCOA)
|
#elif defined(_GLFW_COCOA)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
|
||||||
_glfw.vk.MVK_macos_surface = true;
|
_glfw.vk.MVK_macos_surface = true;
|
||||||
|
else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
|
||||||
|
_glfw.vk.EXT_metal_surface = true;
|
||||||
#elif defined(_GLFW_X11)
|
#elif defined(_GLFW_X11)
|
||||||
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
|
||||||
_glfw.vk.KHR_xlib_surface = true;
|
_glfw.vk.KHR_xlib_surface = true;
|
||||||
@@ -260,7 +266,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!proc)
|
if (!proc)
|
||||||
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
|
*(void **) &proc = _glfw_dlsym(_glfw.vk.handle, procname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return proc;
|
return proc;
|
||||||
|
|||||||
743
glfw/wgl_context.c
vendored
743
glfw/wgl_context.c
vendored
@@ -1,743 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 WGL - 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>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
|
|
||||||
// Returns the specified attribute of the specified pixel format
|
|
||||||
//
|
|
||||||
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
|
|
||||||
{
|
|
||||||
int value = 0;
|
|
||||||
|
|
||||||
assert(_glfw.wgl.ARB_pixel_format);
|
|
||||||
|
|
||||||
if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
|
|
||||||
pixelFormat,
|
|
||||||
0, 1, &attrib, &value))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve pixel format attribute");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a list of available and usable framebuffer configs
|
|
||||||
//
|
|
||||||
static int choosePixelFormat(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
_GLFWfbconfig* usableConfigs;
|
|
||||||
const _GLFWfbconfig* closest;
|
|
||||||
int i, pixelFormat, nativeCount, usableCount;
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_pixel_format)
|
|
||||||
{
|
|
||||||
nativeCount = getPixelFormatAttrib(window,
|
|
||||||
1,
|
|
||||||
WGL_NUMBER_PIXEL_FORMATS_ARB);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nativeCount = DescribePixelFormat(window->context.wgl.dc,
|
|
||||||
1,
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
|
|
||||||
usableCount = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < nativeCount; i++)
|
|
||||||
{
|
|
||||||
const int n = i + 1;
|
|
||||||
_GLFWfbconfig* u = usableConfigs + usableCount;
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_pixel_format)
|
|
||||||
{
|
|
||||||
// Get pixel format attributes through "modern" extension
|
|
||||||
|
|
||||||
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
|
|
||||||
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
|
|
||||||
WGL_TYPE_RGBA_ARB)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
|
|
||||||
WGL_NO_ACCELERATION_ARB)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
|
|
||||||
u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
|
|
||||||
u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
|
|
||||||
u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
|
|
||||||
|
|
||||||
u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
|
|
||||||
u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
|
|
||||||
|
|
||||||
u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
|
|
||||||
u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
|
|
||||||
u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
|
|
||||||
u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
|
|
||||||
|
|
||||||
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
|
|
||||||
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
|
|
||||||
u->stereo = true;
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
|
|
||||||
u->doublebuffer = true;
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_multisample)
|
|
||||||
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_framebuffer_sRGB ||
|
|
||||||
_glfw.wgl.EXT_framebuffer_sRGB)
|
|
||||||
{
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
|
|
||||||
u->sRGB = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.EXT_colorspace)
|
|
||||||
{
|
|
||||||
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
|
|
||||||
WGL_COLORSPACE_SRGB_EXT)
|
|
||||||
{
|
|
||||||
u->sRGB = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get pixel format attributes through legacy PFDs
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
|
|
||||||
if (!DescribePixelFormat(window->context.wgl.dc,
|
|
||||||
n,
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
&pfd))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
|
|
||||||
!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
|
|
||||||
(pfd.dwFlags & PFD_GENERIC_FORMAT))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pfd.iPixelType != PFD_TYPE_RGBA)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
u->redBits = pfd.cRedBits;
|
|
||||||
u->greenBits = pfd.cGreenBits;
|
|
||||||
u->blueBits = pfd.cBlueBits;
|
|
||||||
u->alphaBits = pfd.cAlphaBits;
|
|
||||||
|
|
||||||
u->depthBits = pfd.cDepthBits;
|
|
||||||
u->stencilBits = pfd.cStencilBits;
|
|
||||||
|
|
||||||
u->accumRedBits = pfd.cAccumRedBits;
|
|
||||||
u->accumGreenBits = pfd.cAccumGreenBits;
|
|
||||||
u->accumBlueBits = pfd.cAccumBlueBits;
|
|
||||||
u->accumAlphaBits = pfd.cAccumAlphaBits;
|
|
||||||
|
|
||||||
u->auxBuffers = pfd.cAuxBuffers;
|
|
||||||
|
|
||||||
if (pfd.dwFlags & PFD_STEREO)
|
|
||||||
u->stereo = true;
|
|
||||||
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
|
|
||||||
u->doublebuffer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
u->handle = n;
|
|
||||||
usableCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!usableCount)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"WGL: The driver does not appear to support OpenGL");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
|
|
||||||
if (!closest)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
|
|
||||||
"WGL: Failed to find a suitable pixel format");
|
|
||||||
|
|
||||||
free(usableConfigs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelFormat = (int) closest->handle;
|
|
||||||
free(usableConfigs);
|
|
||||||
|
|
||||||
return pixelFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void makeContextCurrentWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, window);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to make context current");
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!wglMakeCurrent(NULL, NULL))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to clear current context");
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapBuffersWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (!window->monitor)
|
|
||||||
{
|
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
{
|
|
||||||
BOOL enabled;
|
|
||||||
|
|
||||||
// HACK: Use DwmFlush when desktop composition is enabled
|
|
||||||
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
|
||||||
{
|
|
||||||
int count = abs(window->context.wgl.interval);
|
|
||||||
while (count--)
|
|
||||||
DwmFlush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapBuffers(window->context.wgl.dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swapIntervalWGL(int interval)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
|
|
||||||
|
|
||||||
window->context.wgl.interval = interval;
|
|
||||||
|
|
||||||
if (!window->monitor)
|
|
||||||
{
|
|
||||||
if (IsWindowsVistaOrGreater())
|
|
||||||
{
|
|
||||||
BOOL enabled;
|
|
||||||
|
|
||||||
// HACK: Disable WGL swap interval when desktop composition is enabled to
|
|
||||||
// avoid interfering with DWM vsync
|
|
||||||
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
|
||||||
interval = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wgl.EXT_swap_control)
|
|
||||||
_glfw.wgl.SwapIntervalEXT(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int extensionSupportedWGL(const char* extension)
|
|
||||||
{
|
|
||||||
const char* extensions;
|
|
||||||
|
|
||||||
if (_glfw.wgl.GetExtensionsStringEXT)
|
|
||||||
{
|
|
||||||
extensions = _glfw.wgl.GetExtensionsStringEXT();
|
|
||||||
if (extensions)
|
|
||||||
{
|
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wgl.GetExtensionsStringARB)
|
|
||||||
{
|
|
||||||
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
|
|
||||||
if (extensions)
|
|
||||||
{
|
|
||||||
if (_glfwStringInExtensionString(extension, extensions))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLFWglproc getProcAddressWGL(const char* procname)
|
|
||||||
{
|
|
||||||
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
|
|
||||||
if (proc)
|
|
||||||
return proc;
|
|
||||||
|
|
||||||
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the OpenGL context
|
|
||||||
//
|
|
||||||
static void destroyContextWGL(_GLFWwindow* window)
|
|
||||||
{
|
|
||||||
if (window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
wglDeleteContext(window->context.wgl.handle);
|
|
||||||
window->context.wgl.handle = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW internal API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Initialize WGL
|
|
||||||
//
|
|
||||||
bool _glfwInitWGL(void)
|
|
||||||
{
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
HGLRC prc, rc;
|
|
||||||
HDC pdc, dc;
|
|
||||||
|
|
||||||
if (_glfw.wgl.instance)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
|
|
||||||
if (!_glfw.wgl.instance)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to load opengl32.dll");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
|
|
||||||
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
|
|
||||||
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
|
|
||||||
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
|
|
||||||
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
|
|
||||||
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
|
|
||||||
_glfw.wgl.ShareLists = (PFN_wglShareLists)
|
|
||||||
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
|
|
||||||
|
|
||||||
// NOTE: A dummy context has to be created for opengl32.dll to load the
|
|
||||||
// OpenGL ICD, from which we can then query WGL extensions
|
|
||||||
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
|
|
||||||
// creation failure occurs during manual pixel format enumeration
|
|
||||||
|
|
||||||
dc = GetDC(_glfw.win32.helperWindowHandle);
|
|
||||||
|
|
||||||
ZeroMemory(&pfd, sizeof(pfd));
|
|
||||||
pfd.nSize = sizeof(pfd);
|
|
||||||
pfd.nVersion = 1;
|
|
||||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
|
||||||
pfd.iPixelType = PFD_TYPE_RGBA;
|
|
||||||
pfd.cColorBits = 24;
|
|
||||||
|
|
||||||
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to set pixel format for dummy context");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = wglCreateContext(dc);
|
|
||||||
if (!rc)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to create dummy context");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdc = wglGetCurrentDC();
|
|
||||||
prc = wglGetCurrentContext();
|
|
||||||
|
|
||||||
if (!wglMakeCurrent(dc, rc))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to make dummy context current");
|
|
||||||
wglMakeCurrent(pdc, prc);
|
|
||||||
wglDeleteContext(rc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Functions must be loaded first as they're needed to retrieve the
|
|
||||||
// extension string that tells us whether the functions are supported
|
|
||||||
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
|
|
||||||
wglGetProcAddress("wglGetExtensionsStringEXT");
|
|
||||||
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
|
|
||||||
wglGetProcAddress("wglGetExtensionsStringARB");
|
|
||||||
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
|
|
||||||
wglGetProcAddress("wglCreateContextAttribsARB");
|
|
||||||
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
|
|
||||||
wglGetProcAddress("wglSwapIntervalEXT");
|
|
||||||
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
|
|
||||||
wglGetProcAddress("wglGetPixelFormatAttribivARB");
|
|
||||||
|
|
||||||
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
|
|
||||||
// checked below as we are already using them
|
|
||||||
_glfw.wgl.ARB_multisample =
|
|
||||||
extensionSupportedWGL("WGL_ARB_multisample");
|
|
||||||
_glfw.wgl.ARB_framebuffer_sRGB =
|
|
||||||
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
|
|
||||||
_glfw.wgl.EXT_framebuffer_sRGB =
|
|
||||||
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
|
|
||||||
_glfw.wgl.ARB_create_context =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context");
|
|
||||||
_glfw.wgl.ARB_create_context_profile =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_profile");
|
|
||||||
_glfw.wgl.EXT_create_context_es2_profile =
|
|
||||||
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
|
|
||||||
_glfw.wgl.ARB_create_context_robustness =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_robustness");
|
|
||||||
_glfw.wgl.ARB_create_context_no_error =
|
|
||||||
extensionSupportedWGL("WGL_ARB_create_context_no_error");
|
|
||||||
_glfw.wgl.EXT_swap_control =
|
|
||||||
extensionSupportedWGL("WGL_EXT_swap_control");
|
|
||||||
_glfw.wgl.EXT_colorspace =
|
|
||||||
extensionSupportedWGL("WGL_EXT_colorspace");
|
|
||||||
_glfw.wgl.ARB_pixel_format =
|
|
||||||
extensionSupportedWGL("WGL_ARB_pixel_format");
|
|
||||||
_glfw.wgl.ARB_context_flush_control =
|
|
||||||
extensionSupportedWGL("WGL_ARB_context_flush_control");
|
|
||||||
|
|
||||||
wglMakeCurrent(pdc, prc);
|
|
||||||
wglDeleteContext(rc);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terminate WGL
|
|
||||||
//
|
|
||||||
void _glfwTerminateWGL(void)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.instance)
|
|
||||||
FreeLibrary(_glfw.wgl.instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define setAttrib(a, v) \
|
|
||||||
{ \
|
|
||||||
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
|
|
||||||
attribs[index++] = a; \
|
|
||||||
attribs[index++] = v; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the OpenGL or OpenGL ES context
|
|
||||||
//
|
|
||||||
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig)
|
|
||||||
{
|
|
||||||
int attribs[40];
|
|
||||||
int pixelFormat;
|
|
||||||
PIXELFORMATDESCRIPTOR pfd;
|
|
||||||
HGLRC share = NULL;
|
|
||||||
|
|
||||||
if (ctxconfig->share)
|
|
||||||
share = ctxconfig->share->context.wgl.handle;
|
|
||||||
|
|
||||||
window->context.wgl.dc = GetDC(window->win32.handle);
|
|
||||||
if (!window->context.wgl.dc)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to retrieve DC for window");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
|
|
||||||
if (!pixelFormat)
|
|
||||||
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 false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to set selected pixel format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->profile)
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context_profile)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!_glfw.wgl.ARB_create_context ||
|
|
||||||
!_glfw.wgl.ARB_create_context_profile ||
|
|
||||||
!_glfw.wgl.EXT_create_context_es2_profile)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_API_UNAVAILABLE,
|
|
||||||
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wgl.ARB_create_context)
|
|
||||||
{
|
|
||||||
int index = 0, mask = 0, flags = 0;
|
|
||||||
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
if (ctxconfig->forward)
|
|
||||||
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
|
||||||
|
|
||||||
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
|
|
||||||
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
|
||||||
|
|
||||||
if (ctxconfig->debug)
|
|
||||||
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
|
|
||||||
|
|
||||||
if (ctxconfig->robustness)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_create_context_robustness)
|
|
||||||
{
|
|
||||||
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
WGL_NO_RESET_NOTIFICATION_ARB);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
|
|
||||||
WGL_LOSE_CONTEXT_ON_RESET_ARB);
|
|
||||||
}
|
|
||||||
|
|
||||||
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->release)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_context_flush_control)
|
|
||||||
{
|
|
||||||
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
|
|
||||||
}
|
|
||||||
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
|
|
||||||
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctxconfig->noerror)
|
|
||||||
{
|
|
||||||
if (_glfw.wgl.ARB_create_context_no_error)
|
|
||||||
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Only request an explicitly versioned context when necessary, as
|
|
||||||
// explicitly requesting version 1.0 does not always return the
|
|
||||||
// highest version supported by the driver
|
|
||||||
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
|
|
||||||
{
|
|
||||||
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
|
|
||||||
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags)
|
|
||||||
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
|
|
||||||
|
|
||||||
if (mask)
|
|
||||||
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
|
|
||||||
|
|
||||||
setAttrib(0, 0);
|
|
||||||
|
|
||||||
window->context.wgl.handle =
|
|
||||||
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
|
|
||||||
share, attribs);
|
|
||||||
if (!window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
const DWORD error = GetLastError();
|
|
||||||
|
|
||||||
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support OpenGL version %i.%i",
|
|
||||||
ctxconfig->major,
|
|
||||||
ctxconfig->minor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support OpenGL ES version %i.%i",
|
|
||||||
ctxconfig->major,
|
|
||||||
ctxconfig->minor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Driver does not support the requested OpenGL profile");
|
|
||||||
}
|
|
||||||
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_INVALID_VALUE,
|
|
||||||
"WGL: The share context is not compatible with the requested context");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ctxconfig->client == GLFW_OPENGL_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL context");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL ES context");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
|
|
||||||
if (!window->context.wgl.handle)
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: Failed to create OpenGL context");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (share)
|
|
||||||
{
|
|
||||||
if (!wglShareLists(share, window->context.wgl.handle))
|
|
||||||
{
|
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
|
||||||
"WGL: Failed to enable sharing with specified OpenGL context");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window->context.makeCurrent = makeContextCurrentWGL;
|
|
||||||
window->context.swapBuffers = swapBuffersWGL;
|
|
||||||
window->context.swapInterval = swapIntervalWGL;
|
|
||||||
window->context.extensionSupported = extensionSupportedWGL;
|
|
||||||
window->context.getProcAddress = getProcAddressWGL;
|
|
||||||
window->context.destroy = destroyContextWGL;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef setAttrib
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
////// GLFW native API //////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
|
|
||||||
{
|
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
|
||||||
|
|
||||||
if (window->context.client == GLFW_NO_API)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window->context.wgl.handle;
|
|
||||||
}
|
|
||||||
159
glfw/wgl_context.h
vendored
159
glfw/wgl_context.h
vendored
@@ -1,159 +0,0 @@
|
|||||||
//========================================================================
|
|
||||||
// GLFW 3.3 WGL - 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.
|
|
||||||
//
|
|
||||||
//========================================================================
|
|
||||||
|
|
||||||
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
|
|
||||||
#define WGL_SUPPORT_OPENGL_ARB 0x2010
|
|
||||||
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
|
|
||||||
#define WGL_PIXEL_TYPE_ARB 0x2013
|
|
||||||
#define WGL_TYPE_RGBA_ARB 0x202b
|
|
||||||
#define WGL_ACCELERATION_ARB 0x2003
|
|
||||||
#define WGL_NO_ACCELERATION_ARB 0x2025
|
|
||||||
#define WGL_RED_BITS_ARB 0x2015
|
|
||||||
#define WGL_RED_SHIFT_ARB 0x2016
|
|
||||||
#define WGL_GREEN_BITS_ARB 0x2017
|
|
||||||
#define WGL_GREEN_SHIFT_ARB 0x2018
|
|
||||||
#define WGL_BLUE_BITS_ARB 0x2019
|
|
||||||
#define WGL_BLUE_SHIFT_ARB 0x201a
|
|
||||||
#define WGL_ALPHA_BITS_ARB 0x201b
|
|
||||||
#define WGL_ALPHA_SHIFT_ARB 0x201c
|
|
||||||
#define WGL_ACCUM_BITS_ARB 0x201d
|
|
||||||
#define WGL_ACCUM_RED_BITS_ARB 0x201e
|
|
||||||
#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
|
|
||||||
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
|
|
||||||
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
|
|
||||||
#define WGL_DEPTH_BITS_ARB 0x2022
|
|
||||||
#define WGL_STENCIL_BITS_ARB 0x2023
|
|
||||||
#define WGL_AUX_BUFFERS_ARB 0x2024
|
|
||||||
#define WGL_STEREO_ARB 0x2012
|
|
||||||
#define WGL_DOUBLE_BUFFER_ARB 0x2011
|
|
||||||
#define WGL_SAMPLES_ARB 0x2042
|
|
||||||
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
|
|
||||||
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
|
|
||||||
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
|
|
||||||
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
|
||||||
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
|
||||||
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
|
||||||
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
|
||||||
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
|
||||||
#define WGL_CONTEXT_FLAGS_ARB 0x2094
|
|
||||||
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
|
|
||||||
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
|
|
||||||
#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
|
|
||||||
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
|
|
||||||
#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
|
|
||||||
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
|
|
||||||
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
|
|
||||||
#define WGL_COLORSPACE_EXT 0x309d
|
|
||||||
#define WGL_COLORSPACE_SRGB_EXT 0x3089
|
|
||||||
|
|
||||||
#define ERROR_INVALID_VERSION_ARB 0x2095
|
|
||||||
#define ERROR_INVALID_PROFILE_ARB 0x2096
|
|
||||||
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
|
|
||||||
|
|
||||||
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
|
|
||||||
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
|
|
||||||
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
|
|
||||||
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
|
|
||||||
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
|
|
||||||
|
|
||||||
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
|
|
||||||
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
|
|
||||||
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
|
|
||||||
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
|
|
||||||
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
|
|
||||||
|
|
||||||
// opengl32.dll function pointer typedefs
|
|
||||||
#define wglCreateContext _glfw.wgl.CreateContext
|
|
||||||
#define wglDeleteContext _glfw.wgl.DeleteContext
|
|
||||||
#define wglGetProcAddress _glfw.wgl.GetProcAddress
|
|
||||||
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
|
|
||||||
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
|
|
||||||
#define wglMakeCurrent _glfw.wgl.MakeCurrent
|
|
||||||
#define wglShareLists _glfw.wgl.ShareLists
|
|
||||||
|
|
||||||
#define _GLFW_RECREATION_NOT_NEEDED 0
|
|
||||||
#define _GLFW_RECREATION_REQUIRED 1
|
|
||||||
#define _GLFW_RECREATION_IMPOSSIBLE 2
|
|
||||||
|
|
||||||
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
|
|
||||||
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
|
|
||||||
|
|
||||||
|
|
||||||
// WGL-specific per-context data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWcontextWGL
|
|
||||||
{
|
|
||||||
HDC dc;
|
|
||||||
HGLRC handle;
|
|
||||||
int interval;
|
|
||||||
|
|
||||||
} _GLFWcontextWGL;
|
|
||||||
|
|
||||||
// WGL-specific global data
|
|
||||||
//
|
|
||||||
typedef struct _GLFWlibraryWGL
|
|
||||||
{
|
|
||||||
HINSTANCE instance;
|
|
||||||
PFN_wglCreateContext CreateContext;
|
|
||||||
PFN_wglDeleteContext DeleteContext;
|
|
||||||
PFN_wglGetProcAddress GetProcAddress;
|
|
||||||
PFN_wglGetCurrentDC GetCurrentDC;
|
|
||||||
PFN_wglGetCurrentContext GetCurrentContext;
|
|
||||||
PFN_wglMakeCurrent MakeCurrent;
|
|
||||||
PFN_wglShareLists ShareLists;
|
|
||||||
|
|
||||||
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
|
|
||||||
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
|
|
||||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
|
|
||||||
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
|
|
||||||
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
bool _glfwInitWGL(void);
|
|
||||||
void _glfwTerminateWGL(void);
|
|
||||||
bool _glfwCreateContextWGL(_GLFWwindow* window,
|
|
||||||
const _GLFWctxconfig* ctxconfig,
|
|
||||||
const _GLFWfbconfig* fbconfig);
|
|
||||||
|
|
||||||
37
glfw/window.c
vendored
37
glfw/window.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 - www.glfw.org
|
// GLFW 3.4 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
@@ -25,8 +25,11 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// Please use C89 style variable declarations in this file because VS 2010
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -54,8 +57,10 @@ void _glfwInputWindowFocus(_GLFWwindow* window, bool focused)
|
|||||||
{
|
{
|
||||||
if (window->keys[key] == GLFW_PRESS)
|
if (window->keys[key] == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
const int scancode = _glfwPlatformGetKeyScancode(key);
|
const int native_key = _glfwPlatformGetNativeKeyForKey(key);
|
||||||
_glfwInputKeyboard(window, key, scancode, GLFW_RELEASE, 0, "", 0);
|
GLFWkeyevent ev;
|
||||||
|
_glfwInitializeKeyEvent(&ev, key, native_key, GLFW_RELEASE, 0);
|
||||||
|
_glfwInputKeyboard(window, &ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +87,7 @@ _GLFWwindow* _glfwFocusedWindow() {
|
|||||||
_GLFWwindow* _glfwWindowForId(GLFWid id) {
|
_GLFWwindow* _glfwWindowForId(GLFWid id) {
|
||||||
_GLFWwindow *w = _glfw.windowListHead;
|
_GLFWwindow *w = _glfw.windowListHead;
|
||||||
while (w) {
|
while (w) {
|
||||||
if (w->id == _glfw.focusedWindowId) return w;
|
if (w->id == id) return w;
|
||||||
w = w->next;
|
w = w->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -181,7 +186,6 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
|
|||||||
window->monitor = monitor;
|
window->monitor = monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW public API //////
|
////// GLFW public API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -250,6 +254,8 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
|
|||||||
window->maxheight = GLFW_DONT_CARE;
|
window->maxheight = GLFW_DONT_CARE;
|
||||||
window->numer = GLFW_DONT_CARE;
|
window->numer = GLFW_DONT_CARE;
|
||||||
window->denom = GLFW_DONT_CARE;
|
window->denom = GLFW_DONT_CARE;
|
||||||
|
window->widthincr = GLFW_DONT_CARE;
|
||||||
|
window->heightincr = GLFW_DONT_CARE;
|
||||||
|
|
||||||
// Open the actual window and create its context
|
// Open the actual window and create its context
|
||||||
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
|
||||||
@@ -686,6 +692,20 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
|
|||||||
_glfwPlatformSetWindowAspectRatio(window, numer, denom);
|
_glfwPlatformSetWindowAspectRatio(window, numer, denom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLFWAPI void glfwSetWindowSizeIncrements(GLFWwindow* handle, int widthincr, int heightincr)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
|
assert(window != NULL);
|
||||||
|
assert(widthincr >= 0);
|
||||||
|
assert(heightincr >= 0);
|
||||||
|
|
||||||
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
|
window->widthincr = widthincr;
|
||||||
|
window->heightincr = heightincr;
|
||||||
|
_glfwPlatformSetWindowSizeIncrements(window, window->widthincr, window->heightincr);
|
||||||
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
|
GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
@@ -735,12 +755,12 @@ GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
|
|||||||
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
|
_glfwPlatformGetWindowContentScale(window, xscale, yscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI double glfwGetDoubleClickInterval(GLFWwindow* handle)
|
GLFWAPI monotonic_t glfwGetDoubleClickInterval(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(0.5f);
|
_GLFW_REQUIRE_INIT_OR_RETURN(ms_to_monotonic_t(500ll));
|
||||||
return _glfwPlatformGetDoubleClickInterval(window);
|
return _glfwPlatformGetDoubleClickInterval(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1165,6 +1185,5 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
|
|||||||
GLFWAPI void glfwPostEmptyEvent(void)
|
GLFWAPI void glfwPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
|
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|||||||
207
glfw/wl_init.c
vendored
207
glfw/wl_init.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Wayland - www.glfw.org
|
// GLFW 3.4 Wayland - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -23,15 +23,17 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <linux/input.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -39,6 +41,16 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
// Needed for the BTN_* defines
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<linux/input.h>)
|
||||||
|
#include <linux/input.h>
|
||||||
|
#elif __has_include(<dev/evdev/input.h>)
|
||||||
|
#include <dev/evdev/input.h>
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <linux/input.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline int min(int n1, int n2)
|
static inline int min(int n1, int n2)
|
||||||
@@ -46,7 +58,8 @@ static inline int min(int n1, int n2)
|
|||||||
return n1 < n2 ? n1 : n2;
|
return n1 < n2 ? n1 : n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, int* which)
|
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
|
||||||
|
int* which)
|
||||||
{
|
{
|
||||||
int focus;
|
int focus;
|
||||||
_GLFWwindow* window = _glfw.windowListHead;
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
@@ -79,12 +92,12 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleEnter(void* data,
|
static void pointerHandleEnter(void* data UNUSED,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
struct wl_surface* surface,
|
struct wl_surface* surface,
|
||||||
wl_fixed_t sx,
|
wl_fixed_t sx UNUSED,
|
||||||
wl_fixed_t sy)
|
wl_fixed_t sy UNUSED)
|
||||||
{
|
{
|
||||||
// Happens in the case we just destroyed the surface.
|
// Happens in the case we just destroyed the surface.
|
||||||
if (!surface)
|
if (!surface)
|
||||||
@@ -109,10 +122,10 @@ static void pointerHandleEnter(void* data,
|
|||||||
_glfwInputCursorEnter(window, true);
|
_glfwInputCursorEnter(window, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleLeave(void* data,
|
static void pointerHandleLeave(void* data UNUSED,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
struct wl_surface* surface)
|
struct wl_surface* surface UNUSED)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
|
|
||||||
@@ -124,6 +137,7 @@ static void pointerHandleLeave(void* data,
|
|||||||
_glfw.wl.pointerSerial = serial;
|
_glfw.wl.pointerSerial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfwInputCursorEnter(window, false);
|
_glfwInputCursorEnter(window, false);
|
||||||
|
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setCursor(GLFWCursorShape shape)
|
static void setCursor(GLFWCursorShape shape)
|
||||||
@@ -152,52 +166,57 @@ static void setCursor(GLFWCursorShape shape)
|
|||||||
wl_surface_damage(surface, 0, 0,
|
wl_surface_damage(surface, 0, 0,
|
||||||
image->width, image->height);
|
image->width, image->height);
|
||||||
wl_surface_commit(surface);
|
wl_surface_commit(surface);
|
||||||
|
_glfw.wl.cursorPreviousShape = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleMotion(void* data,
|
static void pointerHandleMotion(void* data UNUSED,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer UNUSED,
|
||||||
uint32_t time,
|
uint32_t time UNUSED,
|
||||||
wl_fixed_t sx,
|
wl_fixed_t sx,
|
||||||
wl_fixed_t sy)
|
wl_fixed_t sy)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR;
|
GLFWCursorShape cursorShape = GLFW_ARROW_CURSOR;
|
||||||
|
double x, y;
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
return;
|
return;
|
||||||
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
x = wl_fixed_to_double(sx);
|
||||||
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
y = wl_fixed_to_double(sy);
|
||||||
|
|
||||||
switch (window->wl.decorations.focus)
|
switch (window->wl.decorations.focus)
|
||||||
{
|
{
|
||||||
case mainWindow:
|
case mainWindow:
|
||||||
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
window->wl.cursorPosX = x;
|
||||||
|
window->wl.cursorPosY = y;
|
||||||
|
_glfwInputCursorPos(window, x, y);
|
||||||
|
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
|
||||||
return;
|
return;
|
||||||
case topDecoration:
|
case topDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (y < _GLFW_DECORATION_WIDTH)
|
||||||
cursorShape = GLFW_VRESIZE_CURSOR;
|
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorShape = GLFW_ARROW_CURSOR;
|
cursorShape = GLFW_ARROW_CURSOR;
|
||||||
break;
|
break;
|
||||||
case leftDecoration:
|
case leftDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (y < _GLFW_DECORATION_WIDTH)
|
||||||
cursorShape = GLFW_NW_RESIZE_CURSOR;
|
cursorShape = GLFW_NW_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorShape = GLFW_HRESIZE_CURSOR;
|
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||||
break;
|
break;
|
||||||
case rightDecoration:
|
case rightDecoration:
|
||||||
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
|
if (y < _GLFW_DECORATION_WIDTH)
|
||||||
cursorShape = GLFW_NE_RESIZE_CURSOR;
|
cursorShape = GLFW_NE_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorShape = GLFW_HRESIZE_CURSOR;
|
cursorShape = GLFW_HRESIZE_CURSOR;
|
||||||
break;
|
break;
|
||||||
case bottomDecoration:
|
case bottomDecoration:
|
||||||
if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
|
if (x < _GLFW_DECORATION_WIDTH)
|
||||||
cursorShape = GLFW_SW_RESIZE_CURSOR;
|
cursorShape = GLFW_SW_RESIZE_CURSOR;
|
||||||
else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
|
else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
|
||||||
cursorShape = GLFW_SE_RESIZE_CURSOR;
|
cursorShape = GLFW_SE_RESIZE_CURSOR;
|
||||||
else
|
else
|
||||||
cursorShape = GLFW_VRESIZE_CURSOR;
|
cursorShape = GLFW_VRESIZE_CURSOR;
|
||||||
@@ -205,19 +224,19 @@ static void pointerHandleMotion(void* data,
|
|||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
setCursor(cursorShape);
|
if (_glfw.wl.cursorPreviousShape != cursorShape)
|
||||||
|
setCursor(cursorShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleButton(void* data,
|
static void pointerHandleButton(void* data UNUSED,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
uint32_t time,
|
uint32_t time UNUSED,
|
||||||
uint32_t button,
|
uint32_t button,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
_GLFWwindow* window = _glfw.wl.pointerFocus;
|
||||||
int glfwButton;
|
int glfwButton;
|
||||||
|
|
||||||
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
@@ -272,8 +291,8 @@ static void pointerHandleButton(void* data,
|
|||||||
{
|
{
|
||||||
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
|
||||||
_glfw.wl.seat, serial,
|
_glfw.wl.seat, serial,
|
||||||
window->wl.cursorPosX,
|
(int32_t)window->wl.cursorPosX,
|
||||||
window->wl.cursorPosY);
|
(int32_t)window->wl.cursorPosY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,9 +315,9 @@ static void pointerHandleButton(void* data,
|
|||||||
_glfw.wl.xkb.states.modifiers);
|
_glfw.wl.xkb.states.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pointerHandleAxis(void* data,
|
static void pointerHandleAxis(void* data UNUSED,
|
||||||
struct wl_pointer* pointer,
|
struct wl_pointer* pointer UNUSED,
|
||||||
uint32_t time,
|
uint32_t time UNUSED,
|
||||||
uint32_t axis,
|
uint32_t axis,
|
||||||
wl_fixed_t value)
|
wl_fixed_t value)
|
||||||
{
|
{
|
||||||
@@ -326,8 +345,8 @@ static const struct wl_pointer_listener pointerListener = {
|
|||||||
pointerHandleAxis,
|
pointerHandleAxis,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void keyboardHandleKeymap(void* data,
|
static void keyboardHandleKeymap(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t format,
|
uint32_t format,
|
||||||
int fd,
|
int fd,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
@@ -351,9 +370,9 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleEnter(void* data,
|
static void keyboardHandleEnter(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial UNUSED,
|
||||||
struct wl_surface* surface,
|
struct wl_surface* surface,
|
||||||
struct wl_array* keys)
|
struct wl_array* keys)
|
||||||
{
|
{
|
||||||
@@ -371,12 +390,21 @@ static void keyboardHandleEnter(void* data,
|
|||||||
|
|
||||||
_glfw.wl.keyboardFocus = window;
|
_glfw.wl.keyboardFocus = window;
|
||||||
_glfwInputWindowFocus(window, true);
|
_glfwInputWindowFocus(window, true);
|
||||||
|
uint32_t* key;
|
||||||
|
if (keys && _glfw.wl.keyRepeatInfo.key) {
|
||||||
|
wl_array_for_each(key, keys) {
|
||||||
|
if (*key == _glfw.wl.keyRepeatInfo.key) {
|
||||||
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleLeave(void* data,
|
static void keyboardHandleLeave(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial UNUSED,
|
||||||
struct wl_surface* surface)
|
struct wl_surface* surface UNUSED)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||||
|
|
||||||
@@ -385,21 +413,22 @@ static void keyboardHandleLeave(void* data,
|
|||||||
|
|
||||||
_glfw.wl.keyboardFocus = NULL;
|
_glfw.wl.keyboardFocus = NULL;
|
||||||
_glfwInputWindowFocus(window, false);
|
_glfwInputWindowFocus(window, false);
|
||||||
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dispatchPendingKeyRepeats(id_type timer_id, void *data) {
|
dispatchPendingKeyRepeats(id_type timer_id UNUSED, void *data UNUSED) {
|
||||||
if (_glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return;
|
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);
|
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, (1.0 / (double)_glfw.wl.keyboardRepeatRate));
|
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (s_to_monotonic_t(1ll) / (monotonic_t)_glfw.wl.keyboardRepeatRate));
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void keyboardHandleKey(void* data,
|
static void keyboardHandleKey(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial UNUSED,
|
||||||
uint32_t time,
|
uint32_t time UNUSED,
|
||||||
uint32_t key,
|
uint32_t key,
|
||||||
uint32_t state)
|
uint32_t state)
|
||||||
{
|
{
|
||||||
@@ -409,6 +438,7 @@ static void keyboardHandleKey(void* data,
|
|||||||
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
|
||||||
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
glfw_xkb_handle_key_event(window, &_glfw.wl.xkb, key, action);
|
||||||
bool repeatable = false;
|
bool repeatable = false;
|
||||||
|
_glfw.wl.keyRepeatInfo.key = 0;
|
||||||
|
|
||||||
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
|
if (action == GLFW_PRESS && _glfw.wl.keyboardRepeatRate > 0 && glfw_xkb_should_repeat(&_glfw.wl.xkb, key))
|
||||||
{
|
{
|
||||||
@@ -417,14 +447,14 @@ static void keyboardHandleKey(void* data,
|
|||||||
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
||||||
}
|
}
|
||||||
if (repeatable) {
|
if (repeatable) {
|
||||||
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, (double)(_glfw.wl.keyboardRepeatDelay) / 1000.0);
|
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, _glfw.wl.keyboardRepeatDelay);
|
||||||
}
|
}
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, repeatable ? 1 : 0);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, repeatable ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleModifiers(void* data,
|
static void keyboardHandleModifiers(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard UNUSED,
|
||||||
uint32_t serial,
|
uint32_t serial UNUSED,
|
||||||
uint32_t modsDepressed,
|
uint32_t modsDepressed,
|
||||||
uint32_t modsLatched,
|
uint32_t modsLatched,
|
||||||
uint32_t modsLocked,
|
uint32_t modsLocked,
|
||||||
@@ -433,7 +463,7 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
|
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleRepeatInfo(void* data,
|
static void keyboardHandleRepeatInfo(void* data UNUSED,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard,
|
||||||
int32_t rate,
|
int32_t rate,
|
||||||
int32_t delay)
|
int32_t delay)
|
||||||
@@ -442,7 +472,7 @@ static void keyboardHandleRepeatInfo(void* data,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_glfw.wl.keyboardRepeatRate = rate;
|
_glfw.wl.keyboardRepeatRate = rate;
|
||||||
_glfw.wl.keyboardRepeatDelay = delay;
|
_glfw.wl.keyboardRepeatDelay = ms_to_monotonic_t(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboardListener = {
|
static const struct wl_keyboard_listener keyboardListener = {
|
||||||
@@ -454,7 +484,7 @@ static const struct wl_keyboard_listener keyboardListener = {
|
|||||||
keyboardHandleRepeatInfo,
|
keyboardHandleRepeatInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void seatHandleCapabilities(void* data,
|
static void seatHandleCapabilities(void* data UNUSED,
|
||||||
struct wl_seat* seat,
|
struct wl_seat* seat,
|
||||||
enum wl_seat_capability caps)
|
enum wl_seat_capability caps)
|
||||||
{
|
{
|
||||||
@@ -481,9 +511,9 @@ static void seatHandleCapabilities(void* data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seatHandleName(void* data,
|
static void seatHandleName(void* data UNUSED,
|
||||||
struct wl_seat* seat,
|
struct wl_seat* seat UNUSED,
|
||||||
const char* name)
|
const char* name UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +522,7 @@ static const struct wl_seat_listener seatListener = {
|
|||||||
seatHandleName,
|
seatHandleName,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void wmBaseHandlePing(void* data,
|
static void wmBaseHandlePing(void* data UNUSED,
|
||||||
struct xdg_wm_base* wmBase,
|
struct xdg_wm_base* wmBase,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
@@ -503,7 +533,7 @@ static const struct xdg_wm_base_listener wmBaseListener = {
|
|||||||
wmBaseHandlePing
|
wmBaseHandlePing
|
||||||
};
|
};
|
||||||
|
|
||||||
static void registryHandleGlobal(void* data,
|
static void registryHandleGlobal(void* data UNUSED,
|
||||||
struct wl_registry* registry,
|
struct wl_registry* registry,
|
||||||
uint32_t name,
|
uint32_t name,
|
||||||
const char* interface,
|
const char* interface,
|
||||||
@@ -595,8 +625,7 @@ static void registryHandleGlobal(void* data,
|
|||||||
_glfwSetupWaylandDataDevice();
|
_glfwSetupWaylandDataDevice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0 ||
|
else if (strcmp(interface, "zwp_primary_selection_device_manager_v1") == 0)
|
||||||
strcmp(interface, "gtk_primary_selection_device_manager") == 0)
|
|
||||||
{
|
{
|
||||||
_glfw.wl.primarySelectionDeviceManager =
|
_glfw.wl.primarySelectionDeviceManager =
|
||||||
wl_registry_bind(registry, name,
|
wl_registry_bind(registry, name,
|
||||||
@@ -609,8 +638,8 @@ static void registryHandleGlobal(void* data,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registryHandleGlobalRemove(void *data,
|
static void registryHandleGlobalRemove(void *data UNUSED,
|
||||||
struct wl_registry *registry,
|
struct wl_registry *registry UNUSED,
|
||||||
uint32_t name)
|
uint32_t name)
|
||||||
{
|
{
|
||||||
_GLFWmonitor* monitor;
|
_GLFWmonitor* monitor;
|
||||||
@@ -642,19 +671,19 @@ static const struct wl_registry_listener registryListener = {
|
|||||||
|
|
||||||
|
|
||||||
static void registry_handle_global(void* data,
|
static void registry_handle_global(void* data,
|
||||||
struct wl_registry* registry,
|
struct wl_registry* registry UNUSED,
|
||||||
uint32_t name,
|
uint32_t name UNUSED,
|
||||||
const char* interface,
|
const char* interface,
|
||||||
uint32_t version) {
|
uint32_t version UNUSED) {
|
||||||
if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
||||||
bool *has_ssd = (bool*)data;
|
bool *has_ssd = (bool*)data;
|
||||||
if (has_ssd) *has_ssd = true;
|
if (has_ssd) *has_ssd = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_handle_global_remove(void *data,
|
static void registry_handle_global_remove(void *data UNUSED,
|
||||||
struct wl_registry *registry,
|
struct wl_registry *registry UNUSED,
|
||||||
uint32_t name) {}
|
uint32_t name UNUSED) {}
|
||||||
GLFWAPI const char*
|
GLFWAPI const char*
|
||||||
glfwWaylandCheckForServerSideDecorations(void) {
|
glfwWaylandCheckForServerSideDecorations(void) {
|
||||||
struct wl_display *display = wl_display_connect(NULL);
|
struct wl_display *display = wl_display_connect(NULL);
|
||||||
@@ -679,13 +708,6 @@ glfwWaylandCheckForServerSideDecorations(void) {
|
|||||||
|
|
||||||
int _glfwPlatformInit(void)
|
int _glfwPlatformInit(void)
|
||||||
{
|
{
|
||||||
if (pipe2(_glfw.wl.eventLoopData.wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: failed to create self pipe");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
|
||||||
if (!_glfw.wl.cursor.handle)
|
if (!_glfw.wl.cursor.handle)
|
||||||
{
|
{
|
||||||
@@ -694,14 +716,10 @@ int _glfwPlatformInit(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
|
glfw_dlsym(_glfw.wl.cursor.theme_load, _glfw.wl.cursor.handle, "wl_cursor_theme_load");
|
||||||
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
|
glfw_dlsym(_glfw.wl.cursor.theme_destroy, _glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
|
||||||
_glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
|
glfw_dlsym(_glfw.wl.cursor.theme_get_cursor, _glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
|
||||||
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
|
glfw_dlsym(_glfw.wl.cursor.image_get_buffer, _glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
|
||||||
_glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
|
|
||||||
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
|
|
||||||
_glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
|
|
||||||
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
|
|
||||||
|
|
||||||
_glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
|
_glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
|
||||||
if (!_glfw.wl.egl.handle)
|
if (!_glfw.wl.egl.handle)
|
||||||
@@ -711,12 +729,9 @@ int _glfwPlatformInit(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
|
glfw_dlsym(_glfw.wl.egl.window_create, _glfw.wl.egl.handle, "wl_egl_window_create");
|
||||||
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
|
glfw_dlsym(_glfw.wl.egl.window_destroy, _glfw.wl.egl.handle, "wl_egl_window_destroy");
|
||||||
_glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
|
glfw_dlsym(_glfw.wl.egl.window_resize, _glfw.wl.egl.handle, "wl_egl_window_resize");
|
||||||
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
|
|
||||||
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
|
||||||
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
|
||||||
|
|
||||||
_glfw.wl.display = wl_display_connect(NULL);
|
_glfw.wl.display = wl_display_connect(NULL);
|
||||||
if (!_glfw.wl.display)
|
if (!_glfw.wl.display)
|
||||||
@@ -725,10 +740,13 @@ int _glfwPlatformInit(void)
|
|||||||
"Wayland: Failed to connect to display");
|
"Wayland: Failed to connect to display");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
initPollData(&_glfw.wl.eventLoopData, _glfw.wl.eventLoopData.wakeupFds[0], wl_display_get_fd(_glfw.wl.display));
|
if (!initPollData(&_glfw.wl.eventLoopData, wl_display_get_fd(_glfw.wl.display))) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to initialize event loop data");
|
||||||
|
}
|
||||||
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
|
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData);
|
||||||
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", 0.5, 0, true, dispatchPendingKeyRepeats, NULL, NULL);
|
_glfw.wl.keyRepeatInfo.keyRepeatTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-key-repeat", ms_to_monotonic_t(500ll), 0, true, dispatchPendingKeyRepeats, NULL, NULL);
|
||||||
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, true, animateCursorImage, NULL, NULL);
|
_glfw.wl.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", ms_to_monotonic_t(500ll), 0, true, animateCursorImage, NULL, NULL);
|
||||||
|
|
||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
@@ -748,7 +766,6 @@ int _glfwPlatformInit(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
|
||||||
if (!_glfw.wl.wmBase)
|
if (!_glfw.wl.wmBase)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -835,7 +852,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
wl_data_source_destroy(_glfw.wl.dataSourceForClipboard);
|
wl_data_source_destroy(_glfw.wl.dataSourceForClipboard);
|
||||||
for (size_t doi=0; doi < arraysz(_glfw.wl.dataOffers); doi++) {
|
for (size_t doi=0; doi < arraysz(_glfw.wl.dataOffers); doi++) {
|
||||||
if (_glfw.wl.dataOffers[doi].id) {
|
if (_glfw.wl.dataOffers[doi].id) {
|
||||||
wl_data_offer_destroy(_glfw.wl.dataOffers[doi].id);
|
destroy_data_offer(&_glfw.wl.dataOffers[doi]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_glfw.wl.dataDevice)
|
if (_glfw.wl.dataDevice)
|
||||||
@@ -853,7 +870,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
wl_display_flush(_glfw.wl.display);
|
wl_display_flush(_glfw.wl.display);
|
||||||
wl_display_disconnect(_glfw.wl.display);
|
wl_display_disconnect(_glfw.wl.display);
|
||||||
}
|
}
|
||||||
closeFds(_glfw.wl.eventLoopData.wakeupFds, sizeof(_glfw.wl.eventLoopData.wakeupFds)/sizeof(_glfw.wl.eventLoopData.wakeupFds[0]));
|
finalizePollData(&_glfw.wl.eventLoopData);
|
||||||
free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL;
|
free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL;
|
||||||
free(_glfw.wl.primarySelectionString); _glfw.wl.primarySelectionString = NULL;
|
free(_glfw.wl.primarySelectionString); _glfw.wl.primarySelectionString = NULL;
|
||||||
free(_glfw.wl.pasteString); _glfw.wl.pasteString = NULL;
|
free(_glfw.wl.pasteString); _glfw.wl.pasteString = NULL;
|
||||||
|
|||||||
49
glfw/wl_monitor.c
vendored
49
glfw/wl_monitor.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Wayland - www.glfw.org
|
// GLFW 3.4 Wayland - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -34,15 +36,15 @@
|
|||||||
|
|
||||||
|
|
||||||
static void outputHandleGeometry(void* data,
|
static void outputHandleGeometry(void* data,
|
||||||
struct wl_output* output,
|
struct wl_output* output UNUSED,
|
||||||
int32_t x,
|
int32_t x,
|
||||||
int32_t y,
|
int32_t y,
|
||||||
int32_t physicalWidth,
|
int32_t physicalWidth,
|
||||||
int32_t physicalHeight,
|
int32_t physicalHeight,
|
||||||
int32_t subpixel,
|
int32_t subpixel UNUSED,
|
||||||
const char* make,
|
const char* make,
|
||||||
const char* model,
|
const char* model,
|
||||||
int32_t transform)
|
int32_t transform UNUSED)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
char name[1024];
|
char name[1024];
|
||||||
@@ -57,11 +59,11 @@ static void outputHandleGeometry(void* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void outputHandleMode(void* data,
|
static void outputHandleMode(void* data,
|
||||||
struct wl_output* output,
|
struct wl_output* output UNUSED,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
int32_t width,
|
int32_t width,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
int32_t refresh)
|
int32_t refresh)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
GLFWvidmode mode;
|
GLFWvidmode mode;
|
||||||
@@ -71,7 +73,7 @@ static void outputHandleMode(void* data,
|
|||||||
mode.redBits = 8;
|
mode.redBits = 8;
|
||||||
mode.greenBits = 8;
|
mode.greenBits = 8;
|
||||||
mode.blueBits = 8;
|
mode.blueBits = 8;
|
||||||
mode.refreshRate = (int)round(refresh / 1000.0);
|
mode.refreshRate = (int) round(refresh / 1000.0);
|
||||||
|
|
||||||
monitor->modeCount++;
|
monitor->modeCount++;
|
||||||
monitor->modes =
|
monitor->modes =
|
||||||
@@ -82,7 +84,7 @@ static void outputHandleMode(void* data,
|
|||||||
monitor->wl.currentMode = monitor->modeCount - 1;
|
monitor->wl.currentMode = monitor->modeCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputHandleDone(void* data, struct wl_output* output)
|
static void outputHandleDone(void* data, struct wl_output* output UNUSED)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
for (int i = 0; i < _glfw.monitorCount; i++) {
|
for (int i = 0; i < _glfw.monitorCount; i++) {
|
||||||
@@ -93,8 +95,8 @@ static void outputHandleDone(void* data, struct wl_output* output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void outputHandleScale(void* data,
|
static void outputHandleScale(void* data,
|
||||||
struct wl_output* output,
|
struct wl_output* output UNUSED,
|
||||||
int32_t factor)
|
int32_t factor)
|
||||||
{
|
{
|
||||||
struct _GLFWmonitor *monitor = data;
|
struct _GLFWmonitor *monitor = data;
|
||||||
if (factor > 0 && factor < 24)
|
if (factor > 0 && factor < 24)
|
||||||
@@ -173,7 +175,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = (float) monitor->wl.scale;
|
*yscale = (float) monitor->wl.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
|
||||||
|
int* xpos, int* ypos,
|
||||||
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
if (xpos)
|
if (xpos)
|
||||||
*xpos = monitor->wl.x;
|
*xpos = monitor->wl.x;
|
||||||
@@ -196,14 +200,15 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
*mode = monitor->modes[monitor->wl.currentMode];
|
*mode = monitor->modes[monitor->wl.currentMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
|
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Gamma ramp access is not available");
|
"Wayland: Gamma ramp access is not available");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED,
|
||||||
|
const GLFWgammaramp* ramp UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Gamma ramp access is not available");
|
"Wayland: Gamma ramp access is not available");
|
||||||
|
|||||||
45
glfw/wl_platform.h
vendored
45
glfw/wl_platform.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Wayland - www.glfw.org
|
// GLFW 3.4 Wayland - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -43,7 +43,6 @@ typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWa
|
|||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);
|
||||||
|
|
||||||
#include "posix_thread.h"
|
#include "posix_thread.h"
|
||||||
#include "posix_time.h"
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
#else
|
#else
|
||||||
@@ -133,10 +132,10 @@ typedef struct _GLFWdecorationWayland
|
|||||||
typedef struct _GLFWwindowWayland
|
typedef struct _GLFWwindowWayland
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
bool visible;
|
bool visible;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
bool hovered;
|
bool hovered;
|
||||||
bool transparent;
|
bool transparent;
|
||||||
struct wl_surface* surface;
|
struct wl_surface* surface;
|
||||||
struct wl_egl_window* native;
|
struct wl_egl_window* native;
|
||||||
struct wl_callback* callback;
|
struct wl_callback* callback;
|
||||||
@@ -156,6 +155,7 @@ typedef struct _GLFWwindowWayland
|
|||||||
// We need to track the monitors the window spans on to calculate the
|
// We need to track the monitors the window spans on to calculate the
|
||||||
// optimal scaling factor.
|
// optimal scaling factor.
|
||||||
int scale;
|
int scale;
|
||||||
|
bool initial_scale_notified;
|
||||||
_GLFWmonitor** monitors;
|
_GLFWmonitor** monitors;
|
||||||
int monitorsCount;
|
int monitorsCount;
|
||||||
int monitorsSize;
|
int monitorsSize;
|
||||||
@@ -167,10 +167,10 @@ typedef struct _GLFWwindowWayland
|
|||||||
|
|
||||||
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
struct zwp_idle_inhibitor_v1* idleInhibitor;
|
||||||
|
|
||||||
bool fullscreened;
|
bool fullscreened;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool serverSide;
|
bool serverSide;
|
||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
_GLFWdecorationWayland top, left, right, bottom;
|
_GLFWdecorationWayland top, left, right, bottom;
|
||||||
int focus;
|
int focus;
|
||||||
@@ -195,28 +195,19 @@ typedef enum _GLFWWaylandOfferType
|
|||||||
|
|
||||||
typedef struct _GLFWWaylandDataOffer
|
typedef struct _GLFWWaylandDataOffer
|
||||||
{
|
{
|
||||||
struct wl_data_offer *id;
|
void *id;
|
||||||
const char *mime;
|
|
||||||
_GLFWWaylandOfferType offer_type;
|
_GLFWWaylandOfferType offer_type;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
int is_self_offer;
|
bool is_self_offer;
|
||||||
int has_uri_list;
|
bool is_primary;
|
||||||
|
const char *plain_text_mime, *mime_for_drop;
|
||||||
uint32_t source_actions;
|
uint32_t source_actions;
|
||||||
uint32_t dnd_action;
|
uint32_t dnd_action;
|
||||||
struct wl_surface *surface;
|
struct wl_surface *surface;
|
||||||
|
const char **mimes;
|
||||||
|
size_t mimes_capacity, mimes_count;
|
||||||
} _GLFWWaylandDataOffer;
|
} _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
|
// Wayland-specific global data
|
||||||
//
|
//
|
||||||
typedef struct _GLFWlibraryWayland
|
typedef struct _GLFWlibraryWayland
|
||||||
@@ -247,10 +238,11 @@ typedef struct _GLFWlibraryWayland
|
|||||||
|
|
||||||
struct wl_cursor_theme* cursorTheme;
|
struct wl_cursor_theme* cursorTheme;
|
||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
|
GLFWCursorShape cursorPreviousShape;
|
||||||
uint32_t pointerSerial;
|
uint32_t pointerSerial;
|
||||||
|
|
||||||
int32_t keyboardRepeatRate;
|
int32_t keyboardRepeatRate;
|
||||||
int32_t keyboardRepeatDelay;
|
monotonic_t keyboardRepeatDelay;
|
||||||
struct {
|
struct {
|
||||||
uint32_t key;
|
uint32_t key;
|
||||||
id_type keyRepeatTimer;
|
id_type keyRepeatTimer;
|
||||||
@@ -286,8 +278,6 @@ typedef struct _GLFWlibraryWayland
|
|||||||
size_t dataOffersCounter;
|
size_t dataOffersCounter;
|
||||||
_GLFWWaylandDataOffer dataOffers[8];
|
_GLFWWaylandDataOffer dataOffers[8];
|
||||||
char* primarySelectionString;
|
char* primarySelectionString;
|
||||||
size_t primarySelectionOffersCounter;
|
|
||||||
_GLFWWaylandPrimaryOffer primarySelectionOffers[8];
|
|
||||||
} _GLFWlibraryWayland;
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
// Wayland-specific per-monitor data
|
// Wayland-specific per-monitor data
|
||||||
@@ -295,7 +285,7 @@ typedef struct _GLFWlibraryWayland
|
|||||||
typedef struct _GLFWmonitorWayland
|
typedef struct _GLFWmonitorWayland
|
||||||
{
|
{
|
||||||
struct wl_output* output;
|
struct wl_output* output;
|
||||||
int name;
|
uint32_t name;
|
||||||
int currentMode;
|
int currentMode;
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
@@ -321,3 +311,4 @@ void _glfwSetupWaylandDataDevice(void);
|
|||||||
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
void _glfwSetupWaylandPrimarySelectionDevice(void);
|
||||||
void animateCursorImage(id_type timer_id, void *data);
|
void animateCursorImage(id_type timer_id, void *data);
|
||||||
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape);
|
struct wl_cursor* _glfwLoadCursor(GLFWCursorShape);
|
||||||
|
void destroy_data_offer(_GLFWWaylandDataOffer*);
|
||||||
|
|||||||
445
glfw/wl_window.c
vendored
445
glfw/wl_window.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 Wayland - www.glfw.org
|
// GLFW 3.4 Wayland - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
|
||||||
//
|
//
|
||||||
@@ -23,6 +23,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
#include "memfd.h"
|
#include "memfd.h"
|
||||||
#include "linux_notify.h"
|
#include "linux_notify.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -39,7 +42,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
|
||||||
#define URI_LIST_MIME "text/uri-list"
|
|
||||||
|
|
||||||
|
|
||||||
static bool checkScaleChange(_GLFWwindow* window)
|
static bool checkScaleChange(_GLFWwindow* window)
|
||||||
@@ -52,13 +55,18 @@ static bool checkScaleChange(_GLFWwindow* window)
|
|||||||
if (_glfw.wl.compositorVersion < 3)
|
if (_glfw.wl.compositorVersion < 3)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Get the scale factor from the highest scale monitor.
|
// Get the scale factor from the highest scale monitor that this window is on
|
||||||
for (i = 0; i < window->wl.monitorsCount; ++i)
|
for (i = 0; i < window->wl.monitorsCount; ++i)
|
||||||
{
|
{
|
||||||
monitorScale = window->wl.monitors[i]->wl.scale;
|
monitorScale = window->wl.monitors[i]->wl.scale;
|
||||||
if (scale < monitorScale)
|
if (scale < monitorScale)
|
||||||
scale = monitorScale;
|
scale = monitorScale;
|
||||||
}
|
}
|
||||||
|
if (window->wl.monitorsCount < 1 && _glfw.monitorCount > 0) {
|
||||||
|
// The window has not yet been assigned to any monitors, use the primary monitor
|
||||||
|
_GLFWmonitor *m = _glfw.monitors[0];
|
||||||
|
if (m && m->wl.scale > scale) scale = m->wl.scale;
|
||||||
|
}
|
||||||
|
|
||||||
// Only change the framebuffer size if the scale changed.
|
// Only change the framebuffer size if the scale changed.
|
||||||
if (scale != window->wl.scale)
|
if (scale != window->wl.scale)
|
||||||
@@ -67,6 +75,10 @@ static bool checkScaleChange(_GLFWwindow* window)
|
|||||||
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
wl_surface_set_buffer_scale(window->wl.surface, scale);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (window->wl.monitorsCount > 0 && !window->wl.initial_scale_notified) {
|
||||||
|
window->wl.initial_scale_notified = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,7 +183,7 @@ static void dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, in
|
|||||||
* SCM_RIGHTS methods.
|
* SCM_RIGHTS methods.
|
||||||
*
|
*
|
||||||
* posix_fallocate() is used to guarantee that disk space is available
|
* posix_fallocate() is used to guarantee that disk space is available
|
||||||
* for the file at the given size. If disk space is insufficent, errno
|
* for the file at the given size. If disk space is insufficient, errno
|
||||||
* is set to ENOSPC. If posix_fallocate() is not supported, program may
|
* is set to ENOSPC. If posix_fallocate() is not supported, program may
|
||||||
* receive SIGBUS on accessing mmap()'ed file contents instead.
|
* receive SIGBUS on accessing mmap()'ed file contents instead.
|
||||||
*/
|
*/
|
||||||
@@ -239,8 +251,8 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Creating a buffer file for %d B failed: %m",
|
"Wayland: Creating a buffer file for %d B failed: %s",
|
||||||
length);
|
length, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +260,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
|
|||||||
if (data == MAP_FAILED)
|
if (data == MAP_FAILED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: mmap failed: %m");
|
"Wayland: mmap failed: %s", strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -363,12 +375,12 @@ static void destroyDecorations(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void xdgDecorationHandleConfigure(void* data,
|
static void xdgDecorationHandleConfigure(void* data,
|
||||||
struct zxdg_toplevel_decoration_v1* decoration,
|
struct zxdg_toplevel_decoration_v1* decoration UNUSED,
|
||||||
uint32_t mode)
|
uint32_t mode)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||||
if (!window->wl.decorations.serverSide)
|
if (!window->wl.decorations.serverSide)
|
||||||
createDecorations(window);
|
createDecorations(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +389,7 @@ static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void handleEnter(void *data,
|
static void handleEnter(void *data,
|
||||||
struct wl_surface *surface,
|
struct wl_surface *surface UNUSED,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
@@ -400,7 +412,7 @@ static void handleEnter(void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handleLeave(void *data,
|
static void handleLeave(void *data,
|
||||||
struct wl_surface *surface,
|
struct wl_surface *surface UNUSED,
|
||||||
struct wl_output *output)
|
struct wl_output *output)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
@@ -496,15 +508,14 @@ setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, bool on)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags) {
|
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
|
||||||
(void) flags;
|
|
||||||
bool already_fullscreen = window->wl.fullscreened;
|
bool already_fullscreen = window->wl.fullscreened;
|
||||||
setFullscreen(window, NULL, !already_fullscreen);
|
setFullscreen(window, NULL, !already_fullscreen);
|
||||||
return !already_fullscreen;
|
return !already_fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xdgToplevelHandleConfigure(void* data,
|
static void xdgToplevelHandleConfigure(void* data,
|
||||||
struct xdg_toplevel* toplevel,
|
struct xdg_toplevel* toplevel UNUSED,
|
||||||
int32_t width,
|
int32_t width,
|
||||||
int32_t height,
|
int32_t height,
|
||||||
struct wl_array* states)
|
struct wl_array* states)
|
||||||
@@ -544,9 +555,9 @@ static void xdgToplevelHandleConfigure(void* data,
|
|||||||
aspectRatio = (float)width / (float)height;
|
aspectRatio = (float)width / (float)height;
|
||||||
targetRatio = (float)window->numer / (float)window->denom;
|
targetRatio = (float)window->numer / (float)window->denom;
|
||||||
if (aspectRatio < targetRatio)
|
if (aspectRatio < targetRatio)
|
||||||
height = width / targetRatio;
|
height = (int32_t)((float)width / targetRatio);
|
||||||
else if (aspectRatio > targetRatio)
|
else if (aspectRatio > targetRatio)
|
||||||
width = height * targetRatio;
|
width = (int32_t)((float)height * targetRatio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,7 +573,7 @@ static void xdgToplevelHandleConfigure(void* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void xdgToplevelHandleClose(void* data,
|
static void xdgToplevelHandleClose(void* data,
|
||||||
struct xdg_toplevel* toplevel)
|
struct xdg_toplevel* toplevel UNUSED)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = data;
|
_GLFWwindow* window = data;
|
||||||
_glfwInputWindowCloseRequest(window);
|
_glfwInputWindowCloseRequest(window);
|
||||||
@@ -573,7 +584,7 @@ static const struct xdg_toplevel_listener xdgToplevelListener = {
|
|||||||
xdgToplevelHandleClose
|
xdgToplevelHandleClose
|
||||||
};
|
};
|
||||||
|
|
||||||
static void xdgSurfaceHandleConfigure(void* data,
|
static void xdgSurfaceHandleConfigure(void* data UNUSED,
|
||||||
struct xdg_surface* surface,
|
struct xdg_surface* surface,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
@@ -683,7 +694,7 @@ setCursorImage(_GLFWcursorWayland* cursorWayland)
|
|||||||
image = cursorWayland->cursor->images[cursorWayland->currentImage];
|
image = cursorWayland->cursor->images[cursorWayland->currentImage];
|
||||||
buffer = wl_cursor_image_get_buffer(image);
|
buffer = wl_cursor_image_get_buffer(image);
|
||||||
if (image->delay) {
|
if (image->delay) {
|
||||||
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, ((double)image->delay) / 1000.0);
|
changeTimerInterval(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, ms_to_monotonic_t(image->delay));
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 1);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 1);
|
||||||
} else {
|
} else {
|
||||||
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.cursorAnimationTimer, 0);
|
||||||
@@ -726,7 +737,7 @@ incrementCursorImage(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
animateCursorImage(id_type timer_id, void *data) {
|
animateCursorImage(id_type timer_id UNUSED, void *data UNUSED) {
|
||||||
incrementCursorImage(_glfw.wl.pointerFocus);
|
incrementCursorImage(_glfw.wl.pointerFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -739,26 +750,28 @@ abortOnFatalError(int last_error) {
|
|||||||
_glfwInputWindowCloseRequest(window);
|
_glfwInputWindowCloseRequest(window);
|
||||||
window = window->next;
|
window = window->next;
|
||||||
}
|
}
|
||||||
|
// ensure the tick callback is called
|
||||||
|
_glfw.wl.eventLoopData.wakeup_data_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(double timeout)
|
wayland_read_events(int poll_result, int events, void *data UNUSED) {
|
||||||
|
EVDBG("wayland_read_events poll_result: %d events: %d", poll_result, events);
|
||||||
|
if (poll_result > 0 && events) wl_display_read_events(_glfw.wl.display);
|
||||||
|
else wl_display_cancel_read(_glfw.wl.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handleEvents(monotonic_t timeout)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
struct wl_display* display = _glfw.wl.display;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
EVDBG("starting handleEvents(%.2f)", monotonic_t_to_s_double(timeout));
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0) {
|
while (wl_display_prepare_read(display) != 0) {
|
||||||
while(1) {
|
if (wl_display_dispatch_pending(display) == -1) {
|
||||||
errno = 0;
|
abortOnFatalError(errno);
|
||||||
int num_dispatched = wl_display_dispatch_pending(display);
|
return;
|
||||||
if (num_dispatched == 0) return;
|
|
||||||
if (num_dispatched < 0) {
|
|
||||||
if (errno == EAGAIN) continue;
|
|
||||||
int last_error = wl_display_get_error(display);
|
|
||||||
if (last_error) abortOnFatalError(last_error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -768,22 +781,26 @@ handleEvents(double timeout)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
if (wl_display_flush(display) < 0 && errno != EAGAIN)
|
if (wl_display_flush(display) < 0 && errno != EAGAIN)
|
||||||
{
|
{
|
||||||
abortOnFatalError(errno);
|
|
||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
|
abortOnFatalError(errno);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout);
|
// we pass in wayland_read_events to ensure that the above wl_display_prepare_read call
|
||||||
|
// is followed by either wl_display_cancel_read or wl_display_read_events
|
||||||
|
// before any events/timers are dispatched. This allows other wayland functions
|
||||||
|
// to be called in the event/timer handlers without causing a deadlock
|
||||||
|
bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout, wayland_read_events);
|
||||||
|
EVDBG("display_read_ok: %d", display_read_ok);
|
||||||
if (display_read_ok) {
|
if (display_read_ok) {
|
||||||
wl_display_read_events(display);
|
int num = wl_display_dispatch_pending(display);
|
||||||
wl_display_dispatch_pending(display);
|
(void)num;
|
||||||
}
|
EVDBG("dispatched %d Wayland events", num);
|
||||||
else
|
|
||||||
{
|
|
||||||
wl_display_cancel_read(display);
|
|
||||||
}
|
}
|
||||||
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
|
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
|
||||||
glfw_dbus_session_bus_dispatch();
|
glfw_dbus_session_bus_dispatch();
|
||||||
|
EVDBG("other dispatch done");
|
||||||
|
if (_glfw.wl.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.wl.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_cursor*
|
static struct wl_cursor*
|
||||||
@@ -914,6 +931,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
|||||||
destroyDecorations(window);
|
destroyDecorations(window);
|
||||||
if (window->wl.xdg.decoration)
|
if (window->wl.xdg.decoration)
|
||||||
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
||||||
|
|
||||||
if (window->wl.decorations.buffer)
|
if (window->wl.decorations.buffer)
|
||||||
wl_buffer_destroy(window->wl.decorations.buffer);
|
wl_buffer_destroy(window->wl.decorations.buffer);
|
||||||
|
|
||||||
@@ -940,18 +958,23 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
free(window->wl.title);
|
free(window->wl.title);
|
||||||
window->wl.title = _glfw_strdup(title);
|
window->wl.title = _glfw_strdup(title);
|
||||||
|
// Wayland cannot handle requests larger than ~8200 bytes. Sending
|
||||||
|
// one causes an abort(). Since titles this large are meaningless anyway
|
||||||
|
// ensure they do not happen. One should really truncate ensuring valid UTF-8
|
||||||
|
// but I cant be bothered.
|
||||||
|
if (title && strnlen(title, 2048) >= 2048) window->wl.title[2048] = 0;
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
|
xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
|
||||||
int count, const GLFWimage* images)
|
int count UNUSED, const GLFWimage* images UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Setting window icon not supported");
|
"Wayland: Setting window icon not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
|
||||||
{
|
{
|
||||||
// A Wayland client is not aware of its position, so just warn and leave it
|
// A Wayland client is not aware of its position, so just warn and leave it
|
||||||
// as (0, 0)
|
// as (0, 0)
|
||||||
@@ -960,7 +983,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
|||||||
"Wayland: Window position retrieval not supported");
|
"Wayland: Window position retrieval not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
|
void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
|
||||||
{
|
{
|
||||||
// A Wayland client can not set its position, so just warn
|
// A Wayland client can not set its position, so just warn
|
||||||
|
|
||||||
@@ -1001,13 +1024,22 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED,
|
||||||
|
int numer UNUSED, int denom UNUSED)
|
||||||
{
|
{
|
||||||
// TODO: find out how to trigger a resize.
|
// TODO: find out how to trigger a resize.
|
||||||
// The actual limits are checked in the xdg_toplevel::configure handler.
|
// The actual limits are checked in the xdg_toplevel::configure handler.
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window UNUSED,
|
||||||
|
int widthincr UNUSED, int heightincr UNUSED)
|
||||||
|
{
|
||||||
|
// TODO: find out how to trigger a resize.
|
||||||
|
// The actual limits are checked in the xdg_toplevel::configure handler.
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
|
||||||
|
int* width, int* height)
|
||||||
{
|
{
|
||||||
_glfwPlatformGetWindowSize(window, width, height);
|
_glfwPlatformGetWindowSize(window, width, height);
|
||||||
*width *= window->wl.scale;
|
*width *= window->wl.scale;
|
||||||
@@ -1040,9 +1072,9 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|||||||
*yscale = (float) window->wl.scale;
|
*yscale = (float) window->wl.scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return 0.5;
|
return ms_to_monotonic_t(500ll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
@@ -1096,7 +1128,7 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||||||
window->wl.visible = false;
|
window->wl.visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
static bool notified = false;
|
static bool notified = false;
|
||||||
@@ -1107,7 +1139,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
// TODO: Use an actual Wayland API to implement this when one becomes available
|
// TODO: Use an actual Wayland API to implement this when one becomes available
|
||||||
static char tty[L_ctermid + 1];
|
static char tty[L_ctermid + 1];
|
||||||
@@ -1120,7 +1152,7 @@ int _glfwPlatformWindowBell(_GLFWwindow* window)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Focusing a window requires user interaction");
|
"Wayland: Focusing a window requires user interaction");
|
||||||
@@ -1128,9 +1160,9 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
||||||
_GLFWmonitor* monitor,
|
_GLFWmonitor* monitor,
|
||||||
int xpos, int ypos,
|
int xpos UNUSED, int ypos UNUSED,
|
||||||
int width, int height,
|
int width UNUSED, int height UNUSED,
|
||||||
int refreshRate)
|
int refreshRate UNUSED)
|
||||||
{
|
{
|
||||||
setFullscreen(window, monitor, monitor != NULL);
|
setFullscreen(window, monitor, monitor != NULL);
|
||||||
_glfwInputWindowMonitor(window, monitor);
|
_glfwInputWindowMonitor(window, monitor);
|
||||||
@@ -1141,12 +1173,12 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
|||||||
return _glfw.wl.keyboardFocus == window;
|
return _glfw.wl.keyboardFocus == window;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowIconified(_GLFWwindow* window)
|
int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
// xdg-shell doesn’t give any way to request whether a surface is
|
// xdg-shell doesn’t give any way to request whether a surface is
|
||||||
// iconified.
|
// iconified.
|
||||||
@@ -1173,7 +1205,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||||||
return window->wl.transparent;
|
return window->wl.transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
@@ -1191,19 +1223,19 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Window attribute setting not implemented yet");
|
"Wayland: Window attribute setting not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
|
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return 1.f;
|
return 1.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1215,11 +1247,11 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
double timeout = wl_display_dispatch_pending(_glfw.wl.display) > 0 ? 0 : -1;
|
monotonic_t timeout = wl_display_dispatch_pending(_glfw.wl.display) > 0 ? 0 : -1;
|
||||||
handleEvents(timeout);
|
handleEvents(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout)
|
||||||
{
|
{
|
||||||
if (wl_display_dispatch_pending(_glfw.wl.display) > 0) timeout = 0;
|
if (wl_display_dispatch_pending(_glfw.wl.display) > 0) timeout = 0;
|
||||||
handleEvents(timeout);
|
handleEvents(timeout);
|
||||||
@@ -1227,7 +1259,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
while (write(_glfw.wl.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR);
|
wakeupEventLoop(&_glfw.wl.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@@ -1251,24 +1283,24 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode UNUSED)
|
||||||
{
|
{
|
||||||
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
_glfwPlatformSetCursor(window, window->wl.currentCursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
const char* _glfwPlatformGetNativeKeyName(int native_key)
|
||||||
{
|
{
|
||||||
return glfw_xkb_keysym_name(scancode);
|
return glfw_xkb_keysym_name(native_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetNativeKeyForKey(int key)
|
||||||
{
|
{
|
||||||
return glfw_xkb_sym_for_key(key);
|
return glfw_xkb_sym_for_key(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image,
|
const GLFWimage* image,
|
||||||
int xhot, int yhot, int count)
|
int xhot, int yhot, int count UNUSED)
|
||||||
{
|
{
|
||||||
cursor->wl.buffer = createShmBuffer(image);
|
cursor->wl.buffer = createShmBuffer(image);
|
||||||
if (!cursor->wl.buffer)
|
if (!cursor->wl.buffer)
|
||||||
@@ -1302,11 +1334,11 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handleRelativeMotion(void* data,
|
static void handleRelativeMotion(void* data,
|
||||||
struct zwp_relative_pointer_v1* pointer,
|
struct zwp_relative_pointer_v1* pointer UNUSED,
|
||||||
uint32_t timeHi,
|
uint32_t timeHi UNUSED,
|
||||||
uint32_t timeLo,
|
uint32_t timeLo UNUSED,
|
||||||
wl_fixed_t dx,
|
wl_fixed_t dx UNUSED,
|
||||||
wl_fixed_t dy,
|
wl_fixed_t dy UNUSED,
|
||||||
wl_fixed_t dxUnaccel,
|
wl_fixed_t dxUnaccel,
|
||||||
wl_fixed_t dyUnaccel)
|
wl_fixed_t dyUnaccel)
|
||||||
{
|
{
|
||||||
@@ -1324,8 +1356,8 @@ static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
|
|||||||
handleRelativeMotion
|
handleRelativeMotion
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handleLocked(void* data,
|
static void handleLocked(void* data UNUSED,
|
||||||
struct zwp_locked_pointer_v1* lockedPointer)
|
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1343,10 +1375,10 @@ static void unlockPointer(_GLFWwindow* window)
|
|||||||
window->wl.pointerLock.lockedPointer = NULL;
|
window->wl.pointerLock.lockedPointer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lockPointer(_GLFWwindow* window);
|
static void lockPointer(_GLFWwindow* window UNUSED);
|
||||||
|
|
||||||
static void handleUnlocked(void* data,
|
static void handleUnlocked(void* data UNUSED,
|
||||||
struct zwp_locked_pointer_v1* lockedPointer)
|
struct zwp_locked_pointer_v1* lockedPointer UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1450,8 +1482,8 @@ static void send_text(char *text, int fd)
|
|||||||
{
|
{
|
||||||
if (text) {
|
if (text) {
|
||||||
size_t len = strlen(text), pos = 0;
|
size_t len = strlen(text), pos = 0;
|
||||||
double start = glfwGetTime();
|
monotonic_t start = glfwGetTime();
|
||||||
while (pos < len && glfwGetTime() - start < 2.0) {
|
while (pos < len && glfwGetTime() - start < s_to_monotonic_t(2ll)) {
|
||||||
ssize_t ret = write(fd, text + pos, len - pos);
|
ssize_t ret = write(fd, text + pos, len - pos);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EAGAIN || errno == EINTR) continue;
|
if (errno == EAGAIN || errno == EINTR) continue;
|
||||||
@@ -1468,23 +1500,24 @@ static void send_text(char *text, int fd)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _glfwSendClipboardText(void *data, struct wl_data_source *data_source, const char *mime_type, int fd) {
|
static void _glfwSendClipboardText(void *data UNUSED, struct wl_data_source *data_source UNUSED, const char *mime_type UNUSED, int fd) {
|
||||||
send_text(_glfw.wl.clipboardString, fd);
|
send_text(_glfw.wl.clipboardString, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _glfwSendPrimarySelectionText(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source,
|
static void _glfwSendPrimarySelectionText(void *data UNUSED, struct zwp_primary_selection_source_v1 *primary_selection_source UNUSED,
|
||||||
const char *mime_type, int fd) {
|
const char *mime_type UNUSED, int fd) {
|
||||||
send_text(_glfw.wl.primarySelectionString, fd);
|
send_text(_glfw.wl.primarySelectionString, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* read_offer_string(int data_pipe) {
|
static char* read_offer_string(int data_pipe, size_t *data_sz) {
|
||||||
wl_display_flush(_glfw.wl.display);
|
wl_display_flush(_glfw.wl.display);
|
||||||
size_t sz = 0, capacity = 0;
|
size_t capacity = 0;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
*data_sz = 0;
|
||||||
struct pollfd fds;
|
struct pollfd fds;
|
||||||
fds.fd = data_pipe;
|
fds.fd = data_pipe;
|
||||||
fds.events = POLLIN;
|
fds.events = POLLIN;
|
||||||
double start = glfwGetTime();
|
monotonic_t start = glfwGetTime();
|
||||||
#define bail(...) { \
|
#define bail(...) { \
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR, __VA_ARGS__); \
|
_glfwInputError(GLFW_PLATFORM_ERROR, __VA_ARGS__); \
|
||||||
free(buf); buf = NULL; \
|
free(buf); buf = NULL; \
|
||||||
@@ -1492,7 +1525,7 @@ static char* read_offer_string(int data_pipe) {
|
|||||||
return NULL; \
|
return NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
while (glfwGetTime() - start < 2) {
|
while (glfwGetTime() - start < s_to_monotonic_t(2ll)) {
|
||||||
int ret = poll(&fds, 1, 2000);
|
int ret = poll(&fds, 1, 2000);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
@@ -1501,20 +1534,20 @@ static char* read_offer_string(int data_pipe) {
|
|||||||
if (!ret) {
|
if (!ret) {
|
||||||
bail("Wayland: Failed to read clipboard data from pipe (timed out)");
|
bail("Wayland: Failed to read clipboard data from pipe (timed out)");
|
||||||
}
|
}
|
||||||
if (capacity <= sz || capacity - sz <= 64) {
|
if (capacity <= *data_sz || capacity - *data_sz <= 64) {
|
||||||
capacity += 4096;
|
capacity += 4096;
|
||||||
buf = realloc(buf, capacity);
|
buf = realloc(buf, capacity);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
bail("Wayland: Failed to allocate memory to read clipboard data");
|
bail("Wayland: Failed to allocate memory to read clipboard data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = read(data_pipe, buf + sz, capacity - sz - 1);
|
ret = read(data_pipe, buf + *data_sz, capacity - *data_sz - 1);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue;
|
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue;
|
||||||
bail("Wayland: Failed to read clipboard data from pipe with error: %s", strerror(errno));
|
bail("Wayland: Failed to read clipboard data from pipe with error: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
if (ret == 0) { close(data_pipe); buf[sz] = 0; return buf; }
|
if (ret == 0) { close(data_pipe); buf[*data_sz] = 0; return buf; }
|
||||||
sz += ret;
|
*data_sz += ret;
|
||||||
start = glfwGetTime();
|
start = glfwGetTime();
|
||||||
}
|
}
|
||||||
bail("Wayland: Failed to read clipboard data from pipe (timed out)");
|
bail("Wayland: Failed to read clipboard data from pipe (timed out)");
|
||||||
@@ -1527,62 +1560,66 @@ static char* read_primary_selection_offer(struct zwp_primary_selection_offer_v1
|
|||||||
if (pipe2(pipefd, O_CLOEXEC) != 0) return NULL;
|
if (pipe2(pipefd, O_CLOEXEC) != 0) return NULL;
|
||||||
zwp_primary_selection_offer_v1_receive(primary_selection_offer, mime, pipefd[1]);
|
zwp_primary_selection_offer_v1_receive(primary_selection_offer, mime, pipefd[1]);
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
return read_offer_string(pipefd[0]);
|
size_t sz = 0;
|
||||||
|
return read_offer_string(pipefd[0], &sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* read_data_offer(struct wl_data_offer *data_offer, const char *mime) {
|
static char* read_data_offer(struct wl_data_offer *data_offer, const char *mime, size_t *sz) {
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
if (pipe2(pipefd, O_CLOEXEC) != 0) return NULL;
|
if (pipe2(pipefd, O_CLOEXEC) != 0) return NULL;
|
||||||
wl_data_offer_receive(data_offer, mime, pipefd[1]);
|
wl_data_offer_receive(data_offer, mime, pipefd[1]);
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
return read_offer_string(pipefd[0]);
|
return read_offer_string(pipefd[0], sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_source_canceled(void *data, struct wl_data_source *wl_data_source) {
|
static void data_source_canceled(void *data UNUSED, struct wl_data_source *wl_data_source) {
|
||||||
if (_glfw.wl.dataSourceForClipboard == wl_data_source)
|
if (_glfw.wl.dataSourceForClipboard == wl_data_source)
|
||||||
_glfw.wl.dataSourceForClipboard = NULL;
|
_glfw.wl.dataSourceForClipboard = NULL;
|
||||||
wl_data_source_destroy(wl_data_source);
|
wl_data_source_destroy(wl_data_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void primary_selection_source_canceled(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source) {
|
static void primary_selection_source_canceled(void *data UNUSED, struct zwp_primary_selection_source_v1 *primary_selection_source) {
|
||||||
if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source)
|
if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source)
|
||||||
_glfw.wl.dataSourceForPrimarySelection = NULL;
|
_glfw.wl.dataSourceForPrimarySelection = NULL;
|
||||||
zwp_primary_selection_source_v1_destroy(primary_selection_source);
|
zwp_primary_selection_source_v1_destroy(primary_selection_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_source_target(void *data, struct wl_data_source *wl_data_source, const char* mime) {
|
static void data_source_target(void *data UNUSED, struct wl_data_source *wl_data_source UNUSED, const char* mime UNUSED) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct wl_data_source_listener data_source_listener = {
|
static const struct wl_data_source_listener data_source_listener = {
|
||||||
.send = _glfwSendClipboardText,
|
.send = _glfwSendClipboardText,
|
||||||
.cancelled = data_source_canceled,
|
.cancelled = data_source_canceled,
|
||||||
.target = data_source_target,
|
.target = data_source_target,
|
||||||
};
|
};
|
||||||
|
|
||||||
const static struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
|
static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
|
||||||
.send = _glfwSendPrimarySelectionText,
|
.send = _glfwSendPrimarySelectionText,
|
||||||
.cancelled = primary_selection_source_canceled,
|
.cancelled = primary_selection_source_canceled,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
destroy_data_offer(_GLFWWaylandDataOffer *offer) {
|
||||||
|
if (offer->id) {
|
||||||
|
if (offer->is_primary) zwp_primary_selection_offer_v1_destroy(offer->id);
|
||||||
|
else wl_data_offer_destroy(offer->id);
|
||||||
|
}
|
||||||
|
if (offer->mimes) {
|
||||||
|
for (size_t i = 0; i < offer->mimes_count; i++) free((char*)offer->mimes[i]);
|
||||||
|
free(offer->mimes);
|
||||||
|
}
|
||||||
|
memset(offer, 0, sizeof(_GLFWWaylandDataOffer));
|
||||||
|
}
|
||||||
|
|
||||||
static void prune_unclaimed_data_offers(void) {
|
static void prune_unclaimed_data_offers(void) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id && !_glfw.wl.dataOffers[i].offer_type) {
|
if (_glfw.wl.dataOffers[i].id && !_glfw.wl.dataOffers[i].offer_type) {
|
||||||
wl_data_offer_destroy(_glfw.wl.dataOffers[i].id);
|
destroy_data_offer(&_glfw.wl.dataOffers[i]);
|
||||||
memset(_glfw.wl.dataOffers + i, 0, sizeof(_glfw.wl.dataOffers[0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prune_unclaimed_primary_selection_offers(void) {
|
static void mark_selection_offer(void *data UNUSED, struct wl_data_device *data_device UNUSED, struct wl_data_offer *data_offer)
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
|
|
||||||
if (_glfw.wl.primarySelectionOffers[i].id && !_glfw.wl.dataOffers[i].offer_type) {
|
|
||||||
zwp_primary_selection_offer_v1_destroy(_glfw.wl.primarySelectionOffers[i].id);
|
|
||||||
memset(_glfw.wl.primarySelectionOffers + i, 0, sizeof(_glfw.wl.primarySelectionOffers[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mark_selection_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *data_offer)
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id == data_offer) {
|
if (_glfw.wl.dataOffers[i].id == data_offer) {
|
||||||
@@ -1594,30 +1631,37 @@ static void mark_selection_offer(void *data, struct wl_data_device *data_device,
|
|||||||
prune_unclaimed_data_offers();
|
prune_unclaimed_data_offers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1* primary_selection_device,
|
static void mark_primary_selection_offer(void *data UNUSED, struct zwp_primary_selection_device_v1* primary_selection_device UNUSED,
|
||||||
struct zwp_primary_selection_offer_v1 *primary_selection_offer) {
|
struct zwp_primary_selection_offer_v1 *primary_selection_offer) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.primarySelectionOffers[i].id == primary_selection_offer) {
|
if (_glfw.wl.dataOffers[i].id == primary_selection_offer) {
|
||||||
_glfw.wl.primarySelectionOffers[i].offer_type = PRIMARY_SELECTION;
|
_glfw.wl.dataOffers[i].offer_type = PRIMARY_SELECTION;
|
||||||
} else if (_glfw.wl.primarySelectionOffers[i].offer_type == PRIMARY_SELECTION) {
|
} else if (_glfw.wl.dataOffers[i].offer_type == PRIMARY_SELECTION) {
|
||||||
_glfw.wl.primarySelectionOffers[i].offer_type = EXPIRED; // previous selection offer
|
_glfw.wl.dataOffers[i].offer_type = EXPIRED; // previous selection offer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prune_unclaimed_primary_selection_offers();
|
prune_unclaimed_data_offers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_offer_mimetype(struct _GLFWWaylandDataOffer* offer, const char* mime) {
|
static void
|
||||||
if (strcmp(mime, "text/plain;charset=utf-8") == 0)
|
set_offer_mimetype(_GLFWWaylandDataOffer* offer, const char* mime) {
|
||||||
offer->mime = "text/plain;charset=utf-8";
|
if (strcmp(mime, "text/plain;charset=utf-8") == 0) {
|
||||||
else if (!offer->mime && strcmp(mime, "text/plain") == 0)
|
offer->plain_text_mime = "text/plain;charset=utf-8";
|
||||||
offer->mime = "text/plain";
|
} else if (!offer->plain_text_mime && strcmp(mime, "text/plain")) {
|
||||||
else if (strcmp(mime, clipboard_mime()) == 0)
|
offer->plain_text_mime = "text/plain";
|
||||||
offer->is_self_offer = 1;
|
}
|
||||||
else if (strcmp(mime, URI_LIST_MIME) == 0)
|
if (strcmp(mime, clipboard_mime()) == 0) {
|
||||||
offer->has_uri_list = 1;
|
offer->is_self_offer = true;
|
||||||
|
}
|
||||||
|
if (!offer->mimes || offer->mimes_count >= offer->mimes_capacity - 1) {
|
||||||
|
offer->mimes = realloc(offer->mimes, sizeof(char*) * (offer->mimes_capacity + 64));
|
||||||
|
if (offer->mimes) offer->mimes_capacity += 64;
|
||||||
|
else return;
|
||||||
|
}
|
||||||
|
offer->mimes[offer->mimes_count++] = _glfw_strdup(mime);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_offer_mimetype(void *data, struct wl_data_offer* id, const char *mime) {
|
static void handle_offer_mimetype(void *data UNUSED, struct wl_data_offer* id, const char *mime) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id == id) {
|
if (_glfw.wl.dataOffers[i].id == id) {
|
||||||
set_offer_mimetype(&_glfw.wl.dataOffers[i], mime);
|
set_offer_mimetype(&_glfw.wl.dataOffers[i], mime);
|
||||||
@@ -1626,16 +1670,16 @@ static void handle_offer_mimetype(void *data, struct wl_data_offer* id, const ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_primary_selection_offer_mimetype(void *data, struct zwp_primary_selection_offer_v1* id, const char *mime) {
|
static void handle_primary_selection_offer_mimetype(void *data UNUSED, struct zwp_primary_selection_offer_v1* id, const char *mime) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.primarySelectionOffers[i].id == id) {
|
if (_glfw.wl.dataOffers[i].id == id) {
|
||||||
set_offer_mimetype((struct _GLFWWaylandDataOffer*)&_glfw.wl.primarySelectionOffers[i], mime);
|
set_offer_mimetype((_GLFWWaylandDataOffer*)&_glfw.wl.dataOffers[i], mime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_offer_source_actions(void *data, struct wl_data_offer* id, uint32_t actions) {
|
static void data_offer_source_actions(void *data UNUSED, struct wl_data_offer* id, uint32_t actions) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id == id) {
|
if (_glfw.wl.dataOffers[i].id == id) {
|
||||||
_glfw.wl.dataOffers[i].source_actions = actions;
|
_glfw.wl.dataOffers[i].source_actions = actions;
|
||||||
@@ -1644,7 +1688,7 @@ static void data_offer_source_actions(void *data, struct wl_data_offer* id, uint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_offer_action(void *data, struct wl_data_offer* id, uint32_t action) {
|
static void data_offer_action(void *data UNUSED, struct wl_data_offer* id, uint32_t action) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id == id) {
|
if (_glfw.wl.dataOffers[i].id == id) {
|
||||||
_glfw.wl.dataOffers[i].dnd_action = action;
|
_glfw.wl.dataOffers[i].dnd_action = action;
|
||||||
@@ -1664,7 +1708,8 @@ static const struct zwp_primary_selection_offer_v1_listener primary_selection_of
|
|||||||
.offer = handle_primary_selection_offer_mimetype,
|
.offer = handle_primary_selection_offer_mimetype,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void handle_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id) {
|
static size_t
|
||||||
|
handle_data_offer_generic(void *id, bool is_primary) {
|
||||||
size_t smallest_idx = SIZE_MAX, pos = 0;
|
size_t smallest_idx = SIZE_MAX, pos = 0;
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].idx && _glfw.wl.dataOffers[i].idx < smallest_idx) {
|
if (_glfw.wl.dataOffers[i].idx && _glfw.wl.dataOffers[i].idx < smallest_idx) {
|
||||||
@@ -1672,47 +1717,48 @@ static void handle_data_offer(void *data, struct wl_data_device *wl_data_device,
|
|||||||
pos = i;
|
pos = i;
|
||||||
}
|
}
|
||||||
if (_glfw.wl.dataOffers[i].id == NULL) {
|
if (_glfw.wl.dataOffers[i].id == NULL) {
|
||||||
_glfw.wl.dataOffers[i].id = id;
|
pos = i;
|
||||||
_glfw.wl.dataOffers[i].idx = ++_glfw.wl.dataOffersCounter;
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_glfw.wl.dataOffers[pos].id) wl_data_offer_destroy(_glfw.wl.dataOffers[pos].id);
|
if (_glfw.wl.dataOffers[pos].id) destroy_data_offer(&_glfw.wl.dataOffers[pos]);
|
||||||
memset(_glfw.wl.dataOffers + pos, 0, sizeof(_glfw.wl.dataOffers[0]));
|
|
||||||
_glfw.wl.dataOffers[pos].id = id;
|
|
||||||
_glfw.wl.dataOffers[pos].idx = ++_glfw.wl.dataOffersCounter;
|
|
||||||
end:
|
end:
|
||||||
|
_glfw.wl.dataOffers[pos].id = id;
|
||||||
|
_glfw.wl.dataOffers[pos].is_primary = is_primary;
|
||||||
|
_glfw.wl.dataOffers[pos].idx = ++_glfw.wl.dataOffersCounter;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_data_offer(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, struct wl_data_offer *id) {
|
||||||
|
handle_data_offer_generic(id, false);
|
||||||
wl_data_offer_add_listener(id, &data_offer_listener, NULL);
|
wl_data_offer_add_listener(id, &data_offer_listener, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id) {
|
static void handle_primary_selection_offer(void *data UNUSED, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1 UNUSED, struct zwp_primary_selection_offer_v1 *id) {
|
||||||
size_t smallest_idx = SIZE_MAX, pos = 0;
|
handle_data_offer_generic(id, true);
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
|
|
||||||
if (_glfw.wl.primarySelectionOffers[i].idx && _glfw.wl.primarySelectionOffers[i].idx < smallest_idx) {
|
|
||||||
smallest_idx = _glfw.wl.primarySelectionOffers[i].idx;
|
|
||||||
pos = i;
|
|
||||||
}
|
|
||||||
if (_glfw.wl.primarySelectionOffers[i].id == NULL) {
|
|
||||||
_glfw.wl.primarySelectionOffers[i].id = id;
|
|
||||||
_glfw.wl.primarySelectionOffers[i].idx = ++_glfw.wl.primarySelectionOffersCounter;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_glfw.wl.primarySelectionOffers[pos].id) zwp_primary_selection_offer_v1_destroy(_glfw.wl.primarySelectionOffers[pos].id);
|
|
||||||
memset(_glfw.wl.primarySelectionOffers + pos, 0, sizeof(_glfw.wl.primarySelectionOffers[0]));
|
|
||||||
_glfw.wl.primarySelectionOffers[pos].id = id;
|
|
||||||
_glfw.wl.primarySelectionOffers[pos].idx = ++_glfw.wl.primarySelectionOffersCounter;
|
|
||||||
end:
|
|
||||||
zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, NULL);
|
zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drag_enter(void *data, struct wl_data_device *wl_data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) {
|
static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t serial, struct wl_surface *surface, wl_fixed_t x UNUSED, wl_fixed_t y UNUSED, struct wl_data_offer *id) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id == id) {
|
_GLFWWaylandDataOffer *d = _glfw.wl.dataOffers + i;
|
||||||
_glfw.wl.dataOffers[i].offer_type = DRAG_AND_DROP;
|
if (d->id == id) {
|
||||||
_glfw.wl.dataOffers[i].surface = surface;
|
d->offer_type = DRAG_AND_DROP;
|
||||||
const char *mime = _glfw.wl.dataOffers[i].has_uri_list ? URI_LIST_MIME : NULL;
|
d->surface = surface;
|
||||||
wl_data_offer_accept(id, serial, mime);
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
|
int format_priority = 0;
|
||||||
|
while (window)
|
||||||
|
{
|
||||||
|
if (window->wl.surface == surface) {
|
||||||
|
for (size_t x = 0; x < d->mimes_count; x++) {
|
||||||
|
int prio = _glfwInputDrop(window, d->mimes[x], NULL, 0);
|
||||||
|
if (prio > format_priority) d->mime_for_drop = d->mimes[x];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
window = window->next;
|
||||||
|
}
|
||||||
|
wl_data_offer_accept(id, serial, d->mime_for_drop);
|
||||||
} else if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
} else if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
||||||
_glfw.wl.dataOffers[i].offer_type = EXPIRED; // previous drag offer
|
_glfw.wl.dataOffers[i].offer_type = EXPIRED; // previous drag offer
|
||||||
}
|
}
|
||||||
@@ -1720,51 +1766,46 @@ static void drag_enter(void *data, struct wl_data_device *wl_data_device, uint32
|
|||||||
prune_unclaimed_data_offers();
|
prune_unclaimed_data_offers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drag_leave(void *data, struct wl_data_device *wl_data_device) {
|
static void drag_leave(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
||||||
wl_data_offer_destroy(_glfw.wl.dataOffers[i].id);
|
destroy_data_offer(&_glfw.wl.dataOffers[i]);
|
||||||
memset(_glfw.wl.dataOffers + i, 0, sizeof(_glfw.wl.dataOffers[0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drop(void *data, struct wl_data_device *wl_data_device) {
|
static void drop(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
|
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP && _glfw.wl.dataOffers[i].mime_for_drop) {
|
||||||
char *uri_list = read_data_offer(_glfw.wl.dataOffers[i].id, URI_LIST_MIME);
|
size_t sz = 0;
|
||||||
if (uri_list) {
|
char *data = read_data_offer(_glfw.wl.dataOffers[i].id, _glfw.wl.dataOffers[i].mime_for_drop, &sz);
|
||||||
wl_data_offer_finish(_glfw.wl.dataOffers[i].id);
|
if (data) {
|
||||||
int count;
|
// We dont do finish as this requires version 3 for wl_data_device_manager
|
||||||
char** paths = parseUriList(data, &count);
|
// which then requires more work with calling set_actions for drag and drop to function
|
||||||
|
// wl_data_offer_finish(_glfw.wl.dataOffers[i].id);
|
||||||
|
|
||||||
_GLFWwindow* window = _glfw.windowListHead;
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
while (window)
|
while (window)
|
||||||
{
|
{
|
||||||
if (window->wl.surface == _glfw.wl.dataOffers[i].surface) {
|
if (window->wl.surface == _glfw.wl.dataOffers[i].surface) {
|
||||||
_glfwInputDrop(window, count, (const char**) paths);
|
_glfwInputDrop(window, _glfw.wl.dataOffers[i].mime_for_drop, data, sz);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
window = window->next;
|
window = window->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(data);
|
||||||
for (int k = 0; k < count; k++)
|
|
||||||
free(paths[k]);
|
|
||||||
free(paths);
|
|
||||||
free(uri_list);
|
|
||||||
}
|
}
|
||||||
wl_data_offer_destroy(_glfw.wl.dataOffers[i].id);
|
destroy_data_offer(&_glfw.wl.dataOffers[i]);
|
||||||
memset(_glfw.wl.dataOffers + i, 0, sizeof(_glfw.wl.dataOffers[0]));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void motion(void *data, struct wl_data_device *wl_data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y) {
|
static void motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t time UNUSED, wl_fixed_t x UNUSED, wl_fixed_t y UNUSED) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const static struct wl_data_device_listener data_device_listener = {
|
static const struct wl_data_device_listener data_device_listener = {
|
||||||
.data_offer = handle_data_offer,
|
.data_offer = handle_data_offer,
|
||||||
.selection = mark_selection_offer,
|
.selection = mark_selection_offer,
|
||||||
.enter = drag_enter,
|
.enter = drag_enter,
|
||||||
@@ -1773,7 +1814,7 @@ const static struct wl_data_device_listener data_device_listener = {
|
|||||||
.leave = drag_leave,
|
.leave = drag_leave,
|
||||||
};
|
};
|
||||||
|
|
||||||
const static struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
|
static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
|
||||||
.data_offer = handle_primary_selection_offer,
|
.data_offer = handle_primary_selection_offer,
|
||||||
.selection = mark_primary_selection_offer,
|
.selection = mark_primary_selection_offer,
|
||||||
};
|
};
|
||||||
@@ -1824,7 +1865,7 @@ static inline bool _glfwEnsureDataDevice(void) {
|
|||||||
if (!_glfw.wl.dataDevice)
|
if (!_glfw.wl.dataDevice)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"Wayland: Cannot use clipboard, failed to create data device");
|
"Wayland: Cannot use clipboard, failed to create data device");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1853,17 +1894,19 @@ void _glfwPlatformSetClipboardString(const char* string)
|
|||||||
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "STRING");
|
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "STRING");
|
||||||
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "UTF8_STRING");
|
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "UTF8_STRING");
|
||||||
struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
|
struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
|
||||||
const static struct wl_callback_listener clipboard_copy_callback_listener = {.done = clipboard_copy_callback_done};
|
static const struct wl_callback_listener clipboard_copy_callback_listener = {.done = clipboard_copy_callback_done};
|
||||||
wl_callback_add_listener(callback, &clipboard_copy_callback_listener, _glfw.wl.dataSourceForClipboard);
|
wl_callback_add_listener(callback, &clipboard_copy_callback_listener, _glfw.wl.dataSourceForClipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetClipboardString(void)
|
const char* _glfwPlatformGetClipboardString(void)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.dataOffers[i].id && _glfw.wl.dataOffers[i].mime && _glfw.wl.dataOffers[i].offer_type == CLIPBOARD) {
|
_GLFWWaylandDataOffer *d = _glfw.wl.dataOffers + i;
|
||||||
if (_glfw.wl.dataOffers[i].is_self_offer) return _glfw.wl.clipboardString;
|
if (d->id && d->offer_type == CLIPBOARD && d->plain_text_mime) {
|
||||||
|
if (d->is_self_offer) return _glfw.wl.clipboardString;
|
||||||
free(_glfw.wl.pasteString);
|
free(_glfw.wl.pasteString);
|
||||||
_glfw.wl.pasteString = read_data_offer(_glfw.wl.dataOffers[i].id, _glfw.wl.dataOffers[i].mime);
|
size_t sz = 0;
|
||||||
|
_glfw.wl.pasteString = read_data_offer(d->id, d->plain_text_mime, &sz);
|
||||||
return _glfw.wl.pasteString;
|
return _glfw.wl.pasteString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1902,7 +1945,7 @@ void _glfwPlatformSetPrimarySelectionString(const char* string)
|
|||||||
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING");
|
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING");
|
||||||
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING");
|
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING");
|
||||||
struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
|
struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
|
||||||
const static struct wl_callback_listener primary_selection_copy_callback_listener = {.done = primary_selection_copy_callback_done};
|
static const struct wl_callback_listener primary_selection_copy_callback_listener = {.done = primary_selection_copy_callback_done};
|
||||||
wl_callback_add_listener(callback, &primary_selection_copy_callback_listener, _glfw.wl.dataSourceForPrimarySelection);
|
wl_callback_add_listener(callback, &primary_selection_copy_callback_listener, _glfw.wl.dataSourceForPrimarySelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1910,13 +1953,14 @@ const char* _glfwPlatformGetPrimarySelectionString(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.wl.dataSourceForPrimarySelection != NULL) return _glfw.wl.primarySelectionString;
|
if (_glfw.wl.dataSourceForPrimarySelection != NULL) return _glfw.wl.primarySelectionString;
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
|
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
|
||||||
if (_glfw.wl.primarySelectionOffers[i].id && _glfw.wl.primarySelectionOffers[i].mime && _glfw.wl.primarySelectionOffers[i].offer_type == PRIMARY_SELECTION) {
|
_GLFWWaylandDataOffer *d = _glfw.wl.dataOffers + i;
|
||||||
if (_glfw.wl.primarySelectionOffers[i].is_self_offer) {
|
if (d->id && d->is_primary && d->offer_type == PRIMARY_SELECTION && d->plain_text_mime) {
|
||||||
|
if (d->is_self_offer) {
|
||||||
return _glfw.wl.primarySelectionString;
|
return _glfw.wl.primarySelectionString;
|
||||||
}
|
}
|
||||||
free(_glfw.wl.pasteString);
|
free(_glfw.wl.pasteString);
|
||||||
_glfw.wl.pasteString = read_primary_selection_offer(_glfw.wl.primarySelectionOffers[i].id, _glfw.wl.primarySelectionOffers[i].mime);
|
_glfw.wl.pasteString = read_primary_selection_offer(d->id, d->plain_text_mime);
|
||||||
return _glfw.wl.pasteString;
|
return _glfw.wl.pasteString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1992,7 +2036,7 @@ _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time) {
|
frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time UNUSED) {
|
||||||
_GLFWwindow* window = (_GLFWwindow*) data;
|
_GLFWwindow* window = (_GLFWwindow*) data;
|
||||||
if (callback == window->wl.frameCallbackData.current_wl_callback) {
|
if (callback == window->wl.frameCallbackData.current_wl_callback) {
|
||||||
window->wl.frameCallbackData.callback(window->wl.frameCallbackData.id);
|
window->wl.frameCallbackData.callback(window->wl.frameCallbackData.id);
|
||||||
@@ -2001,6 +2045,7 @@ frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time) {
|
|||||||
wl_callback_destroy(callback);
|
wl_callback_destroy(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW native API //////
|
////// GLFW native API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -2018,7 +2063,7 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
|
|||||||
return window->wl.surface;
|
return window->wl.surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) {
|
GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) {
|
||||||
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
189
glfw/x11_init.c
vendored
189
glfw/x11_init.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 X11 - www.glfw.org
|
// GLFW 3.4 X11 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@@ -46,10 +48,9 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
|
|||||||
unsigned long atomCount,
|
unsigned long atomCount,
|
||||||
const char* atomName)
|
const char* atomName)
|
||||||
{
|
{
|
||||||
unsigned long i;
|
|
||||||
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
|
||||||
|
|
||||||
for (i = 0; i < atomCount; i++)
|
for (unsigned long i = 0; i < atomCount; i++)
|
||||||
{
|
{
|
||||||
if (supportedAtoms[i] == atom)
|
if (supportedAtoms[i] == atom)
|
||||||
return atom;
|
return atom;
|
||||||
@@ -62,18 +63,12 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
|
|||||||
//
|
//
|
||||||
static void detectEWMH(void)
|
static void detectEWMH(void)
|
||||||
{
|
{
|
||||||
|
// First we read the _NET_SUPPORTING_WM_CHECK property on the root window
|
||||||
Window* windowFromRoot = NULL;
|
Window* windowFromRoot = NULL;
|
||||||
Window* windowFromChild = NULL;
|
|
||||||
|
|
||||||
// First we need a couple of atoms
|
|
||||||
const Atom supportingWmCheck =
|
|
||||||
XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
|
|
||||||
const Atom wmSupported =
|
|
||||||
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
|
|
||||||
|
|
||||||
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
|
||||||
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
supportingWmCheck,
|
_glfw.x11.NET_SUPPORTING_WM_CHECK,
|
||||||
XA_WINDOW,
|
XA_WINDOW,
|
||||||
(unsigned char**) &windowFromRoot))
|
(unsigned char**) &windowFromRoot))
|
||||||
{
|
{
|
||||||
@@ -82,10 +77,12 @@ static void detectEWMH(void)
|
|||||||
|
|
||||||
_glfwGrabErrorHandlerX11();
|
_glfwGrabErrorHandlerX11();
|
||||||
|
|
||||||
// It should be the ID of a child window (of the root)
|
// If it exists, it should be the XID of a top-level window
|
||||||
// Then we look for the same property on the child window
|
// Then we look for the same property on that window
|
||||||
|
|
||||||
|
Window* windowFromChild = NULL;
|
||||||
if (!_glfwGetWindowPropertyX11(*windowFromRoot,
|
if (!_glfwGetWindowPropertyX11(*windowFromRoot,
|
||||||
supportingWmCheck,
|
_glfw.x11.NET_SUPPORTING_WM_CHECK,
|
||||||
XA_WINDOW,
|
XA_WINDOW,
|
||||||
(unsigned char**) &windowFromChild))
|
(unsigned char**) &windowFromChild))
|
||||||
{
|
{
|
||||||
@@ -95,7 +92,7 @@ static void detectEWMH(void)
|
|||||||
|
|
||||||
_glfwReleaseErrorHandlerX11();
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
|
||||||
// It should be the ID of that same child window
|
// If the property exists, it should contain the XID of the window
|
||||||
if (*windowFromRoot != *windowFromChild)
|
if (*windowFromRoot != *windowFromChild)
|
||||||
{
|
{
|
||||||
XFree(windowFromRoot);
|
XFree(windowFromRoot);
|
||||||
@@ -107,18 +104,20 @@ static void detectEWMH(void)
|
|||||||
XFree(windowFromChild);
|
XFree(windowFromChild);
|
||||||
|
|
||||||
// We are now fairly sure that an EWMH-compliant window manager is running
|
// We are now fairly sure that an EWMH-compliant window manager is running
|
||||||
|
// We can now start querying the WM about what features it supports by
|
||||||
|
// looking in the _NET_SUPPORTED property on the root window
|
||||||
|
// It should contain a list of supported EWMH protocol and state atoms
|
||||||
|
|
||||||
Atom* supportedAtoms;
|
Atom* supportedAtoms = NULL;
|
||||||
unsigned long atomCount;
|
const unsigned long atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
|
||||||
|
_glfw.x11.NET_SUPPORTED,
|
||||||
// Now we need to check the _NET_SUPPORTED property of the root window
|
|
||||||
// It should be a list of supported WM protocol and state atoms
|
|
||||||
atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
|
|
||||||
wmSupported,
|
|
||||||
XA_ATOM,
|
XA_ATOM,
|
||||||
(unsigned char**) &supportedAtoms);
|
(unsigned char**) &supportedAtoms);
|
||||||
|
if (!supportedAtoms)
|
||||||
|
return;
|
||||||
|
|
||||||
// See which of the atoms we support that are supported by the WM
|
// See which of the atoms we support that are supported by the WM
|
||||||
|
|
||||||
_glfw.x11.NET_WM_STATE =
|
_glfw.x11.NET_WM_STATE =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
|
||||||
_glfw.x11.NET_WM_STATE_ABOVE =
|
_glfw.x11.NET_WM_STATE_ABOVE =
|
||||||
@@ -148,8 +147,7 @@ static void detectEWMH(void)
|
|||||||
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
_glfw.x11.NET_REQUEST_FRAME_EXTENTS =
|
||||||
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
|
||||||
|
|
||||||
if (supportedAtoms)
|
XFree(supportedAtoms);
|
||||||
XFree(supportedAtoms);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for and initialize supported X11 extensions
|
// Look for and initialize supported X11 extensions
|
||||||
@@ -159,14 +157,10 @@ static bool initExtensions(void)
|
|||||||
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
|
||||||
if (_glfw.x11.vidmode.handle)
|
if (_glfw.x11.vidmode.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
|
glfw_dlsym(_glfw.x11.vidmode.QueryExtension, _glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
|
||||||
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
|
glfw_dlsym(_glfw.x11.vidmode.GetGammaRamp, _glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
|
||||||
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
|
glfw_dlsym(_glfw.x11.vidmode.SetGammaRamp, _glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
|
||||||
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
|
glfw_dlsym(_glfw.x11.vidmode.GetGammaRampSize, _glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
|
||||||
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
|
|
||||||
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
|
|
||||||
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
|
|
||||||
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
|
|
||||||
|
|
||||||
_glfw.x11.vidmode.available =
|
_glfw.x11.vidmode.available =
|
||||||
XF86VidModeQueryExtension(_glfw.x11.display,
|
XF86VidModeQueryExtension(_glfw.x11.display,
|
||||||
@@ -181,10 +175,8 @@ static bool initExtensions(void)
|
|||||||
#endif
|
#endif
|
||||||
if (_glfw.x11.xi.handle)
|
if (_glfw.x11.xi.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
|
glfw_dlsym(_glfw.x11.xi.QueryVersion, _glfw.x11.xi.handle, "XIQueryVersion");
|
||||||
_glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
|
glfw_dlsym(_glfw.x11.xi.SelectEvents, _glfw.x11.xi.handle, "XISelectEvents");
|
||||||
_glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
|
|
||||||
_glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
|
|
||||||
|
|
||||||
if (XQueryExtension(_glfw.x11.display,
|
if (XQueryExtension(_glfw.x11.display,
|
||||||
"XInputExtension",
|
"XInputExtension",
|
||||||
@@ -211,42 +203,24 @@ static bool initExtensions(void)
|
|||||||
#endif
|
#endif
|
||||||
if (_glfw.x11.randr.handle)
|
if (_glfw.x11.randr.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
|
glfw_dlsym(_glfw.x11.randr.AllocGamma, _glfw.x11.randr.handle, "XRRAllocGamma");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
|
glfw_dlsym(_glfw.x11.randr.FreeGamma, _glfw.x11.randr.handle, "XRRFreeGamma");
|
||||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
glfw_dlsym(_glfw.x11.randr.FreeCrtcInfo, _glfw.x11.randr.handle, "XRRFreeCrtcInfo");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
glfw_dlsym(_glfw.x11.randr.FreeGamma, _glfw.x11.randr.handle, "XRRFreeGamma");
|
||||||
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
|
glfw_dlsym(_glfw.x11.randr.FreeOutputInfo, _glfw.x11.randr.handle, "XRRFreeOutputInfo");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
|
glfw_dlsym(_glfw.x11.randr.FreeScreenResources, _glfw.x11.randr.handle, "XRRFreeScreenResources");
|
||||||
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
|
glfw_dlsym(_glfw.x11.randr.GetCrtcGamma, _glfw.x11.randr.handle, "XRRGetCrtcGamma");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
|
glfw_dlsym(_glfw.x11.randr.GetCrtcGammaSize, _glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
|
||||||
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
|
glfw_dlsym(_glfw.x11.randr.GetCrtcInfo, _glfw.x11.randr.handle, "XRRGetCrtcInfo");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
|
glfw_dlsym(_glfw.x11.randr.GetOutputInfo, _glfw.x11.randr.handle, "XRRGetOutputInfo");
|
||||||
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
|
glfw_dlsym(_glfw.x11.randr.GetOutputPrimary, _glfw.x11.randr.handle, "XRRGetOutputPrimary");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
|
glfw_dlsym(_glfw.x11.randr.GetScreenResourcesCurrent, _glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
|
||||||
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
|
glfw_dlsym(_glfw.x11.randr.QueryExtension, _glfw.x11.randr.handle, "XRRQueryExtension");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
|
glfw_dlsym(_glfw.x11.randr.QueryVersion, _glfw.x11.randr.handle, "XRRQueryVersion");
|
||||||
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
|
glfw_dlsym(_glfw.x11.randr.SelectInput, _glfw.x11.randr.handle, "XRRSelectInput");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
|
glfw_dlsym(_glfw.x11.randr.SetCrtcConfig, _glfw.x11.randr.handle, "XRRSetCrtcConfig");
|
||||||
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
|
glfw_dlsym(_glfw.x11.randr.SetCrtcGamma, _glfw.x11.randr.handle, "XRRSetCrtcGamma");
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
|
glfw_dlsym(_glfw.x11.randr.UpdateConfiguration, _glfw.x11.randr.handle, "XRRUpdateConfiguration");
|
||||||
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
|
|
||||||
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
|
|
||||||
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
|
|
||||||
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
|
|
||||||
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
|
|
||||||
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
|
|
||||||
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
|
|
||||||
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
|
|
||||||
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
|
|
||||||
_glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
|
|
||||||
|
|
||||||
if (XRRQueryExtension(_glfw.x11.display,
|
if (XRRQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.randr.eventBase,
|
&_glfw.x11.randr.eventBase,
|
||||||
@@ -303,12 +277,9 @@ static bool initExtensions(void)
|
|||||||
#endif
|
#endif
|
||||||
if (_glfw.x11.xcursor.handle)
|
if (_glfw.x11.xcursor.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
|
glfw_dlsym(_glfw.x11.xcursor.ImageCreate, _glfw.x11.xcursor.handle, "XcursorImageCreate");
|
||||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
|
glfw_dlsym(_glfw.x11.xcursor.ImageDestroy, _glfw.x11.xcursor.handle, "XcursorImageDestroy");
|
||||||
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
|
glfw_dlsym(_glfw.x11.xcursor.ImageLoadCursor, _glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
|
||||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
|
|
||||||
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
|
|
||||||
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__CYGWIN__)
|
#if defined(__CYGWIN__)
|
||||||
@@ -318,12 +289,9 @@ static bool initExtensions(void)
|
|||||||
#endif
|
#endif
|
||||||
if (_glfw.x11.xinerama.handle)
|
if (_glfw.x11.xinerama.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
|
glfw_dlsym(_glfw.x11.xinerama.IsActive, _glfw.x11.xinerama.handle, "XineramaIsActive");
|
||||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
|
glfw_dlsym(_glfw.x11.xinerama.QueryExtension, _glfw.x11.xinerama.handle, "XineramaQueryExtension");
|
||||||
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
|
glfw_dlsym(_glfw.x11.xinerama.QueryScreens, _glfw.x11.xinerama.handle, "XineramaQueryScreens");
|
||||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
|
|
||||||
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
|
|
||||||
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
|
|
||||||
|
|
||||||
if (XineramaQueryExtension(_glfw.x11.display,
|
if (XineramaQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.xinerama.major,
|
&_glfw.x11.xinerama.major,
|
||||||
@@ -341,12 +309,9 @@ static bool initExtensions(void)
|
|||||||
#endif
|
#endif
|
||||||
if (_glfw.x11.xrender.handle)
|
if (_glfw.x11.xrender.handle)
|
||||||
{
|
{
|
||||||
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
|
glfw_dlsym(_glfw.x11.xrender.QueryExtension, _glfw.x11.xrender.handle, "XRenderQueryExtension");
|
||||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
|
glfw_dlsym(_glfw.x11.xrender.QueryVersion, _glfw.x11.xrender.handle, "XRenderQueryVersion");
|
||||||
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
|
glfw_dlsym(_glfw.x11.xrender.FindVisualFormat, _glfw.x11.xrender.handle, "XRenderFindVisualFormat");
|
||||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
|
|
||||||
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
|
|
||||||
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
|
|
||||||
|
|
||||||
if (XRenderQueryExtension(_glfw.x11.display,
|
if (XRenderQueryExtension(_glfw.x11.display,
|
||||||
&_glfw.x11.xrender.errorBase,
|
&_glfw.x11.xrender.errorBase,
|
||||||
@@ -387,9 +352,6 @@ static bool initExtensions(void)
|
|||||||
if (!glfw_xkb_update_x11_keyboard_id(&_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;
|
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return false;
|
||||||
|
|
||||||
// Detect whether an EWMH-conformant window manager is running
|
|
||||||
detectEWMH();
|
|
||||||
|
|
||||||
// String format atoms
|
// String format atoms
|
||||||
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
|
||||||
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
|
||||||
@@ -422,7 +384,6 @@ static bool initExtensions(void)
|
|||||||
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
_glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
|
||||||
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
|
_glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
|
||||||
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
_glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
|
||||||
_glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
|
|
||||||
|
|
||||||
// ICCCM, EWMH and Motif window property atoms
|
// ICCCM, EWMH and Motif window property atoms
|
||||||
// These can be set safely even without WM support
|
// These can be set safely even without WM support
|
||||||
@@ -433,6 +394,10 @@ static bool initExtensions(void)
|
|||||||
XInternAtom(_glfw.x11.display, "WM_STATE", False);
|
XInternAtom(_glfw.x11.display, "WM_STATE", False);
|
||||||
_glfw.x11.WM_DELETE_WINDOW =
|
_glfw.x11.WM_DELETE_WINDOW =
|
||||||
XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
|
XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
|
||||||
|
_glfw.x11.NET_SUPPORTED =
|
||||||
|
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
|
||||||
|
_glfw.x11.NET_SUPPORTING_WM_CHECK =
|
||||||
|
XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
|
||||||
_glfw.x11.NET_WM_ICON =
|
_glfw.x11.NET_WM_ICON =
|
||||||
XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
|
XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
|
||||||
_glfw.x11.NET_WM_PING =
|
_glfw.x11.NET_WM_PING =
|
||||||
@@ -457,6 +422,9 @@ static bool initExtensions(void)
|
|||||||
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
|
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect whether an EWMH-conformant window manager is running
|
||||||
|
detectEWMH();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,12 +432,10 @@ static bool initExtensions(void)
|
|||||||
//
|
//
|
||||||
void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool 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
|
// Start by assuming the default X11 DPI
|
||||||
// for which monitor a window is considered to be on
|
// NOTE: Some desktop environments (KDE) may remove the Xft.dpi field when it
|
||||||
float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) *
|
// would be set to 96, so assume that is the case if we cannot find it
|
||||||
25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
|
float xdpi = 96.f, ydpi = 96.f;
|
||||||
float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) *
|
|
||||||
25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
|
|
||||||
|
|
||||||
// NOTE: Basing the scale on Xft.dpi where available should provide the most
|
// NOTE: Basing the scale on Xft.dpi where available should provide the most
|
||||||
// consistent user experience (matches Qt, Gtk, etc), although not
|
// consistent user experience (matches Qt, Gtk, etc), although not
|
||||||
@@ -499,7 +465,7 @@ void _glfwGetSystemContentScaleX11(float* xscale, float* yscale, bool bypass_cac
|
|||||||
if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
|
if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
|
||||||
{
|
{
|
||||||
if (type && strcmp(type, "String") == 0)
|
if (type && strcmp(type, "String") == 0)
|
||||||
xdpi = ydpi = atof(value.addr);
|
xdpi = ydpi = (float)atof(value.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
XrmDestroyDatabase(db);
|
XrmDestroyDatabase(db);
|
||||||
@@ -536,7 +502,7 @@ static Window createHelperWindow(void)
|
|||||||
|
|
||||||
// X error handler
|
// X error handler
|
||||||
//
|
//
|
||||||
static int errorHandler(Display *display, XErrorEvent* event)
|
static int errorHandler(Display *display UNUSED, XErrorEvent* event)
|
||||||
{
|
{
|
||||||
_glfw.x11.errorCode = event->error_code;
|
_glfw.x11.errorCode = event->error_code;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -611,6 +577,7 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
|
|||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -620,13 +587,6 @@ int _glfwPlatformInit(void)
|
|||||||
XInitThreads();
|
XInitThreads();
|
||||||
XrmInitialize();
|
XrmInitialize();
|
||||||
|
|
||||||
if (pipe2(_glfw.x11.eventLoopData.wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: failed to create self pipe");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.x11.display = XOpenDisplay(NULL);
|
_glfw.x11.display = XOpenDisplay(NULL);
|
||||||
if (!_glfw.x11.display)
|
if (!_glfw.x11.display)
|
||||||
{
|
{
|
||||||
@@ -645,7 +605,10 @@ int _glfwPlatformInit(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
initPollData(&_glfw.x11.eventLoopData, _glfw.x11.eventLoopData.wakeupFds[0], ConnectionNumber(_glfw.x11.display));
|
if (!initPollData(&_glfw.x11.eventLoopData, ConnectionNumber(_glfw.x11.display))) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"X11: Failed to initialize event loop data");
|
||||||
|
}
|
||||||
glfw_dbus_init(&_glfw.x11.dbus, &_glfw.x11.eventLoopData);
|
glfw_dbus_init(&_glfw.x11.dbus, &_glfw.x11.eventLoopData);
|
||||||
|
|
||||||
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
_glfw.x11.screen = DefaultScreen(_glfw.x11.display);
|
||||||
@@ -671,8 +634,6 @@ int _glfwPlatformInit(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
|
||||||
|
|
||||||
_glfwPollMonitorsX11();
|
_glfwPollMonitorsX11();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -754,7 +715,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
#endif
|
#endif
|
||||||
closeFds(_glfw.x11.eventLoopData.wakeupFds, sizeof(_glfw.x11.eventLoopData.wakeupFds)/sizeof(_glfw.x11.eventLoopData.wakeupFds[0]));
|
finalizePollData(&_glfw.x11.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetVersionString(void)
|
const char* _glfwPlatformGetVersionString(void)
|
||||||
|
|||||||
106
glfw/x11_monitor.c
vendored
106
glfw/x11_monitor.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 X11 - www.glfw.org
|
// GLFW 3.4 X11 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,6 +24,8 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
@@ -54,9 +56,7 @@ static int calculateRefreshRate(const XRRModeInfo* mi)
|
|||||||
//
|
//
|
||||||
static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
|
static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
|
||||||
{
|
{
|
||||||
int i;
|
for (int i = 0; i < sr->nmode; i++)
|
||||||
|
|
||||||
for (i = 0; i < sr->nmode; i++)
|
|
||||||
{
|
{
|
||||||
if (sr->modes[i].id == id)
|
if (sr->modes[i].id == id)
|
||||||
return sr->modes + i;
|
return sr->modes + i;
|
||||||
@@ -102,7 +102,7 @@ void _glfwPollMonitorsX11(void)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
int i, j, disconnectedCount, screenCount = 0;
|
int disconnectedCount, screenCount = 0;
|
||||||
_GLFWmonitor** disconnected = NULL;
|
_GLFWmonitor** disconnected = NULL;
|
||||||
XineramaScreenInfo* screens = NULL;
|
XineramaScreenInfo* screens = NULL;
|
||||||
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
|
||||||
@@ -122,14 +122,11 @@ void _glfwPollMonitorsX11(void)
|
|||||||
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
_glfw.monitorCount * sizeof(_GLFWmonitor*));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sr->noutput; i++)
|
for (int i = 0; i < sr->noutput; i++)
|
||||||
{
|
{
|
||||||
int type, widthMM, heightMM;
|
int j, type, widthMM, heightMM;
|
||||||
XRROutputInfo* oi;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
_GLFWmonitor* monitor;
|
|
||||||
|
|
||||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
|
||||||
if (oi->connection != RR_Connected || oi->crtc == None)
|
if (oi->connection != RR_Connected || oi->crtc == None)
|
||||||
{
|
{
|
||||||
XRRFreeOutputInfo(oi);
|
XRRFreeOutputInfo(oi);
|
||||||
@@ -152,7 +149,7 @@ void _glfwPollMonitorsX11(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
|
||||||
if (!ci)
|
if (!ci)
|
||||||
{
|
{
|
||||||
XRRFreeOutputInfo(oi);
|
XRRFreeOutputInfo(oi);
|
||||||
@@ -169,7 +166,17 @@ void _glfwPollMonitorsX11(void)
|
|||||||
heightMM = oi->mm_height;
|
heightMM = oi->mm_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
if (widthMM <= 0 || heightMM <= 0)
|
||||||
|
{
|
||||||
|
// HACK: If RandR does not provide a physical size, assume the
|
||||||
|
// X11 default 96 DPI and calcuate from the CRTC viewport
|
||||||
|
// NOTE: These members are affected by rotation, unlike the mode
|
||||||
|
// info and output info members
|
||||||
|
widthMM = (int) (ci->width * 25.4f / 96.f);
|
||||||
|
heightMM = (int) (ci->height * 25.4f / 96.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
_GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
|
||||||
monitor->x11.output = sr->outputs[i];
|
monitor->x11.output = sr->outputs[i];
|
||||||
monitor->x11.crtc = oi->crtc;
|
monitor->x11.crtc = oi->crtc;
|
||||||
|
|
||||||
@@ -177,8 +184,8 @@ void _glfwPollMonitorsX11(void)
|
|||||||
{
|
{
|
||||||
if (screens[j].x_org == ci->x &&
|
if (screens[j].x_org == ci->x &&
|
||||||
screens[j].y_org == ci->y &&
|
screens[j].y_org == ci->y &&
|
||||||
screens[j].width == ci->width &&
|
screens[j].width == (short int)ci->width &&
|
||||||
screens[j].height == ci->height)
|
screens[j].height == (short int)ci->height)
|
||||||
{
|
{
|
||||||
monitor->x11.index = j;
|
monitor->x11.index = j;
|
||||||
break;
|
break;
|
||||||
@@ -201,7 +208,7 @@ void _glfwPollMonitorsX11(void)
|
|||||||
if (screens)
|
if (screens)
|
||||||
XFree(screens);
|
XFree(screens);
|
||||||
|
|
||||||
for (i = 0; i < disconnectedCount; i++)
|
for (int i = 0; i < disconnectedCount; i++)
|
||||||
{
|
{
|
||||||
if (disconnected[i])
|
if (disconnected[i])
|
||||||
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
|
||||||
@@ -226,24 +233,19 @@ void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
XRROutputInfo* oi;
|
|
||||||
GLFWvidmode current;
|
GLFWvidmode current;
|
||||||
const GLFWvidmode* best;
|
|
||||||
RRMode native = None;
|
RRMode native = None;
|
||||||
int i;
|
|
||||||
|
|
||||||
best = _glfwChooseVideoMode(monitor, desired);
|
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
|
||||||
_glfwPlatformGetVideoMode(monitor, ¤t);
|
_glfwPlatformGetVideoMode(monitor, ¤t);
|
||||||
if (_glfwCompareVideoModes(¤t, best) == 0)
|
if (_glfwCompareVideoModes(¤t, best) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
|
|
||||||
for (i = 0; i < oi->nmode; i++)
|
for (int i = 0; i < oi->nmode; i++)
|
||||||
{
|
{
|
||||||
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
||||||
if (!modeIsGood(mi))
|
if (!modeIsGood(mi))
|
||||||
@@ -284,14 +286,11 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
|
|
||||||
if (monitor->x11.oldMode == None)
|
if (monitor->x11.oldMode == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
XRRSetCrtcConfig(_glfw.x11.display,
|
XRRSetCrtcConfig(_glfw.x11.display,
|
||||||
sr, monitor->x11.crtc,
|
sr, monitor->x11.crtc,
|
||||||
@@ -314,7 +313,7 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
|
|||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
|
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,11 +321,9 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
if (ci)
|
if (ci)
|
||||||
{
|
{
|
||||||
if (xpos)
|
if (xpos)
|
||||||
@@ -340,7 +337,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
|
||||||
float* xscale, float* yscale)
|
float* xscale, float* yscale)
|
||||||
{
|
{
|
||||||
if (xscale)
|
if (xscale)
|
||||||
@@ -349,17 +346,15 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
|
|||||||
*yscale = _glfw.x11.contentScaleY;
|
*yscale = _glfw.x11.contentScaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height)
|
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
|
||||||
{
|
{
|
||||||
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
|
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
|
||||||
|
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
areaX = ci->x;
|
areaX = ci->x;
|
||||||
areaY = ci->y;
|
areaY = ci->y;
|
||||||
@@ -451,24 +446,20 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
|
|||||||
|
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
int i, j;
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
XRRScreenResources* sr;
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
XRRCrtcInfo* ci;
|
XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
||||||
XRROutputInfo* oi;
|
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
|
||||||
oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
|
|
||||||
|
|
||||||
result = calloc(oi->nmode, sizeof(GLFWvidmode));
|
result = calloc(oi->nmode, sizeof(GLFWvidmode));
|
||||||
|
|
||||||
for (i = 0; i < oi->nmode; i++)
|
for (int i = 0; i < oi->nmode; i++)
|
||||||
{
|
{
|
||||||
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
|
||||||
if (!modeIsGood(mi))
|
if (!modeIsGood(mi))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
|
||||||
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < *count; j++)
|
for (j = 0; j < *count; j++)
|
||||||
{
|
{
|
||||||
@@ -502,11 +493,9 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
|
||||||
{
|
{
|
||||||
XRRScreenResources* sr;
|
|
||||||
XRRCrtcInfo* ci;
|
|
||||||
|
|
||||||
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
|
||||||
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
|
||||||
|
|
||||||
if (ci) {
|
if (ci) {
|
||||||
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
|
||||||
@@ -570,7 +559,7 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
|
||||||
{
|
{
|
||||||
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
|
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != (int)ramp->size)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Gamma ramp size must match current ramp size");
|
"X11: Gamma ramp size must match current ramp size");
|
||||||
@@ -595,7 +584,8 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
|
|||||||
(unsigned short*) ramp->green,
|
(unsigned short*) ramp->green,
|
||||||
(unsigned short*) ramp->blue);
|
(unsigned short*) ramp->blue);
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: Gamma ramp access not supported by server");
|
"X11: Gamma ramp access not supported by server");
|
||||||
}
|
}
|
||||||
|
|||||||
33
glfw/x11_platform.h
vendored
33
glfw/x11_platform.h
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 X11 - www.glfw.org
|
// GLFW 3.4 X11 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -152,7 +152,6 @@ typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSur
|
|||||||
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
|
||||||
|
|
||||||
#include "posix_thread.h"
|
#include "posix_thread.h"
|
||||||
#include "posix_time.h"
|
|
||||||
#include "glx_context.h"
|
#include "glx_context.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
#include "osmesa_context.h"
|
#include "osmesa_context.h"
|
||||||
@@ -181,12 +180,13 @@ typedef struct _GLFWwindowX11
|
|||||||
{
|
{
|
||||||
Colormap colormap;
|
Colormap colormap;
|
||||||
Window handle;
|
Window handle;
|
||||||
|
Window parent;
|
||||||
|
|
||||||
bool iconified;
|
bool iconified;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
|
|
||||||
// Whether the visual supports framebuffer transparency
|
// Whether the visual supports framebuffer transparency
|
||||||
bool transparent;
|
bool transparent;
|
||||||
|
|
||||||
// Cached position and size used to filter out duplicate events
|
// Cached position and size used to filter out duplicate events
|
||||||
int width, height;
|
int width, height;
|
||||||
@@ -227,6 +227,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
_GLFWwindow* disabledCursorWindow;
|
_GLFWwindow* disabledCursorWindow;
|
||||||
|
|
||||||
// Window manager atoms
|
// Window manager atoms
|
||||||
|
Atom NET_SUPPORTED;
|
||||||
|
Atom NET_SUPPORTING_WM_CHECK;
|
||||||
Atom WM_PROTOCOLS;
|
Atom WM_PROTOCOLS;
|
||||||
Atom WM_STATE;
|
Atom WM_STATE;
|
||||||
Atom WM_DELETE_WINDOW;
|
Atom WM_DELETE_WINDOW;
|
||||||
@@ -264,7 +266,6 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom XdndFinished;
|
Atom XdndFinished;
|
||||||
Atom XdndSelection;
|
Atom XdndSelection;
|
||||||
Atom XdndTypeList;
|
Atom XdndTypeList;
|
||||||
Atom text_uri_list;
|
|
||||||
|
|
||||||
// Selection (clipboard) atoms
|
// Selection (clipboard) atoms
|
||||||
Atom TARGETS;
|
Atom TARGETS;
|
||||||
@@ -284,14 +285,14 @@ typedef struct _GLFWlibraryX11
|
|||||||
Atom RESOURCE_MANAGER;
|
Atom RESOURCE_MANAGER;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
bool gammaBroken;
|
bool gammaBroken;
|
||||||
bool monitorBroken;
|
bool monitorBroken;
|
||||||
PFN_XRRAllocGamma AllocGamma;
|
PFN_XRRAllocGamma AllocGamma;
|
||||||
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
PFN_XRRFreeCrtcInfo FreeCrtcInfo;
|
||||||
PFN_XRRFreeGamma FreeGamma;
|
PFN_XRRFreeGamma FreeGamma;
|
||||||
@@ -325,7 +326,8 @@ typedef struct _GLFWlibraryX11
|
|||||||
struct {
|
struct {
|
||||||
int version;
|
int version;
|
||||||
Window source;
|
Window source;
|
||||||
Atom format;
|
char format[128];
|
||||||
|
int format_priority;
|
||||||
} xdnd;
|
} xdnd;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -336,7 +338,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xcursor;
|
} xcursor;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
@@ -346,7 +348,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xinerama;
|
} xinerama;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
@@ -357,7 +359,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} vidmode;
|
} vidmode;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
@@ -369,7 +371,7 @@ typedef struct _GLFWlibraryX11
|
|||||||
} xi;
|
} xi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool available;
|
bool available;
|
||||||
void* handle;
|
void* handle;
|
||||||
int major;
|
int major;
|
||||||
int minor;
|
int minor;
|
||||||
@@ -406,6 +408,7 @@ typedef struct _GLFWcursorX11
|
|||||||
|
|
||||||
} _GLFWcursorX11;
|
} _GLFWcursorX11;
|
||||||
|
|
||||||
|
|
||||||
void _glfwPollMonitorsX11(void);
|
void _glfwPollMonitorsX11(void);
|
||||||
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
|
||||||
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
|
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
|
||||||
|
|||||||
495
glfw/x11_window.c
vendored
495
glfw/x11_window.c
vendored
@@ -1,8 +1,8 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 X11 - www.glfw.org
|
// GLFW 3.4 X11 - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2002-2006 Marcus Geelnard
|
// Copyright (c) 2002-2006 Marcus Geelnard
|
||||||
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
|
// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
|
||||||
//
|
//
|
||||||
// This software is provided 'as-is', without any express or implied
|
// This software is provided 'as-is', without any express or implied
|
||||||
// warranty. In no event will the authors be held liable for any damages
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
@@ -24,11 +24,14 @@
|
|||||||
// distribution.
|
// distribution.
|
||||||
//
|
//
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
// It is fine to use C99 in this file because it will not be built with VS
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
#include "linux_notify.h"
|
#include "linux_notify.h"
|
||||||
|
#include "../kitty/monotonic.h"
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
#include <X11/Xmd.h>
|
#include <X11/Xmd.h>
|
||||||
@@ -49,8 +52,13 @@
|
|||||||
#define Button6 6
|
#define Button6 6
|
||||||
#define Button7 7
|
#define Button7 7
|
||||||
|
|
||||||
|
// Motif WM hints flags
|
||||||
|
#define MWM_HINTS_DECORATIONS 2
|
||||||
|
#define MWM_DECOR_ALL 1
|
||||||
|
|
||||||
#define _GLFW_XDND_VERSION 5
|
#define _GLFW_XDND_VERSION 5
|
||||||
|
|
||||||
|
|
||||||
// Wait for data to arrive using poll
|
// Wait for data to arrive using poll
|
||||||
// This avoids blocking other threads via the per-display Xlib lock that also
|
// This avoids blocking other threads via the per-display Xlib lock that also
|
||||||
// covers GLX functions
|
// covers GLX functions
|
||||||
@@ -58,9 +66,9 @@
|
|||||||
static unsigned _glfwDispatchX11Events(void);
|
static unsigned _glfwDispatchX11Events(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(double timeout) {
|
handleEvents(monotonic_t timeout) {
|
||||||
EVDBG("starting handleEvents(%.2f)", timeout);
|
EVDBG("starting handleEvents(%.2f)", monotonic_t_to_s_double(timeout));
|
||||||
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout);
|
int display_read_ok = pollForEvents(&_glfw.x11.eventLoopData, timeout, NULL);
|
||||||
EVDBG("display_read_ok: %d", display_read_ok);
|
EVDBG("display_read_ok: %d", display_read_ok);
|
||||||
if (display_read_ok) {
|
if (display_read_ok) {
|
||||||
unsigned dispatched = _glfwDispatchX11Events();
|
unsigned dispatched = _glfwDispatchX11Events();
|
||||||
@@ -70,12 +78,13 @@ handleEvents(double timeout) {
|
|||||||
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
||||||
glfw_dbus_session_bus_dispatch();
|
glfw_dbus_session_bus_dispatch();
|
||||||
EVDBG("other dispatch done");
|
EVDBG("other dispatch done");
|
||||||
|
if (_glfw.x11.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.x11.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
waitForX11Event(double timeout) {
|
waitForX11Event(monotonic_t timeout) {
|
||||||
// returns true iff there is X11 data waiting to be read, does not run watches and timers
|
// returns true if there is X11 data waiting to be read, does not run watches and timers
|
||||||
double end_time = glfwGetTime() + timeout;
|
monotonic_t end_time = glfwGetTime() + timeout;
|
||||||
while(true) {
|
while(true) {
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
const int result = pollWithTimeout(_glfw.x11.eventLoopData.fds, 1, timeout);
|
const int result = pollWithTimeout(_glfw.x11.eventLoopData.fds, 1, timeout);
|
||||||
@@ -105,7 +114,7 @@ static bool waitForVisibilityNotify(_GLFWwindow* window)
|
|||||||
VisibilityNotify,
|
VisibilityNotify,
|
||||||
&dummy))
|
&dummy))
|
||||||
{
|
{
|
||||||
if (!waitForX11Event(0.1))
|
if (!waitForX11Event(ms_to_monotonic_t(100ll)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +147,7 @@ static int getWindowState(_GLFWwindow* window)
|
|||||||
|
|
||||||
// Returns whether the event is a selection event
|
// Returns whether the event is a selection event
|
||||||
//
|
//
|
||||||
static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
|
static Bool isSelectionEvent(Display* display UNUSED, XEvent* event, XPointer pointer UNUSED)
|
||||||
{
|
{
|
||||||
if (event->xany.window != _glfw.x11.helperWindowHandle)
|
if (event->xany.window != _glfw.x11.helperWindowHandle)
|
||||||
return False;
|
return False;
|
||||||
@@ -150,7 +159,7 @@ static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
|
|||||||
|
|
||||||
// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window
|
// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window
|
||||||
//
|
//
|
||||||
static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)
|
static Bool isFrameExtentsEvent(Display* display UNUSED, XEvent* event, XPointer pointer)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) pointer;
|
_GLFWwindow* window = (_GLFWwindow*) pointer;
|
||||||
return event->type == PropertyNotify &&
|
return event->type == PropertyNotify &&
|
||||||
@@ -161,7 +170,7 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
|
|||||||
|
|
||||||
// Returns whether it is a property event for the specified selection transfer
|
// Returns whether it is a property event for the specified selection transfer
|
||||||
//
|
//
|
||||||
static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
|
static Bool isSelPropNewValueNotify(Display* display UNUSED, XEvent* event, XPointer pointer)
|
||||||
{
|
{
|
||||||
XEvent* notification = (XEvent*) pointer;
|
XEvent* notification = (XEvent*) pointer;
|
||||||
return event->type == PropertyNotify &&
|
return event->type == PropertyNotify &&
|
||||||
@@ -197,10 +206,7 @@ static int translateState(int state)
|
|||||||
static void sendEventToWM(_GLFWwindow* window, Atom type,
|
static void sendEventToWM(_GLFWwindow* window, Atom type,
|
||||||
long a, long b, long c, long d, long e)
|
long a, long b, long c, long d, long e)
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event = { ClientMessage };
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
|
|
||||||
event.type = ClientMessage;
|
|
||||||
event.xclient.window = window->x11.handle;
|
event.xclient.window = window->x11.handle;
|
||||||
event.xclient.format = 32; // Data is 32-bit longs
|
event.xclient.format = 32; // Data is 32-bit longs
|
||||||
event.xclient.message_type = type;
|
event.xclient.message_type = type;
|
||||||
@@ -249,6 +255,14 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height)
|
|||||||
hints->min_aspect.x = hints->max_aspect.x = window->numer;
|
hints->min_aspect.x = hints->max_aspect.x = window->numer;
|
||||||
hints->min_aspect.y = hints->max_aspect.y = window->denom;
|
hints->min_aspect.y = hints->max_aspect.y = window->denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->widthincr != GLFW_DONT_CARE &&
|
||||||
|
window->heightincr != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
hints->flags |= PResizeInc;
|
||||||
|
hints->width_inc = window->widthincr;
|
||||||
|
hints->height_inc = window->heightincr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -328,8 +342,7 @@ set_fullscreen(_GLFWwindow *window, bool on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags) {
|
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
|
||||||
(void) flags;
|
|
||||||
bool already_fullscreen = is_window_fullscreen(window);
|
bool already_fullscreen = is_window_fullscreen(window);
|
||||||
set_fullscreen(window, !already_fullscreen);
|
set_fullscreen(window, !already_fullscreen);
|
||||||
return !already_fullscreen;
|
return !already_fullscreen;
|
||||||
@@ -508,8 +521,8 @@ static bool createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (wndconfig->scaleToMonitor)
|
if (wndconfig->scaleToMonitor)
|
||||||
{
|
{
|
||||||
width *= _glfw.x11.contentScaleX;
|
width *= (int)_glfw.x11.contentScaleX;
|
||||||
height *= _glfw.x11.contentScaleY;
|
height *= (int)_glfw.x11.contentScaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a colormap based on the visual used by the current context
|
// Create a colormap based on the visual used by the current context
|
||||||
@@ -520,46 +533,41 @@ static bool createNativeWindow(_GLFWwindow* window,
|
|||||||
|
|
||||||
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
|
window->x11.transparent = _glfwIsVisualTransparentX11(visual);
|
||||||
|
|
||||||
// Create the actual window
|
XSetWindowAttributes wa = { 0 };
|
||||||
|
wa.colormap = window->x11.colormap;
|
||||||
|
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
||||||
|
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
||||||
|
ExposureMask | FocusChangeMask | VisibilityChangeMask |
|
||||||
|
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
|
||||||
|
|
||||||
|
_glfwGrabErrorHandlerX11();
|
||||||
|
|
||||||
|
window->x11.parent = _glfw.x11.root;
|
||||||
|
window->x11.handle = XCreateWindow(_glfw.x11.display,
|
||||||
|
_glfw.x11.root,
|
||||||
|
0, 0, // Position
|
||||||
|
width, height,
|
||||||
|
0, // Border width
|
||||||
|
depth, // Color depth
|
||||||
|
InputOutput,
|
||||||
|
visual,
|
||||||
|
CWBorderPixel | CWColormap | CWEventMask,
|
||||||
|
&wa);
|
||||||
|
|
||||||
|
_glfwReleaseErrorHandlerX11();
|
||||||
|
|
||||||
|
if (!window->x11.handle)
|
||||||
{
|
{
|
||||||
XSetWindowAttributes wa;
|
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
||||||
const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
|
"X11: Failed to create window");
|
||||||
|
return false;
|
||||||
wa.colormap = window->x11.colormap;
|
|
||||||
wa.border_pixel = 0;
|
|
||||||
wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
|
||||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
|
|
||||||
ExposureMask | FocusChangeMask | VisibilityChangeMask |
|
|
||||||
EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
|
|
||||||
|
|
||||||
_glfwGrabErrorHandlerX11();
|
|
||||||
|
|
||||||
window->x11.handle = XCreateWindow(_glfw.x11.display,
|
|
||||||
_glfw.x11.root,
|
|
||||||
0, 0,
|
|
||||||
width, height,
|
|
||||||
0, // Border width
|
|
||||||
depth, // Color depth
|
|
||||||
InputOutput,
|
|
||||||
visual,
|
|
||||||
wamask,
|
|
||||||
&wa);
|
|
||||||
|
|
||||||
_glfwReleaseErrorHandlerX11();
|
|
||||||
|
|
||||||
if (!window->x11.handle)
|
|
||||||
{
|
|
||||||
_glfwInputErrorX11(GLFW_PLATFORM_ERROR,
|
|
||||||
"X11: Failed to create window");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSaveContext(_glfw.x11.display,
|
|
||||||
window->x11.handle,
|
|
||||||
_glfw.x11.context,
|
|
||||||
(XPointer) window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XSaveContext(_glfw.x11.display,
|
||||||
|
window->x11.handle,
|
||||||
|
_glfw.x11.context,
|
||||||
|
(XPointer) window);
|
||||||
|
|
||||||
if (!wndconfig->decorated)
|
if (!wndconfig->decorated)
|
||||||
_glfwPlatformSetWindowDecorated(window, false);
|
_glfwPlatformSetWindowDecorated(window, false);
|
||||||
|
|
||||||
@@ -589,7 +597,7 @@ static bool createNativeWindow(_GLFWwindow* window,
|
|||||||
{
|
{
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char*) &states, count);
|
PropModeReplace, (unsigned char*) states, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,11 +849,8 @@ static void handleSelectionRequest(XEvent* event)
|
|||||||
{
|
{
|
||||||
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
const XSelectionRequestEvent* request = &event->xselectionrequest;
|
||||||
|
|
||||||
XEvent reply;
|
XEvent reply = { SelectionNotify };
|
||||||
memset(&reply, 0, sizeof(reply));
|
|
||||||
|
|
||||||
reply.xselection.property = writeTargetToProperty(request);
|
reply.xselection.property = writeTargetToProperty(request);
|
||||||
reply.xselection.type = SelectionNotify;
|
|
||||||
reply.xselection.display = request->display;
|
reply.xselection.display = request->display;
|
||||||
reply.xselection.requestor = request->requestor;
|
reply.xselection.requestor = request->requestor;
|
||||||
reply.xselection.selection = request->selection;
|
reply.xselection.selection = request->selection;
|
||||||
@@ -857,7 +862,6 @@ static void handleSelectionRequest(XEvent* event)
|
|||||||
|
|
||||||
static const char* getSelectionString(Atom selection)
|
static const char* getSelectionString(Atom selection)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
char** selectionString = NULL;
|
char** selectionString = NULL;
|
||||||
const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
|
||||||
const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
|
const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
|
||||||
@@ -878,13 +882,13 @@ static const char* getSelectionString(Atom selection)
|
|||||||
free(*selectionString);
|
free(*selectionString);
|
||||||
*selectionString = NULL;
|
*selectionString = NULL;
|
||||||
|
|
||||||
for (i = 0; i < targetCount; i++)
|
for (size_t i = 0; i < targetCount; i++)
|
||||||
{
|
{
|
||||||
char* data;
|
char* data;
|
||||||
Atom actualType;
|
Atom actualType;
|
||||||
int actualFormat;
|
int actualFormat;
|
||||||
unsigned long itemCount, bytesAfter;
|
unsigned long itemCount, bytesAfter;
|
||||||
double start = glfwGetTime();
|
monotonic_t start = glfwGetTime();
|
||||||
XEvent notification, dummy;
|
XEvent notification, dummy;
|
||||||
|
|
||||||
XConvertSelection(_glfw.x11.display,
|
XConvertSelection(_glfw.x11.display,
|
||||||
@@ -899,10 +903,10 @@ static const char* getSelectionString(Atom selection)
|
|||||||
SelectionNotify,
|
SelectionNotify,
|
||||||
¬ification))
|
¬ification))
|
||||||
{
|
{
|
||||||
double time = glfwGetTime();
|
monotonic_t time = glfwGetTime();
|
||||||
if (time - start > 2)
|
if (time - start > s_to_monotonic_t(2ll))
|
||||||
return "";
|
return "";
|
||||||
waitForX11Event(2.0 - (time - start));
|
waitForX11Event(s_to_monotonic_t(2ll) - (time - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notification.xselection.property == None)
|
if (notification.xselection.property == None)
|
||||||
@@ -939,10 +943,10 @@ static const char* getSelectionString(Atom selection)
|
|||||||
isSelPropNewValueNotify,
|
isSelPropNewValueNotify,
|
||||||
(XPointer) ¬ification))
|
(XPointer) ¬ification))
|
||||||
{
|
{
|
||||||
double time = glfwGetTime();
|
monotonic_t time = glfwGetTime();
|
||||||
if (time - start > 2)
|
if (time - start > s_to_monotonic_t(2ll))
|
||||||
return "";
|
return "";
|
||||||
waitForX11Event(2.0 - (time - start));
|
waitForX11Event(s_to_monotonic_t(2ll) - (time - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(data);
|
XFree(data);
|
||||||
@@ -1075,7 +1079,6 @@ static void onConfigChange(void)
|
|||||||
//
|
//
|
||||||
static void processEvent(XEvent *event)
|
static void processEvent(XEvent *event)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = NULL;
|
|
||||||
static bool keymap_dirty = 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); }
|
#define UPDATE_KEYMAP_IF_NEEDED if (keymap_dirty) { keymap_dirty = false; glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL); }
|
||||||
|
|
||||||
@@ -1170,6 +1173,7 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_GLFWwindow* window = NULL;
|
||||||
if (XFindContext(_glfw.x11.display,
|
if (XFindContext(_glfw.x11.display,
|
||||||
event->xany.window,
|
event->xany.window,
|
||||||
_glfw.x11.context,
|
_glfw.x11.context,
|
||||||
@@ -1181,6 +1185,12 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
|
case ReparentNotify:
|
||||||
|
{
|
||||||
|
window->x11.parent = event->xreparent.parent;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
{
|
{
|
||||||
UPDATE_KEYMAP_IF_NEEDED;
|
UPDATE_KEYMAP_IF_NEEDED;
|
||||||
@@ -1374,18 +1384,28 @@ static void processEvent(XEvent *event)
|
|||||||
window->x11.height = event->xconfigure.height;
|
window->x11.height = event->xconfigure.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->xconfigure.x != window->x11.xpos ||
|
int xpos = event->xconfigure.x;
|
||||||
event->xconfigure.y != window->x11.ypos)
|
int ypos = event->xconfigure.y;
|
||||||
{
|
|
||||||
if (event->xany.send_event)
|
|
||||||
{
|
|
||||||
_glfwInputWindowPos(window,
|
|
||||||
event->xconfigure.x,
|
|
||||||
event->xconfigure.y);
|
|
||||||
|
|
||||||
window->x11.xpos = event->xconfigure.x;
|
// NOTE: ConfigureNotify events from the server are in local
|
||||||
window->x11.ypos = event->xconfigure.y;
|
// coordinates, so if we are reparented we need to translate
|
||||||
}
|
// the position into root (screen) coordinates
|
||||||
|
if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
|
||||||
|
{
|
||||||
|
Window dummy;
|
||||||
|
XTranslateCoordinates(_glfw.x11.display,
|
||||||
|
window->x11.parent,
|
||||||
|
_glfw.x11.root,
|
||||||
|
xpos, ypos,
|
||||||
|
&xpos, &ypos,
|
||||||
|
&dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xpos != window->x11.xpos || ypos != window->x11.ypos)
|
||||||
|
{
|
||||||
|
_glfwInputWindowPos(window, xpos, ypos);
|
||||||
|
window->x11.xpos = xpos;
|
||||||
|
window->x11.ypos = ypos;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1434,7 +1454,8 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
_glfw.x11.xdnd.source = event->xclient.data.l[0];
|
||||||
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
_glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
|
||||||
_glfw.x11.xdnd.format = None;
|
memset(_glfw.x11.xdnd.format, 0, sizeof(_glfw.x11.xdnd.format));
|
||||||
|
_glfw.x11.xdnd.format_priority = 0;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
@@ -1451,14 +1472,22 @@ static void processEvent(XEvent *event)
|
|||||||
count = 3;
|
count = 3;
|
||||||
formats = (Atom*) event->xclient.data.l + 2;
|
formats = (Atom*) event->xclient.data.l + 2;
|
||||||
}
|
}
|
||||||
|
char **atom_names = calloc(count, sizeof(char**));
|
||||||
|
if (atom_names) {
|
||||||
|
XGetAtomNames(_glfw.x11.display, formats, count, atom_names);
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
|
||||||
if (formats[i] == _glfw.x11.text_uri_list)
|
|
||||||
{
|
{
|
||||||
_glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
|
if (atom_names[i]) {
|
||||||
break;
|
int prio = _glfwInputDrop(window, atom_names[i], NULL, 0);
|
||||||
|
if (prio > _glfw.x11.xdnd.format_priority) {
|
||||||
|
_glfw.x11.xdnd.format_priority = prio;
|
||||||
|
strncpy(_glfw.x11.xdnd.format, atom_names[i], arraysz(_glfw.x11.xdnd.format) - 1);
|
||||||
|
}
|
||||||
|
XFree(atom_names[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
free(atom_names);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list && formats)
|
if (list && formats)
|
||||||
@@ -1472,7 +1501,7 @@ static void processEvent(XEvent *event)
|
|||||||
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.format)
|
if (_glfw.x11.xdnd.format_priority > 0)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.xdnd.version >= 1)
|
if (_glfw.x11.xdnd.version >= 1)
|
||||||
time = event->xclient.data.l[2];
|
time = event->xclient.data.l[2];
|
||||||
@@ -1480,17 +1509,14 @@ static void processEvent(XEvent *event)
|
|||||||
// Request the chosen format from the source window
|
// Request the chosen format from the source window
|
||||||
XConvertSelection(_glfw.x11.display,
|
XConvertSelection(_glfw.x11.display,
|
||||||
_glfw.x11.XdndSelection,
|
_glfw.x11.XdndSelection,
|
||||||
_glfw.x11.xdnd.format,
|
XInternAtom(_glfw.x11.display, _glfw.x11.xdnd.format, 0),
|
||||||
_glfw.x11.XdndSelection,
|
_glfw.x11.XdndSelection,
|
||||||
window->x11.handle,
|
window->x11.handle,
|
||||||
time);
|
time);
|
||||||
}
|
}
|
||||||
else if (_glfw.x11.xdnd.version >= 2)
|
else if (_glfw.x11.xdnd.version >= 2)
|
||||||
{
|
{
|
||||||
XEvent reply;
|
XEvent reply = { ClientMessage };
|
||||||
memset(&reply, 0, sizeof(reply));
|
|
||||||
|
|
||||||
reply.type = ClientMessage;
|
|
||||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
@@ -1523,10 +1549,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
_glfwInputCursorPos(window, xpos, ypos);
|
_glfwInputCursorPos(window, xpos, ypos);
|
||||||
|
|
||||||
XEvent reply;
|
XEvent reply = { ClientMessage };
|
||||||
memset(&reply, 0, sizeof(reply));
|
|
||||||
|
|
||||||
reply.type = ClientMessage;
|
|
||||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
reply.xclient.message_type = _glfw.x11.XdndStatus;
|
||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
@@ -1534,7 +1557,7 @@ static void processEvent(XEvent *event)
|
|||||||
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
reply.xclient.data.l[2] = 0; // Specify an empty rectangle
|
||||||
reply.xclient.data.l[3] = 0;
|
reply.xclient.data.l[3] = 0;
|
||||||
|
|
||||||
if (_glfw.x11.xdnd.format)
|
if (_glfw.x11.xdnd.format_priority > 0)
|
||||||
{
|
{
|
||||||
// Reply that we are ready to copy the dragged data
|
// Reply that we are ready to copy the dragged data
|
||||||
reply.xclient.data.l[1] = 1; // Accept with no rectangle
|
reply.xclient.data.l[1] = 1; // Accept with no rectangle
|
||||||
@@ -1564,14 +1587,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
int i, count;
|
_glfwInputDrop(window, _glfw.x11.xdnd.format, data, result);
|
||||||
char** paths = parseUriList(data, &count);
|
|
||||||
|
|
||||||
_glfwInputDrop(window, count, (const char**) paths);
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
free(paths[i]);
|
|
||||||
free(paths);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data)
|
if (data)
|
||||||
@@ -1579,10 +1595,7 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
if (_glfw.x11.xdnd.version >= 2)
|
if (_glfw.x11.xdnd.version >= 2)
|
||||||
{
|
{
|
||||||
XEvent reply;
|
XEvent reply = { ClientMessage };
|
||||||
memset(&reply, 0, sizeof(reply));
|
|
||||||
|
|
||||||
reply.type = ClientMessage;
|
|
||||||
reply.xclient.window = _glfw.x11.xdnd.source;
|
reply.xclient.window = _glfw.x11.xdnd.source;
|
||||||
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
reply.xclient.message_type = _glfw.x11.XdndFinished;
|
||||||
reply.xclient.format = 32;
|
reply.xclient.format = 32;
|
||||||
@@ -1601,9 +1614,6 @@ static void processEvent(XEvent *event)
|
|||||||
|
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
|
||||||
disableCursor(window);
|
|
||||||
|
|
||||||
if (event->xfocus.mode == NotifyGrab ||
|
if (event->xfocus.mode == NotifyGrab ||
|
||||||
event->xfocus.mode == NotifyUngrab)
|
event->xfocus.mode == NotifyUngrab)
|
||||||
{
|
{
|
||||||
@@ -1612,15 +1622,15 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
disableCursor(window);
|
||||||
|
|
||||||
_glfwInputWindowFocus(window, true);
|
_glfwInputWindowFocus(window, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
|
||||||
enableCursor(window);
|
|
||||||
|
|
||||||
if (event->xfocus.mode == NotifyGrab ||
|
if (event->xfocus.mode == NotifyGrab ||
|
||||||
event->xfocus.mode == NotifyUngrab)
|
event->xfocus.mode == NotifyUngrab)
|
||||||
{
|
{
|
||||||
@@ -1629,6 +1639,9 @@ static void processEvent(XEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
enableCursor(window);
|
||||||
|
|
||||||
if (window->monitor && window->autoIconify)
|
if (window->monitor && window->autoIconify)
|
||||||
_glfwPlatformIconifyWindow(window);
|
_glfwPlatformIconifyWindow(window);
|
||||||
|
|
||||||
@@ -2025,8 +2038,8 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
||||||
int minwidth, int minheight,
|
int minwidth UNUSED, int minheight UNUSED,
|
||||||
int maxwidth, int maxheight)
|
int maxwidth UNUSED, int maxheight UNUSED)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
@@ -2034,7 +2047,15 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
|
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer UNUSED, int denom UNUSED)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
|
updateNormalHints(window, width, height);
|
||||||
|
XFlush(_glfw.x11.display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformSetWindowSizeIncrements(_GLFWwindow* window, int widthincr UNUSED, int heightincr UNUSED)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
@@ -2079,7 +2100,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
isFrameExtentsEvent,
|
isFrameExtentsEvent,
|
||||||
(XPointer) window))
|
(XPointer) window))
|
||||||
{
|
{
|
||||||
if (!waitForX11Event(0.5))
|
if (!waitForX11Event(ms_to_monotonic_t(500ll)))
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
"X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
|
||||||
@@ -2107,7 +2128,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
|
|||||||
XFree(extents);
|
XFree(extents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
|
||||||
float* xscale, float* yscale)
|
float* xscale, float* yscale)
|
||||||
{
|
{
|
||||||
if (xscale)
|
if (xscale)
|
||||||
@@ -2116,9 +2137,9 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|||||||
*yscale = _glfw.x11.contentScaleY;
|
*yscale = _glfw.x11.contentScaleY;
|
||||||
}
|
}
|
||||||
|
|
||||||
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window)
|
monotonic_t _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return 0.5;
|
return ms_to_monotonic_t(500ll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
@@ -2154,18 +2175,67 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (_glfw.x11.NET_WM_STATE &&
|
if (!_glfw.x11.NET_WM_STATE ||
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
_NET_WM_STATE_ADD,
|
_NET_WM_STATE_ADD,
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
||||||
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
|
||||||
1, 0);
|
1, 0);
|
||||||
XFlush(_glfw.x11.display);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Atom* states = NULL;
|
||||||
|
unsigned long count =
|
||||||
|
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_STATE,
|
||||||
|
XA_ATOM,
|
||||||
|
(unsigned char**) &states);
|
||||||
|
|
||||||
|
// NOTE: We don't check for failure as this property may not exist yet
|
||||||
|
// and that's fine (and we'll create it implicitly with append)
|
||||||
|
|
||||||
|
Atom missing[2] =
|
||||||
|
{
|
||||||
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
|
||||||
|
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
|
||||||
|
};
|
||||||
|
unsigned long missingCount = 2;
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (unsigned long j = 0; j < missingCount; j++)
|
||||||
|
{
|
||||||
|
if (states[i] == missing[j])
|
||||||
|
{
|
||||||
|
missing[j] = missing[missingCount - 1];
|
||||||
|
missingCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (states)
|
||||||
|
XFree(states);
|
||||||
|
|
||||||
|
if (!missingCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
|
PropModeAppend,
|
||||||
|
(unsigned char*) missing,
|
||||||
|
missingCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
@@ -2185,6 +2255,9 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
|
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION)
|
||||||
|
return;
|
||||||
|
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
_NET_WM_STATE_ADD,
|
_NET_WM_STATE_ADD,
|
||||||
@@ -2201,7 +2274,7 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
if (_glfw.x11.NET_ACTIVE_WINDOW)
|
||||||
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
|
sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
|
||||||
else
|
else if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
XRaiseWindow(_glfw.x11.display, window->x11.handle);
|
||||||
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
XSetInputFocus(_glfw.x11.display, window->x11.handle,
|
||||||
@@ -2215,7 +2288,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
_GLFWmonitor* monitor,
|
_GLFWmonitor* monitor,
|
||||||
int xpos, int ypos,
|
int xpos, int ypos,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
int refreshRate)
|
int refreshRate UNUSED)
|
||||||
{
|
{
|
||||||
if (window->monitor == monitor)
|
if (window->monitor == monitor)
|
||||||
{
|
{
|
||||||
@@ -2245,13 +2318,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
|
|||||||
|
|
||||||
if (window->monitor)
|
if (window->monitor)
|
||||||
{
|
{
|
||||||
if (!_glfwPlatformWindowVisible(window))
|
if (!_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
XMapRaised(_glfw.x11.display, window->x11.handle);
|
XMapRaised(_glfw.x11.display, window->x11.handle);
|
||||||
waitForVisibilityNotify(window);
|
waitForVisibilityNotify(window);
|
||||||
}
|
}
|
||||||
updateWindowMode(window);
|
|
||||||
acquireMonitor(window);
|
updateWindowMode(window);
|
||||||
|
acquireMonitor(window);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2272,7 +2346,7 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
|
|||||||
return window->x11.handle == focused;
|
return window->x11.handle == focused;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowOccluded(_GLFWwindow* window)
|
int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2294,10 +2368,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
|
|||||||
Atom* states;
|
Atom* states;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
bool maximized = false;
|
bool maximized = false;
|
||||||
|
|
||||||
if (!_glfw.x11.NET_WM_STATE ||
|
if (!_glfw.x11.NET_WM_STATE ||
|
||||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
|
||||||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
|
||||||
|
{
|
||||||
return maximized;
|
return maximized;
|
||||||
|
}
|
||||||
const unsigned long count =
|
const unsigned long count =
|
||||||
_glfwGetWindowPropertyX11(window->x11.handle,
|
_glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
@@ -2350,7 +2427,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||||||
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
|
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled UNUSED)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwPlatformGetWindowSize(window, &width, &height);
|
_glfwPlatformGetWindowSize(window, &width, &height);
|
||||||
@@ -2359,33 +2436,24 @@ void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
|
||||||
{
|
{
|
||||||
if (enabled)
|
struct
|
||||||
{
|
{
|
||||||
XDeleteProperty(_glfw.x11.display,
|
unsigned long flags;
|
||||||
window->x11.handle,
|
unsigned long functions;
|
||||||
_glfw.x11.MOTIF_WM_HINTS);
|
unsigned long decorations;
|
||||||
}
|
long input_mode;
|
||||||
else
|
unsigned long status;
|
||||||
{
|
} hints = {0};
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
unsigned long functions;
|
|
||||||
unsigned long decorations;
|
|
||||||
long input_mode;
|
|
||||||
unsigned long status;
|
|
||||||
} hints;
|
|
||||||
|
|
||||||
hints.flags = 2; // Set decorations
|
hints.flags = MWM_HINTS_DECORATIONS;
|
||||||
hints.decorations = 0; // No decorations
|
hints.decorations = enabled ? MWM_DECOR_ALL : 0;
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.MOTIF_WM_HINTS,
|
_glfw.x11.MOTIF_WM_HINTS,
|
||||||
_glfw.x11.MOTIF_WM_HINTS, 32,
|
_glfw.x11.MOTIF_WM_HINTS, 32,
|
||||||
PropModeReplace,
|
PropModeReplace,
|
||||||
(unsigned char*) &hints,
|
(unsigned char*) &hints,
|
||||||
sizeof(hints) / sizeof(long));
|
sizeof(hints) / sizeof(long));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
||||||
@@ -2395,7 +2463,7 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
|||||||
|
|
||||||
if (_glfwPlatformWindowVisible(window))
|
if (_glfwPlatformWindowVisible(window))
|
||||||
{
|
{
|
||||||
const Atom action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||||
sendEventToWM(window,
|
sendEventToWM(window,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
action,
|
action,
|
||||||
@@ -2404,15 +2472,16 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Atom* states;
|
Atom* states = NULL;
|
||||||
unsigned long i, count;
|
unsigned long i, count;
|
||||||
|
|
||||||
count = _glfwGetWindowPropertyX11(window->x11.handle,
|
count = _glfwGetWindowPropertyX11(window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE,
|
_glfw.x11.NET_WM_STATE,
|
||||||
XA_ATOM,
|
XA_ATOM,
|
||||||
(unsigned char**) &states);
|
(unsigned char**) &states);
|
||||||
if (!states)
|
|
||||||
return;
|
// NOTE: We don't check for failure as this property may not exist yet
|
||||||
|
// and that's fine (and we'll create it implicitly with append)
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
@@ -2422,32 +2491,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == count)
|
if (i < count)
|
||||||
{
|
return;
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
PropModeAppend,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
|
PropModeAppend,
|
||||||
1);
|
(unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
|
||||||
}
|
1);
|
||||||
}
|
}
|
||||||
else
|
else if (states)
|
||||||
{
|
{
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
|
if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
|
||||||
{
|
break;
|
||||||
states[i] = states[count - 1];
|
|
||||||
count--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i == count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
states[i] = states[count - 1];
|
||||||
|
count--;
|
||||||
|
|
||||||
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
XChangeProperty(_glfw.x11.display, window->x11.handle,
|
||||||
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
|
||||||
PropModeReplace, (unsigned char*) &states, count);
|
PropModeReplace, (unsigned char*) states, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFree(states);
|
if (states)
|
||||||
|
XFree(states);
|
||||||
}
|
}
|
||||||
|
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
@@ -2485,14 +2558,12 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned
|
static inline unsigned
|
||||||
dispatch_x11_queued_events(void) {
|
dispatch_x11_queued_events(int num_events) {
|
||||||
unsigned dispatched = 0;
|
unsigned dispatched = num_events > 0 ? num_events : 0;
|
||||||
while (XQLength(_glfw.x11.display) > 0)
|
while (num_events-- > 0) {
|
||||||
{
|
|
||||||
XEvent event;
|
XEvent event;
|
||||||
XNextEvent(_glfw.x11.display, &event);
|
XNextEvent(_glfw.x11.display, &event);
|
||||||
processEvent(&event);
|
processEvent(&event);
|
||||||
dispatched += 1;
|
|
||||||
}
|
}
|
||||||
return dispatched;
|
return dispatched;
|
||||||
}
|
}
|
||||||
@@ -2503,10 +2574,9 @@ _glfwDispatchX11Events(void) {
|
|||||||
unsigned dispatched = 0;
|
unsigned dispatched = 0;
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
_glfwDetectJoystickConnectionLinux();
|
if (_glfw.hints.init.enableJoysticks) _glfwDetectJoystickConnectionLinux();
|
||||||
#endif
|
#endif
|
||||||
XPending(_glfw.x11.display);
|
dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAfterFlush));
|
||||||
dispatched += dispatch_x11_queued_events();
|
|
||||||
|
|
||||||
window = _glfw.x11.disabledCursorWindow;
|
window = _glfw.x11.disabledCursorWindow;
|
||||||
if (window)
|
if (window)
|
||||||
@@ -2524,8 +2594,10 @@ _glfwDispatchX11Events(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
// XFlush can cause events to be queued
|
// XFlush can cause events to be queued, we don't use QueuedAfterFlush here
|
||||||
dispatched += dispatch_x11_queued_events();
|
// as something might have inserted events into the queue, but we want to guarantee
|
||||||
|
// a flush.
|
||||||
|
dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAlready));
|
||||||
return dispatched;
|
return dispatched;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2537,11 +2609,11 @@ void _glfwPlatformPollEvents(void)
|
|||||||
|
|
||||||
void _glfwPlatformWaitEvents(void)
|
void _glfwPlatformWaitEvents(void)
|
||||||
{
|
{
|
||||||
double timeout = _glfwDispatchX11Events() ? 0 : -1;
|
monotonic_t timeout = _glfwDispatchX11Events() ? 0 : -1;
|
||||||
handleEvents(timeout);
|
handleEvents(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformWaitEventsTimeout(double timeout)
|
void _glfwPlatformWaitEventsTimeout(monotonic_t timeout)
|
||||||
{
|
{
|
||||||
if (_glfwDispatchX11Events()) timeout = 0;
|
if (_glfwDispatchX11Events()) timeout = 0;
|
||||||
handleEvents(timeout);
|
handleEvents(timeout);
|
||||||
@@ -2549,7 +2621,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
|
|||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
{
|
{
|
||||||
while (write(_glfw.x11.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR);
|
wakeupEventLoop(&_glfw.x11.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
@@ -2595,20 +2667,20 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
|
|||||||
XFlush(_glfw.x11.display);
|
XFlush(_glfw.x11.display);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* _glfwPlatformGetScancodeName(int scancode)
|
const char* _glfwPlatformGetNativeKeyName(int native_key)
|
||||||
{
|
{
|
||||||
|
|
||||||
return glfw_xkb_keysym_name(scancode);
|
return glfw_xkb_keysym_name(native_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetNativeKeyForKey(int key)
|
||||||
{
|
{
|
||||||
return glfw_xkb_sym_for_key(key);
|
return glfw_xkb_sym_for_key(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
const GLFWimage* image,
|
const GLFWimage* image,
|
||||||
int xhot, int yhot, int count)
|
int xhot, int yhot, int count UNUSED)
|
||||||
{
|
{
|
||||||
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
|
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
|
||||||
if (!cursor->x11.handle)
|
if (!cursor->x11.handle)
|
||||||
@@ -2622,7 +2694,7 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, GLFWCursorShape shape
|
|||||||
int native = 0;
|
int native = 0;
|
||||||
#define C(name, val) case name: native = val; break;
|
#define C(name, val) case name: native = val; break;
|
||||||
switch(shape) {
|
switch(shape) {
|
||||||
C(GLFW_ARROW_CURSOR, XC_arrow);
|
C(GLFW_ARROW_CURSOR, XC_left_ptr);
|
||||||
C(GLFW_IBEAM_CURSOR, XC_xterm);
|
C(GLFW_IBEAM_CURSOR, XC_xterm);
|
||||||
C(GLFW_CROSSHAIR_CURSOR, XC_crosshair);
|
C(GLFW_CROSSHAIR_CURSOR, XC_crosshair);
|
||||||
C(GLFW_HAND_CURSOR, XC_hand2);
|
C(GLFW_HAND_CURSOR, XC_hand2);
|
||||||
@@ -2654,7 +2726,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
|||||||
XFreeCursor(_glfw.x11.display, cursor->x11.handle);
|
XFreeCursor(_glfw.x11.display, cursor->x11.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor UNUSED)
|
||||||
{
|
{
|
||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||||
{
|
{
|
||||||
@@ -2665,8 +2737,9 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
|
|
||||||
void _glfwPlatformSetClipboardString(const char* string)
|
void _glfwPlatformSetClipboardString(const char* string)
|
||||||
{
|
{
|
||||||
|
char* copy = _glfw_strdup(string);
|
||||||
free(_glfw.x11.clipboardString);
|
free(_glfw.x11.clipboardString);
|
||||||
_glfw.x11.clipboardString = _glfw_strdup(string);
|
_glfw.x11.clipboardString = copy;
|
||||||
|
|
||||||
XSetSelectionOwner(_glfw.x11.display,
|
XSetSelectionOwner(_glfw.x11.display,
|
||||||
_glfw.x11.CLIPBOARD,
|
_glfw.x11.CLIPBOARD,
|
||||||
@@ -2880,7 +2953,7 @@ GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
|
|||||||
return window->x11.handle;
|
return window->x11.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwGetXKBScancode(const char* keyName, bool caseSensitive) {
|
GLFWAPI int glfwGetNativeKeyForName(const char* keyName, bool caseSensitive) {
|
||||||
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
return glfw_xkb_keysym_from_name(keyName, caseSensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
250
glfw/xkb_glfw.c
vendored
250
glfw/xkb_glfw.c
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "xkb_glfw.h"
|
#include "xkb_glfw.h"
|
||||||
|
START_ALLOW_CASE_RANGE
|
||||||
|
|
||||||
#define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__);
|
#define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__);
|
||||||
|
|
||||||
@@ -36,19 +37,131 @@
|
|||||||
#define map_key(key) \
|
#define map_key(key) \
|
||||||
switch(key) { \
|
switch(key) { \
|
||||||
S(space, SPACE); \
|
S(space, SPACE); \
|
||||||
|
S(exclam, EXCLAM); \
|
||||||
|
S(quotedbl, DOUBLE_QUOTE); \
|
||||||
|
S(numbersign, NUMBER_SIGN); \
|
||||||
|
S(dollar, DOLLAR); \
|
||||||
|
S(ampersand, AMPERSAND); \
|
||||||
S(apostrophe, APOSTROPHE); \
|
S(apostrophe, APOSTROPHE); \
|
||||||
|
S(parenleft, PARENTHESIS_LEFT); \
|
||||||
|
S(parenright, PARENTHESIS_RIGHT); \
|
||||||
|
S(plus, PLUS); \
|
||||||
S(comma, COMMA); \
|
S(comma, COMMA); \
|
||||||
S(minus, MINUS); \
|
S(minus, MINUS); \
|
||||||
S(period, PERIOD); \
|
S(period, PERIOD); \
|
||||||
S(slash, SLASH); \
|
S(slash, SLASH); \
|
||||||
|
R(0, 9, 0, 9); \
|
||||||
|
S(colon, COLON); \
|
||||||
S(semicolon, SEMICOLON); \
|
S(semicolon, SEMICOLON); \
|
||||||
|
S(less, LESS); \
|
||||||
S(equal, EQUAL); \
|
S(equal, EQUAL); \
|
||||||
|
S(greater, GREATER); \
|
||||||
|
S(at, AT); \
|
||||||
|
D(A, Z, A, Z); \
|
||||||
S(bracketleft, LEFT_BRACKET); \
|
S(bracketleft, LEFT_BRACKET); \
|
||||||
S(backslash, BACKSLASH); \
|
S(backslash, BACKSLASH); \
|
||||||
S(bracketright, RIGHT_BRACKET); \
|
S(bracketright, RIGHT_BRACKET); \
|
||||||
S(plus, PLUS); \
|
S(asciicircum, CIRCUMFLEX); \
|
||||||
S(underscore, UNDERSCORE); \
|
S(underscore, UNDERSCORE); \
|
||||||
S(grave, GRAVE_ACCENT); \
|
S(grave, GRAVE_ACCENT); \
|
||||||
|
R(a, z, A, Z); \
|
||||||
|
S(paragraph, PARAGRAPH); \
|
||||||
|
S(masculine, MASCULINE); \
|
||||||
|
S(agrave, A_GRAVE); \
|
||||||
|
F(Agrave, A_GRAVE); \
|
||||||
|
S(adiaeresis, A_DIAERESIS); \
|
||||||
|
F(Adiaeresis, A_DIAERESIS); \
|
||||||
|
S(aring, A_RING); \
|
||||||
|
F(Aring, A_RING); \
|
||||||
|
S(ae, AE); \
|
||||||
|
F(AE, AE); \
|
||||||
|
S(ccedilla, C_CEDILLA); \
|
||||||
|
F(Ccedilla, C_CEDILLA); \
|
||||||
|
S(egrave, E_GRAVE); \
|
||||||
|
F(Egrave, E_GRAVE); \
|
||||||
|
S(aacute, E_ACUTE); \
|
||||||
|
F(Eacute, E_ACUTE); \
|
||||||
|
S(igrave, I_GRAVE); \
|
||||||
|
F(Igrave, I_GRAVE); \
|
||||||
|
S(ntilde, N_TILDE); \
|
||||||
|
F(Ntilde, N_TILDE); \
|
||||||
|
S(ograve, O_GRAVE); \
|
||||||
|
F(Ograve, O_GRAVE); \
|
||||||
|
S(odiaeresis, O_DIAERESIS); \
|
||||||
|
F(Odiaeresis, O_DIAERESIS); \
|
||||||
|
S(oslash, O_SLASH); \
|
||||||
|
F(Oslash, O_SLASH); \
|
||||||
|
S(ugrave, U_GRAVE); \
|
||||||
|
F(Ugrave, U_GRAVE); \
|
||||||
|
S(udiaeresis, U_DIAERESIS); \
|
||||||
|
F(Udiaeresis, U_DIAERESIS); \
|
||||||
|
S(ssharp, S_SHARP); \
|
||||||
|
S(Cyrillic_a, CYRILLIC_A); \
|
||||||
|
F(Cyrillic_A, CYRILLIC_A); \
|
||||||
|
S(Cyrillic_be, CYRILLIC_BE); \
|
||||||
|
F(Cyrillic_BE, CYRILLIC_BE); \
|
||||||
|
S(Cyrillic_ve, CYRILLIC_VE); \
|
||||||
|
F(Cyrillic_VE, CYRILLIC_VE); \
|
||||||
|
S(Cyrillic_ghe, CYRILLIC_GHE); \
|
||||||
|
F(Cyrillic_GHE, CYRILLIC_GHE); \
|
||||||
|
S(Cyrillic_de, CYRILLIC_DE); \
|
||||||
|
F(Cyrillic_DE, CYRILLIC_DE); \
|
||||||
|
S(Cyrillic_ie, CYRILLIC_IE); \
|
||||||
|
F(Cyrillic_IE, CYRILLIC_IE); \
|
||||||
|
S(Cyrillic_zhe, CYRILLIC_ZHE); \
|
||||||
|
F(Cyrillic_ZHE, CYRILLIC_ZHE); \
|
||||||
|
S(Cyrillic_ze, CYRILLIC_ZE); \
|
||||||
|
F(Cyrillic_ZE, CYRILLIC_ZE); \
|
||||||
|
S(Cyrillic_i, CYRILLIC_I); \
|
||||||
|
F(Cyrillic_I, CYRILLIC_I); \
|
||||||
|
S(Cyrillic_shorti, CYRILLIC_SHORT_I); \
|
||||||
|
F(Cyrillic_SHORTI, CYRILLIC_SHORT_I); \
|
||||||
|
S(Cyrillic_ka, CYRILLIC_KA); \
|
||||||
|
F(Cyrillic_KA, CYRILLIC_KA); \
|
||||||
|
S(Cyrillic_el, CYRILLIC_EL); \
|
||||||
|
F(Cyrillic_EL, CYRILLIC_EL); \
|
||||||
|
S(Cyrillic_em, CYRILLIC_EM); \
|
||||||
|
F(Cyrillic_EM, CYRILLIC_EM); \
|
||||||
|
S(Cyrillic_en, CYRILLIC_EN); \
|
||||||
|
F(Cyrillic_EN, CYRILLIC_EN); \
|
||||||
|
S(Cyrillic_o, CYRILLIC_O); \
|
||||||
|
F(Cyrillic_O, CYRILLIC_O); \
|
||||||
|
S(Cyrillic_pe, CYRILLIC_PE); \
|
||||||
|
F(Cyrillic_PE, CYRILLIC_PE); \
|
||||||
|
S(Cyrillic_er, CYRILLIC_ER); \
|
||||||
|
F(Cyrillic_ER, CYRILLIC_ER); \
|
||||||
|
S(Cyrillic_es, CYRILLIC_ES); \
|
||||||
|
F(Cyrillic_ES, CYRILLIC_ES); \
|
||||||
|
S(Cyrillic_te, CYRILLIC_TE); \
|
||||||
|
F(Cyrillic_TE, CYRILLIC_TE); \
|
||||||
|
S(Cyrillic_u, CYRILLIC_U); \
|
||||||
|
F(Cyrillic_U, CYRILLIC_U); \
|
||||||
|
S(Cyrillic_ef, CYRILLIC_EF); \
|
||||||
|
F(Cyrillic_EF, CYRILLIC_EF); \
|
||||||
|
S(Cyrillic_ha, CYRILLIC_HA); \
|
||||||
|
F(Cyrillic_HA, CYRILLIC_HA); \
|
||||||
|
S(Cyrillic_tse, CYRILLIC_TSE); \
|
||||||
|
F(Cyrillic_TSE, CYRILLIC_TSE); \
|
||||||
|
S(Cyrillic_che, CYRILLIC_CHE); \
|
||||||
|
F(Cyrillic_CHE, CYRILLIC_CHE); \
|
||||||
|
S(Cyrillic_sha, CYRILLIC_SHA); \
|
||||||
|
F(Cyrillic_SHA, CYRILLIC_SHA); \
|
||||||
|
S(Cyrillic_shcha, CYRILLIC_SHCHA); \
|
||||||
|
F(Cyrillic_SHCHA, CYRILLIC_SHCHA); \
|
||||||
|
S(Cyrillic_hardsign, CYRILLIC_HARD_SIGN); \
|
||||||
|
F(Cyrillic_HARDSIGN, CYRILLIC_HARD_SIGN); \
|
||||||
|
S(Cyrillic_yeru, CYRILLIC_YERU); \
|
||||||
|
F(Cyrillic_YERU, CYRILLIC_YERU); \
|
||||||
|
S(Cyrillic_softsign, CYRILLIC_SOFT_SIGN); \
|
||||||
|
F(Cyrillic_SOFTSIGN, CYRILLIC_SOFT_SIGN); \
|
||||||
|
S(Cyrillic_e, CYRILLIC_E); \
|
||||||
|
F(Cyrillic_E, CYRILLIC_E); \
|
||||||
|
S(Cyrillic_yu, CYRILLIC_YU); \
|
||||||
|
F(Cyrillic_YU, CYRILLIC_YU); \
|
||||||
|
S(Cyrillic_ya, CYRILLIC_YA); \
|
||||||
|
F(Cyrillic_YA, CYRILLIC_YA); \
|
||||||
|
S(Cyrillic_io, CYRILLIC_IO); \
|
||||||
|
F(Cyrillic_IO, CYRILLIC_IO); \
|
||||||
S(Escape, ESCAPE); \
|
S(Escape, ESCAPE); \
|
||||||
S(Return, ENTER); \
|
S(Return, ENTER); \
|
||||||
S(Tab, TAB); \
|
S(Tab, TAB); \
|
||||||
@@ -90,9 +203,6 @@
|
|||||||
S(Alt_R, RIGHT_ALT); \
|
S(Alt_R, RIGHT_ALT); \
|
||||||
S(Super_R, RIGHT_SUPER); \
|
S(Super_R, RIGHT_SUPER); \
|
||||||
S(Menu, MENU); \
|
S(Menu, MENU); \
|
||||||
R(0, 9, 0, 9); \
|
|
||||||
R(a, z, A, Z); \
|
|
||||||
D(A, Z, A, Z); \
|
|
||||||
R(F1, F25, F1, F25); \
|
R(F1, F25, F1, F25); \
|
||||||
R(KP_0, KP_9, KP_0, KP_9); \
|
R(KP_0, KP_9, KP_0, KP_9); \
|
||||||
|
|
||||||
@@ -101,7 +211,7 @@ glfw_key_for_sym(xkb_keysym_t key) {
|
|||||||
#define S(f, t) case XKB_KEY_##f: return GLFW_KEY_##t
|
#define S(f, t) case XKB_KEY_##f: return GLFW_KEY_##t
|
||||||
#define F(f, t) S(f, t)
|
#define F(f, t) S(f, t)
|
||||||
#define R(s, e, gs, ...) case XKB_KEY_##s ... XKB_KEY_##e: return GLFW_KEY_##gs + key - XKB_KEY_##s
|
#define R(s, e, gs, ...) case XKB_KEY_##s ... XKB_KEY_##e: return GLFW_KEY_##gs + key - XKB_KEY_##s
|
||||||
#define D(s, e, gs, ...) R(s, e, gs)
|
#define D(s, e, gs, ...) R(s, e, gs, __VA_ARGS__)
|
||||||
map_key(key)
|
map_key(key)
|
||||||
S(KP_Up, UP);
|
S(KP_Up, UP);
|
||||||
S(KP_Down, DOWN);
|
S(KP_Down, DOWN);
|
||||||
@@ -115,7 +225,7 @@ glfw_key_for_sym(xkb_keysym_t key) {
|
|||||||
#undef D
|
#undef D
|
||||||
#undef R
|
#undef R
|
||||||
#undef S
|
#undef S
|
||||||
};
|
}
|
||||||
|
|
||||||
xkb_keysym_t
|
xkb_keysym_t
|
||||||
glfw_xkb_sym_for_key(int key) {
|
glfw_xkb_sym_for_key(int key) {
|
||||||
@@ -133,6 +243,7 @@ glfw_xkb_sym_for_key(int key) {
|
|||||||
#undef R
|
#undef R
|
||||||
#undef S
|
#undef S
|
||||||
}
|
}
|
||||||
|
END_ALLOW_CASE_RANGE
|
||||||
|
|
||||||
#ifdef _GLFW_X11
|
#ifdef _GLFW_X11
|
||||||
|
|
||||||
@@ -167,7 +278,7 @@ glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
|
|||||||
if (conn) keymap = xkb_x11_keymap_new_from_device(xkb->context, conn, xkb->keyboard_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); \
|
if (conn) keymap = xkb_x11_keymap_new_from_device(xkb->context, conn, xkb->keyboard_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define xkb_glfw_load_state(keymap, state, ...) {\
|
#define xkb_glfw_load_state(keymap, state) {\
|
||||||
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \
|
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \
|
||||||
if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \
|
if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \
|
||||||
}
|
}
|
||||||
@@ -175,7 +286,7 @@ glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
|
#define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
|
||||||
#define xkb_glfw_load_state(keymap, state, ...) state = xkb_state_new(keymap);
|
#define xkb_glfw_load_state(keymap, state) state = xkb_state_new(keymap);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -327,24 +438,22 @@ glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_m
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
|
glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode) {
|
||||||
#ifdef _GLFW_WAYLAND
|
#ifdef _GLFW_WAYLAND
|
||||||
scancode += 8;
|
keycode += 8;
|
||||||
#endif
|
#endif
|
||||||
return xkb_keymap_key_repeats(xkb->keymap, scancode);
|
return xkb_keymap_key_repeats(xkb->keymap, keycode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static KeyEvent key_event = {};
|
|
||||||
|
|
||||||
static inline xkb_keysym_t
|
static inline xkb_keysym_t
|
||||||
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed) {
|
compose_symbol(struct xkb_compose_state *composeState, xkb_keysym_t sym, int *compose_completed, char *key_text, int n) {
|
||||||
*compose_completed = 0;
|
*compose_completed = 0;
|
||||||
if (sym == XKB_KEY_NoSymbol || !composeState) return sym;
|
if (sym == XKB_KEY_NoSymbol || !composeState) return sym;
|
||||||
if (xkb_compose_state_feed(composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED) return sym;
|
if (xkb_compose_state_feed(composeState, sym) != XKB_COMPOSE_FEED_ACCEPTED) return sym;
|
||||||
switch (xkb_compose_state_get_status(composeState)) {
|
switch (xkb_compose_state_get_status(composeState)) {
|
||||||
case XKB_COMPOSE_COMPOSED:
|
case XKB_COMPOSE_COMPOSED:
|
||||||
xkb_compose_state_get_utf8(composeState, key_event.text, sizeof(key_event.text));
|
xkb_compose_state_get_utf8(composeState, key_text, n);
|
||||||
*compose_completed = 1;
|
*compose_completed = 1;
|
||||||
return xkb_compose_state_get_one_sym(composeState);
|
return xkb_compose_state_get_one_sym(composeState);
|
||||||
case XKB_COMPOSE_COMPOSING:
|
case XKB_COMPOSE_COMPOSING:
|
||||||
@@ -424,66 +533,74 @@ glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, i
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
|
glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed) {
|
||||||
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
|
_GLFWwindow *window = _glfwWindowForId(ev->window_id);
|
||||||
if (failed && window && window->callbacks.keyboard) {
|
if (failed && window && window->callbacks.keyboard) {
|
||||||
// notify application to remove any existing pre-edit text
|
// notify application to remove any existing pre-edit text
|
||||||
window->callbacks.keyboard((GLFWwindow*) window, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0, "", 1);
|
GLFWkeyevent fake_ev;
|
||||||
|
_glfwInitializeKeyEvent(&fake_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0);
|
||||||
|
fake_ev.ime_state = 1;
|
||||||
|
window->callbacks.keyboard((GLFWwindow*) window, &fake_ev);
|
||||||
}
|
}
|
||||||
static xkb_keycode_t last_handled_press_keycode = 0;
|
static xkb_keycode_t last_handled_press_keycode = 0;
|
||||||
// We filter out release events that correspond to the last press event
|
// We filter out release events that correspond to the last press event
|
||||||
// handled by the IME system. This wont fix the case of multiple key
|
// handled by the IME system. This won't fix the case of multiple key
|
||||||
// presses before a release, but is better than nothing. For that case
|
// presses before a release, but is better than nothing. For that case
|
||||||
// you'd need to implement a ring buffer to store pending key presses.
|
// you'd need to implement a ring buffer to store pending key presses.
|
||||||
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
|
xkb_keycode_t prev_handled_press = last_handled_press_keycode;
|
||||||
last_handled_press_keycode = 0;
|
last_handled_press_keycode = 0;
|
||||||
bool is_release = ev->action == GLFW_RELEASE;
|
bool is_release = ev->glfw_ev.action == GLFW_RELEASE;
|
||||||
debug("From IBUS: scancode: 0x%x name: %s is_release: %d\n", ev->keycode, glfw_xkb_keysym_name(ev->keysym), is_release);
|
debug("From IBUS: native_key: 0x%x name: %s is_release: %d\n", ev->glfw_ev.native_key, glfw_xkb_keysym_name(ev->glfw_ev.key), is_release);
|
||||||
if (window && !handled_by_ime && !(is_release && ev->keycode == prev_handled_press)) {
|
if (window && !handled_by_ime && !(is_release && ev->glfw_ev.native_key == (int) prev_handled_press)) {
|
||||||
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
|
debug("↳ to application: glfw_keycode: 0x%x (%s) keysym: 0x%x (%s) action: %s %s text: %s\n",
|
||||||
ev->glfw_keycode, _glfwGetKeyName(ev->glfw_keycode), ev->keysym, glfw_xkb_keysym_name(ev->keysym),
|
ev->glfw_ev.native_key, _glfwGetKeyName(ev->glfw_ev.native_key), ev->glfw_ev.key, glfw_xkb_keysym_name(ev->glfw_ev.key),
|
||||||
(ev->action == GLFW_RELEASE ? "RELEASE" : (ev->action == GLFW_PRESS ? "PRESS" : "REPEAT")),
|
(ev->glfw_ev.action == GLFW_RELEASE ? "RELEASE" : (ev->glfw_ev.action == GLFW_PRESS ? "PRESS" : "REPEAT")),
|
||||||
format_mods(ev->glfw_modifiers), ev->text
|
format_mods(ev->glfw_ev.mods), ev->glfw_ev.text
|
||||||
);
|
);
|
||||||
_glfwInputKeyboard(window, ev->glfw_keycode, ev->keysym, ev->action, ev->glfw_modifiers, ev->text, 0);
|
|
||||||
|
ev->glfw_ev.ime_state = 0;
|
||||||
|
_glfwInputKeyboard(window, &ev->glfw_ev);
|
||||||
} else debug("↳ discarded\n");
|
} else debug("↳ discarded\n");
|
||||||
if (!is_release && handled_by_ime) last_handled_press_keycode = ev->keycode;
|
if (!is_release && handled_by_ime)
|
||||||
|
last_handled_press_keycode = ev->glfw_ev.native_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) {
|
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t xkb_keycode, int action) {
|
||||||
|
static char key_text[64] = {0};
|
||||||
const xkb_keysym_t *syms, *clean_syms, *default_syms;
|
const xkb_keysym_t *syms, *clean_syms, *default_syms;
|
||||||
xkb_keysym_t glfw_sym;
|
xkb_keysym_t xkb_sym;
|
||||||
xkb_keycode_t code_for_sym = scancode;
|
xkb_keycode_t code_for_sym = xkb_keycode, ibus_keycode = xkb_keycode;
|
||||||
key_event.ibus_keycode = scancode;
|
GLFWkeyevent glfw_ev;
|
||||||
|
_glfwInitializeKeyEvent(&glfw_ev, GLFW_KEY_UNKNOWN, 0, GLFW_PRESS, 0); // init with default values
|
||||||
#ifdef _GLFW_WAYLAND
|
#ifdef _GLFW_WAYLAND
|
||||||
code_for_sym += 8;
|
code_for_sym += 8;
|
||||||
#else
|
#else
|
||||||
key_event.ibus_keycode -= 8;
|
ibus_keycode -= 8;
|
||||||
#endif
|
#endif
|
||||||
debug("%s scancode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", scancode);
|
debug("%s xkb_keycode: 0x%x ", action == GLFW_RELEASE ? "Release" : "Press", xkb_keycode);
|
||||||
XKBStateGroup *sg = &xkb->states;
|
XKBStateGroup *sg = &xkb->states;
|
||||||
int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms);
|
int num_syms = xkb_state_key_get_syms(sg->state, code_for_sym, &syms);
|
||||||
int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms);
|
int num_clean_syms = xkb_state_key_get_syms(sg->clean_state, code_for_sym, &clean_syms);
|
||||||
key_event.text[0] = 0;
|
key_text[0] = 0;
|
||||||
// According to the documentation of xkb_compose_state_feed it does not
|
// According to the documentation of xkb_compose_state_feed it does not
|
||||||
// support multi-sym events, so we ignore them
|
// support multi-sym events, so we ignore them
|
||||||
if (num_syms != 1 || num_clean_syms != 1) {
|
if (num_syms != 1 || num_clean_syms != 1) {
|
||||||
debug("num_syms: %d num_clean_syms: %d ignoring event\n", num_syms, num_clean_syms);
|
debug("num_syms: %d num_clean_syms: %d ignoring event\n", num_syms, num_clean_syms);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glfw_sym = clean_syms[0];
|
xkb_sym = clean_syms[0];
|
||||||
debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
|
debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
|
||||||
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
|
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
|
||||||
const char *text_type = "composed_text";
|
const char *text_type = "composed_text";
|
||||||
int compose_completed;
|
int compose_completed;
|
||||||
glfw_sym = compose_symbol(sg->composeState, syms[0], &compose_completed);
|
xkb_sym = compose_symbol(sg->composeState, syms[0], &compose_completed, key_text, sizeof(key_text));
|
||||||
if (glfw_sym == XKB_KEY_NoSymbol && !compose_completed) {
|
if (xkb_sym == XKB_KEY_NoSymbol && !compose_completed) {
|
||||||
debug("compose not complete, ignoring.\n");
|
debug("compose not complete, ignoring.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug("composed_sym: %s ", glfw_xkb_keysym_name(glfw_sym));
|
debug("composed_sym: %s ", glfw_xkb_keysym_name(xkb_sym));
|
||||||
if (glfw_sym == syms[0]) { // composed sym is the same as non-composed sym
|
if (xkb_sym == syms[0]) { // composed sym is the same as non-composed sym
|
||||||
// Only use the clean_sym if no mods other than the mods we report
|
// Only use the clean_sym if no mods other than the mods we report
|
||||||
// are active (for example if ISO_Shift_Level_* mods are active
|
// are active (for example if ISO_Shift_Level_* mods are active
|
||||||
// they are not reported by GLFW so the key should be the shifted
|
// they are not reported by GLFW so the key should be the shifted
|
||||||
@@ -491,37 +608,58 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
|
|||||||
xkb_mod_mask_t consumed_unknown_mods = xkb_state_key_get_consumed_mods(sg->state, code_for_sym) & sg->activeUnknownModifiers;
|
xkb_mod_mask_t consumed_unknown_mods = xkb_state_key_get_consumed_mods(sg->state, code_for_sym) & sg->activeUnknownModifiers;
|
||||||
if (sg->activeUnknownModifiers) debug("%s", format_xkb_mods(xkb, "active_unknown_mods", sg->activeUnknownModifiers));
|
if (sg->activeUnknownModifiers) debug("%s", format_xkb_mods(xkb, "active_unknown_mods", sg->activeUnknownModifiers));
|
||||||
if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); }
|
if (consumed_unknown_mods) { debug("%s", format_xkb_mods(xkb, "consumed_unknown_mods", consumed_unknown_mods)); }
|
||||||
else glfw_sym = clean_syms[0];
|
else xkb_sym = clean_syms[0];
|
||||||
// xkb returns text even if alt and/or super are pressed
|
// xkb returns text even if alt and/or super are pressed
|
||||||
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) xkb_state_key_get_utf8(sg->state, code_for_sym, key_event.text, sizeof(key_event.text));
|
if ( ((GLFW_MOD_CONTROL | GLFW_MOD_ALT | GLFW_MOD_SUPER) & sg->modifiers) == 0) {
|
||||||
|
xkb_state_key_get_utf8(sg->state, code_for_sym, key_text, sizeof(key_text));
|
||||||
|
}
|
||||||
text_type = "text";
|
text_type = "text";
|
||||||
}
|
}
|
||||||
if ((1 <= key_event.text[0] && key_event.text[0] <= 31) || key_event.text[0] == 127) key_event.text[0] = 0; // don't send text for ascii control codes
|
if ((1 <= key_text[0] && key_text[0] <= 31) || key_text[0] == 127) {
|
||||||
if (key_event.text[0]) { debug("%s: %s ", text_type, key_event.text); }
|
key_text[0] = 0; // don't send text for ascii control codes
|
||||||
|
}
|
||||||
|
if (key_text[0]) { debug("%s: %s ", text_type, key_text); }
|
||||||
}
|
}
|
||||||
int glfw_keycode = glfw_key_for_sym(glfw_sym);
|
int glfw_sym = glfw_key_for_sym(xkb_sym);
|
||||||
bool is_fallback = false;
|
bool is_fallback = false;
|
||||||
if (glfw_keycode == GLFW_KEY_UNKNOWN && !key_event.text[0]) {
|
if (glfw_sym == GLFW_KEY_UNKNOWN && !key_text[0]) {
|
||||||
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
|
int num_default_syms = xkb_state_key_get_syms(sg->default_state, code_for_sym, &default_syms);
|
||||||
if (num_default_syms > 0) {
|
if (num_default_syms > 0) {
|
||||||
glfw_sym = default_syms[0];
|
xkb_sym = default_syms[0];
|
||||||
glfw_keycode = glfw_key_for_sym(glfw_sym);
|
glfw_sym = glfw_key_for_sym(xkb_sym);
|
||||||
is_fallback = true;
|
is_fallback = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug(
|
debug(
|
||||||
"%s%s: %d (%s) xkb_key: %d (%s)\n",
|
"%s%s: %d (%s) xkb_key: %d (%s)\n",
|
||||||
format_mods(sg->modifiers),
|
format_mods(sg->modifiers),
|
||||||
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_keycode, _glfwGetKeyName(glfw_keycode),
|
is_fallback ? "glfw_fallback_key" : "glfw_key", glfw_sym, _glfwGetKeyName(glfw_sym),
|
||||||
glfw_sym, glfw_xkb_keysym_name(glfw_sym)
|
xkb_sym, glfw_xkb_keysym_name(xkb_sym)
|
||||||
);
|
);
|
||||||
key_event.action = action; key_event.glfw_modifiers = sg->modifiers;
|
|
||||||
key_event.keycode = scancode; key_event.keysym = glfw_sym;
|
// NOTE: On linux, the reported native key identifier is the XKB keysym value.
|
||||||
key_event.window_id = window->id; key_event.glfw_keycode = glfw_keycode;
|
// Do not confuse `native_key` with `xkb_keycode` (the native keycode reported for the
|
||||||
key_event.ibus_sym = syms[0];
|
// glfw event VS the X internal code for a key).
|
||||||
if (ibus_process_key(&key_event, &xkb->ibus)) {
|
//
|
||||||
debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", key_event.ibus_keycode, key_event.ibus_sym, glfw_xkb_keysym_name(key_event.ibus_sym), format_mods(key_event.glfw_modifiers));
|
// We use the XKB keysym instead of the X keycode to be able to go back-and-forth between
|
||||||
|
// the GLFW keysym and the XKB keysym when needed, which is not possible using the X keycode,
|
||||||
|
// because of the lost information when resolving the keycode to the keysym, like consumed
|
||||||
|
// mods.
|
||||||
|
glfw_ev.native_key = xkb_sym;
|
||||||
|
|
||||||
|
glfw_ev.action = action;
|
||||||
|
glfw_ev.key = glfw_sym;
|
||||||
|
glfw_ev.mods = sg->modifiers;
|
||||||
|
glfw_ev.text = key_text;
|
||||||
|
|
||||||
|
_GLFWIBUSKeyEvent ibus_ev;
|
||||||
|
ibus_ev.glfw_ev = glfw_ev;
|
||||||
|
ibus_ev.ibus_keycode = ibus_keycode;
|
||||||
|
ibus_ev.window_id = window->id;
|
||||||
|
ibus_ev.ibus_keysym = syms[0];
|
||||||
|
if (ibus_process_key(&ibus_ev, &xkb->ibus)) {
|
||||||
|
debug("↳ to IBUS: keycode: 0x%x keysym: 0x%x (%s) %s\n", ibus_ev.ibus_keycode, ibus_ev.ibus_keysym, glfw_xkb_keysym_name(ibus_ev.ibus_keysym), format_mods(ibus_ev.glfw_ev.mods));
|
||||||
} else {
|
} else {
|
||||||
_glfwInputKeyboard(window, glfw_keycode, glfw_sym, action, sg->modifiers, key_event.text, 0);
|
_glfwInputKeyboard(window, &glfw_ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
glfw/xkb_glfw.h
vendored
12
glfw/xkb_glfw.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
// GLFW 3.3 XKB - www.glfw.org
|
// GLFW 3.4 XKB - www.glfw.org
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
// Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
//
|
//
|
||||||
@@ -67,8 +67,8 @@ typedef struct {
|
|||||||
|
|
||||||
#ifdef _GLFW_X11
|
#ifdef _GLFW_X11
|
||||||
int32_t keyboard_device_id;
|
int32_t keyboard_device_id;
|
||||||
bool available;
|
bool available;
|
||||||
bool detectable;
|
bool detectable;
|
||||||
int majorOpcode;
|
int majorOpcode;
|
||||||
int eventBase;
|
int eventBase;
|
||||||
int errorBase;
|
int errorBase;
|
||||||
@@ -87,10 +87,10 @@ void glfw_xkb_release(_GLFWXKBData *xkb);
|
|||||||
bool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
bool glfw_xkb_create_context(_GLFWXKBData *xkb);
|
||||||
bool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
|
bool glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str);
|
||||||
void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group);
|
void glfw_xkb_update_modifiers(_GLFWXKBData *xkb, xkb_mod_mask_t depressed, xkb_mod_mask_t latched, xkb_mod_mask_t locked, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group);
|
||||||
bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode);
|
bool glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t keycode);
|
||||||
const char* glfw_xkb_keysym_name(xkb_keysym_t sym);
|
const char* glfw_xkb_keysym_name(xkb_keysym_t sym);
|
||||||
xkb_keysym_t glfw_xkb_sym_for_key(int key);
|
xkb_keysym_t glfw_xkb_sym_for_key(int key);
|
||||||
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action);
|
void glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t keycode, int action);
|
||||||
int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive);
|
int glfw_xkb_keysym_from_name(const char *name, bool case_sensitive);
|
||||||
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
|
void glfw_xkb_update_ime_state(_GLFWwindow *w, _GLFWXKBData *xkb, int which, int a, int b, int c, int d);
|
||||||
void glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed);
|
void glfw_xkb_key_from_ime(_GLFWIBUSKeyEvent *ev, bool handled_by_ime, bool failed);
|
||||||
|
|||||||
@@ -4,27 +4,34 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
|
from typing import TYPE_CHECKING, List, Optional, Tuple
|
||||||
|
|
||||||
from kitty.cli import parse_args
|
from kitty.cli import parse_args
|
||||||
|
from kitty.cli_stub import AskCLIOptions
|
||||||
from kitty.constants import cache_dir
|
from kitty.constants import cache_dir
|
||||||
|
from kitty.typing import BossType
|
||||||
|
|
||||||
|
from ..tui.handler import result_handler
|
||||||
from ..tui.operations import alternate_screen, styled
|
from ..tui.operations import alternate_screen, styled
|
||||||
|
|
||||||
readline = None
|
if TYPE_CHECKING:
|
||||||
|
import readline
|
||||||
|
else:
|
||||||
|
readline = None
|
||||||
|
|
||||||
|
|
||||||
def get_history_items():
|
def get_history_items() -> List[str]:
|
||||||
return list(map(readline.get_history_item, range(1, readline.get_current_history_length() + 1)))
|
return list(map(readline.get_history_item, range(1, readline.get_current_history_length() + 1)))
|
||||||
|
|
||||||
|
|
||||||
def sort_key(item):
|
def sort_key(item: str) -> Tuple[int, str]:
|
||||||
return len(item), item.lower()
|
return len(item), item.lower()
|
||||||
|
|
||||||
|
|
||||||
class HistoryCompleter:
|
class HistoryCompleter:
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self, name: Optional[str] = None):
|
||||||
self.matches = []
|
self.matches: List[str] = []
|
||||||
self.history_path = None
|
self.history_path = None
|
||||||
if name:
|
if name:
|
||||||
ddir = os.path.join(cache_dir(), 'ask')
|
ddir = os.path.join(cache_dir(), 'ask')
|
||||||
@@ -32,7 +39,7 @@ class HistoryCompleter:
|
|||||||
os.makedirs(ddir)
|
os.makedirs(ddir)
|
||||||
self.history_path = os.path.join(ddir, name)
|
self.history_path = os.path.join(ddir, name)
|
||||||
|
|
||||||
def complete(self, text, state):
|
def complete(self, text: str, state: int) -> Optional[str]:
|
||||||
response = None
|
response = None
|
||||||
if state == 0:
|
if state == 0:
|
||||||
history_values = get_history_items()
|
history_values = get_history_items()
|
||||||
@@ -47,19 +54,19 @@ class HistoryCompleter:
|
|||||||
response = None
|
response = None
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self) -> 'HistoryCompleter':
|
||||||
if self.history_path:
|
if self.history_path:
|
||||||
with suppress(Exception):
|
with suppress(Exception):
|
||||||
readline.read_history_file(self.history_path)
|
readline.read_history_file(self.history_path)
|
||||||
readline.set_completer(self.complete)
|
readline.set_completer(self.complete)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, *a):
|
def __exit__(self, *a: object) -> None:
|
||||||
if self.history_path:
|
if self.history_path:
|
||||||
readline.write_history_file(self.history_path)
|
readline.write_history_file(self.history_path)
|
||||||
|
|
||||||
|
|
||||||
def option_text():
|
def option_text() -> str:
|
||||||
return '''\
|
return '''\
|
||||||
--type -t
|
--type -t
|
||||||
choices=line
|
choices=line
|
||||||
@@ -78,7 +85,18 @@ be used for completions and via the browse history readline bindings.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
try:
|
||||||
|
from typing import TypedDict
|
||||||
|
except ImportError:
|
||||||
|
TypedDict = dict
|
||||||
|
|
||||||
|
|
||||||
|
class Response(TypedDict):
|
||||||
|
items: List[str]
|
||||||
|
response: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
|
def main(args: List[str]) -> Response:
|
||||||
# For some reason importing readline in a key handler in the main kitty process
|
# For some reason importing readline in a key handler in the main kitty process
|
||||||
# causes a crash of the python interpreter, probably because of some global
|
# causes a crash of the python interpreter, probably because of some global
|
||||||
# lock
|
# lock
|
||||||
@@ -88,7 +106,7 @@ def main(args):
|
|||||||
from kitty.shell import init_readline
|
from kitty.shell import init_readline
|
||||||
msg = 'Ask the user for input'
|
msg = 'Ask the user for input'
|
||||||
try:
|
try:
|
||||||
args, items = parse_args(args[1:], option_text, '', msg, 'kitty ask')
|
cli_opts, items = parse_args(args[1:], option_text, '', msg, 'kitty ask', result_class=AskCLIOptions)
|
||||||
except SystemExit as e:
|
except SystemExit as e:
|
||||||
if e.code != 0:
|
if e.code != 0:
|
||||||
print(e.args[0])
|
print(e.args[0])
|
||||||
@@ -96,20 +114,21 @@ def main(args):
|
|||||||
raise SystemExit(e.code)
|
raise SystemExit(e.code)
|
||||||
|
|
||||||
init_readline(readline)
|
init_readline(readline)
|
||||||
ans = {'items': items}
|
response = None
|
||||||
|
|
||||||
with alternate_screen(), HistoryCompleter(args.name):
|
with alternate_screen(), HistoryCompleter(cli_opts.name):
|
||||||
if args.message:
|
if cli_opts.message:
|
||||||
print(styled(args.message, bold=True))
|
print(styled(cli_opts.message, bold=True))
|
||||||
|
|
||||||
prompt = '> '
|
prompt = '> '
|
||||||
with suppress(KeyboardInterrupt, EOFError):
|
with suppress(KeyboardInterrupt, EOFError):
|
||||||
ans['response'] = input(prompt)
|
response = input(prompt)
|
||||||
return ans
|
return {'items': items, 'response': response}
|
||||||
|
|
||||||
|
|
||||||
def handle_result(args, data, target_window_id, boss):
|
@result_handler()
|
||||||
if 'response' in data:
|
def handle_result(args: List[str], data: Response, target_window_id: int, boss: BossType) -> None:
|
||||||
|
if data['response'] is not None:
|
||||||
func, *args = data['items']
|
func, *args = data['items']
|
||||||
getattr(boss, func)(data['response'], *args)
|
getattr(boss, func)(data['response'], *args)
|
||||||
|
|
||||||
|
|||||||
@@ -3,39 +3,40 @@
|
|||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Iterable, List, Union
|
||||||
|
|
||||||
|
from kitty.key_encoding import KeyEvent
|
||||||
|
|
||||||
|
from . import subseq_matcher
|
||||||
from ..tui.handler import Handler
|
from ..tui.handler import Handler
|
||||||
from ..tui.loop import Loop
|
from ..tui.loop import Loop
|
||||||
|
|
||||||
from . import subseq_matcher
|
|
||||||
|
|
||||||
|
|
||||||
def match(
|
def match(
|
||||||
input_data,
|
input_data: Union[str, bytes, Iterable[Union[str, bytes]]],
|
||||||
query,
|
query: str,
|
||||||
threads=0,
|
threads: int = 0,
|
||||||
positions=False,
|
positions: bool = False,
|
||||||
level1='/',
|
level1: str = '/',
|
||||||
level2='-_0123456789',
|
level2: str = '-_0123456789',
|
||||||
level3='.',
|
level3: str = '.',
|
||||||
limit=0,
|
limit: int = 0,
|
||||||
mark_before='',
|
mark_before: str = '',
|
||||||
mark_after='',
|
mark_after: str = '',
|
||||||
delimiter='\n'
|
delimiter: str = '\n'
|
||||||
):
|
) -> List[str]:
|
||||||
if isinstance(input_data, str):
|
if isinstance(input_data, str):
|
||||||
input_data = input_data.encode('utf-8')
|
idata = [x.encode('utf-8') for x in input_data.split(delimiter)]
|
||||||
if isinstance(input_data, bytes):
|
elif isinstance(input_data, bytes):
|
||||||
input_data = input_data.split(delimiter.encode('utf-8'))
|
idata = input_data.split(delimiter.encode('utf-8'))
|
||||||
else:
|
else:
|
||||||
input_data = [x.encode('utf-8') if isinstance(x, str) else x for x in input_data]
|
idata = [x.encode('utf-8') if isinstance(x, str) else x for x in input_data]
|
||||||
query = query.lower()
|
query = query.lower()
|
||||||
level1 = level1.lower()
|
level1 = level1.lower()
|
||||||
level2 = level2.lower()
|
level2 = level2.lower()
|
||||||
level3 = level3.lower()
|
level3 = level3.lower()
|
||||||
data = subseq_matcher.match(
|
data = subseq_matcher.match(
|
||||||
input_data, (level1, level2, level3), query,
|
idata, (level1, level2, level3), query,
|
||||||
positions, limit, threads,
|
positions, limit, threads,
|
||||||
mark_before, mark_after, delimiter)
|
mark_before, mark_after, delimiter)
|
||||||
if data is None:
|
if data is None:
|
||||||
@@ -45,23 +46,23 @@ def match(
|
|||||||
|
|
||||||
class ChooseHandler(Handler):
|
class ChooseHandler(Handler):
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_text(self, text, in_bracketed_paste=False):
|
def on_text(self, text: str, in_bracketed_paste: bool = False) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_key(self, key_event):
|
def on_key(self, key_event: KeyEvent) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_interrupt(self):
|
def on_interrupt(self) -> None:
|
||||||
self.quit_loop(1)
|
self.quit_loop(1)
|
||||||
|
|
||||||
def on_eot(self):
|
def on_eot(self) -> None:
|
||||||
self.quit_loop(1)
|
self.quit_loop(1)
|
||||||
|
|
||||||
|
|
||||||
def main(args):
|
def main(args: List[str]) -> None:
|
||||||
loop = Loop()
|
loop = Loop()
|
||||||
handler = ChooseHandler()
|
handler = ChooseHandler()
|
||||||
loop.loop(handler)
|
loop.loop(handler)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user