Compare commits
775 Commits
4.3.1
...
img-loadin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91e19bc36d | ||
|
|
30d21ef791 | ||
|
|
57b419ebb1 | ||
|
|
9d303723b0 | ||
|
|
08bd1129ad | ||
|
|
0cb0fc8317 | ||
|
|
874a3837d9 | ||
|
|
31fc5a5a54 | ||
|
|
40d81f5959 | ||
|
|
4fad97d8ab | ||
|
|
f1a8c95ca4 | ||
|
|
65a1804f05 | ||
|
|
92873e62ed | ||
|
|
0f7c33f894 | ||
|
|
6a83d38e7b | ||
|
|
f89be80562 | ||
|
|
b66fa84161 | ||
|
|
ee7f2f9702 | ||
|
|
900011808a | ||
|
|
b8ee9873f3 | ||
|
|
0c9faea358 | ||
|
|
2568611a8c | ||
|
|
4c64111b5b | ||
|
|
4f18a34dfa | ||
|
|
bc0d315e6c | ||
|
|
13d72eed2d | ||
|
|
7bafbeffcf | ||
|
|
f572ca52d2 | ||
|
|
193b383739 | ||
|
|
6785461c26 | ||
|
|
b9ee9979e7 | ||
|
|
6bbec87700 | ||
|
|
b35608a351 | ||
|
|
416763bf2d | ||
|
|
9179ebb28e | ||
|
|
bcc17b3033 | ||
|
|
00439f9e5c | ||
|
|
c9d748fc51 | ||
|
|
719eafa60c | ||
|
|
1759d27da9 | ||
|
|
53275481a5 | ||
|
|
cbe6d0da76 | ||
|
|
c349ed9562 | ||
|
|
74ce69a8a1 | ||
|
|
4f17f3ac24 | ||
|
|
9c8e464b04 | ||
|
|
51d0d13a9e | ||
|
|
0ee3b1c861 | ||
|
|
46f88c69a1 | ||
|
|
140976a670 | ||
|
|
9f2b847835 | ||
|
|
9e11ea699c | ||
|
|
1a4eebe022 | ||
|
|
2963468019 | ||
|
|
bfbd95d7d6 | ||
|
|
c1c1d4431d | ||
|
|
155a4fac5c | ||
|
|
76f481eb7b | ||
|
|
0782c8a051 | ||
|
|
3d27ff1177 | ||
|
|
3ada664a89 | ||
|
|
643a91bd08 | ||
|
|
c86733b4fa | ||
|
|
55099b7d0e | ||
|
|
db3858a204 | ||
|
|
07bff74544 | ||
|
|
b4262883a8 | ||
|
|
563c85e222 | ||
|
|
d75246a543 | ||
|
|
b3856a3ea0 | ||
|
|
bd4d24f8ed | ||
|
|
65ce3eb207 | ||
|
|
865ac44963 | ||
|
|
55a935db53 | ||
|
|
6fefae3dbb | ||
|
|
f7c84ddc7f | ||
|
|
f4a4dd2615 | ||
|
|
b718d99d1f | ||
|
|
c7215d1199 | ||
|
|
24d69ef125 | ||
|
|
7c3fbdecf2 | ||
|
|
b77938f40f | ||
|
|
f703744564 | ||
|
|
a3ccff3773 | ||
|
|
9869082c1c | ||
|
|
754212d0f9 | ||
|
|
a9b81577c6 | ||
|
|
eaa2dada54 | ||
|
|
ce2b2128bb | ||
|
|
41c25b8809 | ||
|
|
b5ff35ff3e | ||
|
|
06423d807f | ||
|
|
0395395d52 | ||
|
|
c3ca48b249 | ||
|
|
464e0aed04 | ||
|
|
d46e4fcecd | ||
|
|
363fb96e81 | ||
|
|
2382bd3bb2 | ||
|
|
3b0a9e84ab | ||
|
|
850aebea5d | ||
|
|
26e632e549 | ||
|
|
64d2d7074f | ||
|
|
062a15310a | ||
|
|
299c7c3514 | ||
|
|
6599cb001f | ||
|
|
f1347f5841 | ||
|
|
f3ccf62463 | ||
|
|
44fea33c5d | ||
|
|
8b48cf11f9 | ||
|
|
e681fdd958 | ||
|
|
d4b7a78c54 | ||
|
|
a45cbad553 | ||
|
|
16b9a30655 | ||
|
|
82a184a7b7 | ||
|
|
9e198a59b6 | ||
|
|
c002678085 | ||
|
|
486cffc361 | ||
|
|
67495fcc77 | ||
|
|
b26a370ce4 | ||
|
|
4dc0e67ac7 | ||
|
|
2c060663cf | ||
|
|
76a8eb4960 | ||
|
|
ad3dad1965 | ||
|
|
172d97de05 | ||
|
|
4c967d5b45 | ||
|
|
b244f31337 | ||
|
|
8550a04bf4 | ||
|
|
cb38ead48e | ||
|
|
9713c3394d | ||
|
|
fa57b006c9 | ||
|
|
9f73f0234a | ||
|
|
a4f067481c | ||
|
|
733fb527fa | ||
|
|
3667c6b053 | ||
|
|
1071818df8 | ||
|
|
11c2d9ea30 | ||
|
|
52cdf3056d | ||
|
|
32899a1edd | ||
|
|
119458f13e | ||
|
|
2863095f06 | ||
|
|
cbc050b9ed | ||
|
|
18affbd390 | ||
|
|
0b7a36ce33 | ||
|
|
1957915940 | ||
|
|
552b71d4e2 | ||
|
|
480112f9aa | ||
|
|
9a2f4d8026 | ||
|
|
3b15f32335 | ||
|
|
7404a6fc4f | ||
|
|
91d1ec41c2 | ||
|
|
9237c8be67 | ||
|
|
6c87d362c5 | ||
|
|
4f31d3587d | ||
|
|
29a2f4021a | ||
|
|
e2d321a16a | ||
|
|
7366f5099a | ||
|
|
4fbef5f466 | ||
|
|
2e48ff3362 | ||
|
|
7cdbdb663c | ||
|
|
1b390d3857 | ||
|
|
2808f9c75b | ||
|
|
49d109c29e | ||
|
|
36dd959bf9 | ||
|
|
2f9a67b8a1 | ||
|
|
6d5d9ea073 | ||
|
|
1cfd340cae | ||
|
|
369ccfc34f | ||
|
|
e556513de6 | ||
|
|
79dc1a2a4d | ||
|
|
9e5a501c73 | ||
|
|
2db8d7f6a2 | ||
|
|
94c3f4d4fc | ||
|
|
3fa26861cd | ||
|
|
ef2b0ccd6c | ||
|
|
f1702d24e7 | ||
|
|
3a50ff57d8 | ||
|
|
8ac2e8d495 | ||
|
|
e56cf85fd1 | ||
|
|
1c6aef1862 | ||
|
|
4653cbe56e | ||
|
|
93148d302f | ||
|
|
a443ba91ce | ||
|
|
d8daef2de7 | ||
|
|
845d43c77a | ||
|
|
f8dbcc472b | ||
|
|
0f0f75f6b1 | ||
|
|
4e2e2d84fc | ||
|
|
887885b6e0 | ||
|
|
a868a5c434 | ||
|
|
a0c147d246 | ||
|
|
38040c96d6 | ||
|
|
989ecf69ad | ||
|
|
9d26399143 | ||
|
|
b9cad7cc54 | ||
|
|
357b97b5a6 | ||
|
|
318160d836 | ||
|
|
5e90d63373 | ||
|
|
0b7f1e488f | ||
|
|
e281bbbb55 | ||
|
|
892bacee52 | ||
|
|
2f1db4b77c | ||
|
|
f90e9b26f8 | ||
|
|
ad71f454bd | ||
|
|
c66bd791c4 | ||
|
|
40bceef3ca | ||
|
|
9d79f55dc9 | ||
|
|
c5c1cf6d55 | ||
|
|
9eb8aa9a32 | ||
|
|
95931a7e6c | ||
|
|
d9daaed43f | ||
|
|
b9c51e65c1 | ||
|
|
da5eb92f47 | ||
|
|
03ed585f6f | ||
|
|
51f953a1aa | ||
|
|
93fb07d808 | ||
|
|
5e311d4d85 | ||
|
|
e652054d50 | ||
|
|
58c31b8627 | ||
|
|
b945033b41 | ||
|
|
92d2867170 | ||
|
|
5d38c8c558 | ||
|
|
552a4b2c82 | ||
|
|
7a4afb08bd | ||
|
|
c5cd1ac630 | ||
|
|
90edb76415 | ||
|
|
8f397502df | ||
|
|
1cb17d8613 | ||
|
|
88e796bb45 | ||
|
|
1310bf0218 | ||
|
|
4efeaa844f | ||
|
|
24685612a9 | ||
|
|
bf21df4195 | ||
|
|
417b3f9c6b | ||
|
|
2d84a1c63e | ||
|
|
5ab9a29bc4 | ||
|
|
383ea0d86a | ||
|
|
df8f75bb8f | ||
|
|
ba95ef63da | ||
|
|
bea4aa31ea | ||
|
|
6c19a8352f | ||
|
|
e3df89b524 | ||
|
|
a9003f7ac0 | ||
|
|
2cc06f60c5 | ||
|
|
4759afcc3e | ||
|
|
66b297e408 | ||
|
|
bbd2b255a3 | ||
|
|
8b2f28eee3 | ||
|
|
ae767dc5bf | ||
|
|
d923402934 | ||
|
|
9667f889b3 | ||
|
|
d2ea7af335 | ||
|
|
f95e9407a9 | ||
|
|
7be3c2974a | ||
|
|
5444f604cb | ||
|
|
94e68b0e36 | ||
|
|
910d86f958 | ||
|
|
fd885e42b0 | ||
|
|
ea31ae31c1 | ||
|
|
00763e5af3 | ||
|
|
1bf5aab18c | ||
|
|
210a709246 | ||
|
|
5feba67a3d | ||
|
|
e9e373913e | ||
|
|
f1f197e3b9 | ||
|
|
cedb6183e9 | ||
|
|
0415d46c0f | ||
|
|
68388331c7 | ||
|
|
92817b0603 | ||
|
|
f8a1726ffa | ||
|
|
be34f27026 | ||
|
|
12c5518e2b | ||
|
|
d8ab5c3c45 | ||
|
|
36d1c9e8b7 | ||
|
|
45c047f5c0 | ||
|
|
da1232caaf | ||
|
|
fff5a83957 | ||
|
|
f5b6488eb2 | ||
|
|
c02bae9e08 | ||
|
|
58e65ae7dd | ||
|
|
3977518f00 | ||
|
|
8adee3dace | ||
|
|
09ad930da4 | ||
|
|
52f7bb6950 | ||
|
|
68db945e47 | ||
|
|
b54f4cf5d4 | ||
|
|
9a8a9451b1 | ||
|
|
fffa903ce9 | ||
|
|
ab08885a32 | ||
|
|
ad3995b1b9 | ||
|
|
75cc0710ac | ||
|
|
7cec7054e2 | ||
|
|
fe280e578f | ||
|
|
a32973f56b | ||
|
|
7762311911 | ||
|
|
edd73ffbed | ||
|
|
fca87d93e9 | ||
|
|
c2fe2c0385 | ||
|
|
8aa25046dc | ||
|
|
27a07ed89c | ||
|
|
071a6bcc06 | ||
|
|
f98ac6590d | ||
|
|
6b733d2943 | ||
|
|
6f165efcdb | ||
|
|
7bc1c9a562 | ||
|
|
1596fdeba3 | ||
|
|
1599b659cf | ||
|
|
bb65564c7d | ||
|
|
03031b3dc1 | ||
|
|
b7636ebbc0 | ||
|
|
5707b80a69 | ||
|
|
81e5d4c327 | ||
|
|
f8111125ef | ||
|
|
c020e83890 | ||
|
|
f6659fea8d | ||
|
|
a06858ccd9 | ||
|
|
c6c48d327c | ||
|
|
5d0f188615 | ||
|
|
78fcc8feb8 | ||
|
|
27cad85247 | ||
|
|
ad0c1d4dbe | ||
|
|
00abaed89a | ||
|
|
342f02711b | ||
|
|
d9c48a8d01 | ||
|
|
d757696116 | ||
|
|
528ebfabf0 | ||
|
|
2ebde276d1 | ||
|
|
04f3c8054b | ||
|
|
ea07bf7536 | ||
|
|
80e6f1ca8c | ||
|
|
54d29568ec | ||
|
|
4e1ea58503 | ||
|
|
90c429a91c | ||
|
|
4b28e038e0 | ||
|
|
8df694a358 | ||
|
|
eb8778e1cd | ||
|
|
256f3a0d60 | ||
|
|
54c087e7ec | ||
|
|
69a99b89f9 | ||
|
|
f328ab9d83 | ||
|
|
8acce5f294 | ||
|
|
bdbe0acd1f | ||
|
|
fc701baef8 | ||
|
|
a457a81fd9 | ||
|
|
4cc7977d36 | ||
|
|
e5e7f5dd88 | ||
|
|
916886312a | ||
|
|
8ff94ea1f2 | ||
|
|
053bd0cd31 | ||
|
|
a3ce574193 | ||
|
|
ef92adc87d | ||
|
|
46a9538b6a | ||
|
|
ca547b8716 | ||
|
|
04ea51e843 | ||
|
|
f7dc0dda4e | ||
|
|
8713843022 | ||
|
|
6563b05d60 | ||
|
|
d119c55b72 | ||
|
|
253e25a73c | ||
|
|
c63774967f | ||
|
|
bbc36448fb | ||
|
|
5df323fb64 | ||
|
|
0f2c5f13be | ||
|
|
58180ad3be | ||
|
|
fb0229890b | ||
|
|
9099888398 | ||
|
|
882855f865 | ||
|
|
f59d2ae89d | ||
|
|
7c3a53a171 | ||
|
|
1e22572716 | ||
|
|
8a25f54e1f | ||
|
|
c51f2fc0ec | ||
|
|
2a528df977 | ||
|
|
84684bd56e | ||
|
|
e1606ce8eb | ||
|
|
47072e0441 | ||
|
|
915c229396 | ||
|
|
0bf46b4845 | ||
|
|
a7a2dbc3ea | ||
|
|
7e8f586859 | ||
|
|
bb9dccd773 | ||
|
|
7b743e662e | ||
|
|
769dc53c05 | ||
|
|
1a4554daf3 | ||
|
|
6c0633ef61 | ||
|
|
4d020a3875 | ||
|
|
316cc55e69 | ||
|
|
95f2634ea9 | ||
|
|
95c032f531 | ||
|
|
744955753f | ||
|
|
ae5e7dc65d | ||
|
|
ed41c46926 | ||
|
|
a460fb2734 | ||
|
|
39ddce6ba3 | ||
|
|
8da7e3bdc3 | ||
|
|
eff53c023a | ||
|
|
99e4a6a2d6 | ||
|
|
c06817b951 | ||
|
|
e765aaa3f4 | ||
|
|
1728aa581c | ||
|
|
c50475de34 | ||
|
|
5d7ecb7a6e | ||
|
|
06348a8517 | ||
|
|
c4dbb8f01e | ||
|
|
e67b2cb54b | ||
|
|
908b1e5e12 | ||
|
|
539391ce6c | ||
|
|
7fc90aed26 | ||
|
|
23e79d2eb2 | ||
|
|
0c7b1431d7 | ||
|
|
b6c0155836 | ||
|
|
76d67b586c | ||
|
|
914edb1472 | ||
|
|
dbf5033f94 | ||
|
|
cc6ecc8b62 | ||
|
|
b7e6922605 | ||
|
|
05eaffb9f2 | ||
|
|
67b568f464 | ||
|
|
19b534f7de | ||
|
|
bc386c9a60 | ||
|
|
db8b3419c2 | ||
|
|
0f5ba5192a | ||
|
|
108c423d70 | ||
|
|
dded10a396 | ||
|
|
1b080826db | ||
|
|
910f23ea19 | ||
|
|
f1b50baba1 | ||
|
|
4453597946 | ||
|
|
192bfa10cb | ||
|
|
0781429dc5 | ||
|
|
d760332f00 | ||
|
|
131be5f2e8 | ||
|
|
57a95c540c | ||
|
|
09deb1d757 | ||
|
|
5c4aba4b9c | ||
|
|
6a5d555f58 | ||
|
|
f5dc71021f | ||
|
|
39005461c5 | ||
|
|
4dc4c00267 | ||
|
|
d76460343a | ||
|
|
0d8dd0c664 | ||
|
|
ee6491f717 | ||
|
|
7044951dab | ||
|
|
98986a25f9 | ||
|
|
ae3e586714 | ||
|
|
0ef12193f9 | ||
|
|
b695ef9168 | ||
|
|
7fb1389648 | ||
|
|
f88efb811b | ||
|
|
466d33ca69 | ||
|
|
d44ce1987d | ||
|
|
527b2c5ab1 | ||
|
|
4d0c2997cf | ||
|
|
6f04ec9dae | ||
|
|
00cc99818d | ||
|
|
e51fdc1c9b | ||
|
|
8d5ef4ab30 | ||
|
|
7bdda15b86 | ||
|
|
4c41ef8de3 | ||
|
|
7aec3b0fa1 | ||
|
|
fce23c981b | ||
|
|
351819b570 | ||
|
|
a10b1b7341 | ||
|
|
02c6226741 | ||
|
|
620ccdabb5 | ||
|
|
4b12dc6547 | ||
|
|
bd69d7e23f | ||
|
|
8648486400 | ||
|
|
6c00117119 | ||
|
|
9c4c4eaaa1 | ||
|
|
969b3257a7 | ||
|
|
65c6af31e1 | ||
|
|
6b8bc83420 | ||
|
|
30aaab5c6c | ||
|
|
72e2a46c05 | ||
|
|
e06e0e8555 | ||
|
|
9f1d6e1f44 | ||
|
|
15ed1a329e | ||
|
|
505436340b | ||
|
|
a27434a8a7 | ||
|
|
2c987861a6 | ||
|
|
c7320df0c9 | ||
|
|
dd666e4fe4 | ||
|
|
e4f0418003 | ||
|
|
430b6f8fb1 | ||
|
|
ba3e80cbfa | ||
|
|
7cd4282bad | ||
|
|
01e9fa9adb | ||
|
|
581e01b2da | ||
|
|
5a3b4de1b7 | ||
|
|
74288eceaf | ||
|
|
37ba057128 | ||
|
|
6d5ba9590b | ||
|
|
215f792851 | ||
|
|
1c55b32879 | ||
|
|
82eb947f41 | ||
|
|
485dae9f25 | ||
|
|
eb3423312f | ||
|
|
04c2093d5c | ||
|
|
ccd5992a83 | ||
|
|
ca8d9fbe0b | ||
|
|
62bac44a21 | ||
|
|
0ddd06113d | ||
|
|
b1fbc2ef24 | ||
|
|
c787fe7ecb | ||
|
|
bdb49720be | ||
|
|
1d448a2b8a | ||
|
|
c5df081904 | ||
|
|
8a2f3e1fe5 | ||
|
|
8dfc627e46 | ||
|
|
0fce30070f | ||
|
|
8bfe82f686 | ||
|
|
7d32ec51e7 | ||
|
|
5784f8c2f9 | ||
|
|
74e01ddec5 | ||
|
|
1347573139 | ||
|
|
f2b41e708d | ||
|
|
a5555943ed | ||
|
|
2c023cdaed | ||
|
|
bcc7028640 | ||
|
|
bdee75cd0f | ||
|
|
94eb3d7ac0 | ||
|
|
0ae2acfb1a | ||
|
|
afc5f46ca9 | ||
|
|
e544c891ca | ||
|
|
af0c95c11a | ||
|
|
4d5dc18a57 | ||
|
|
9f6fb161e2 | ||
|
|
3883a98771 | ||
|
|
9b44965f13 | ||
|
|
aa6a9de6ba | ||
|
|
8669e8a498 | ||
|
|
ead31db096 | ||
|
|
69fda941c7 | ||
|
|
67c9e7a4a8 | ||
|
|
4e4f57e091 | ||
|
|
ac64d2d910 | ||
|
|
49a76257cd | ||
|
|
77829cf3ed | ||
|
|
4d10ab3d35 | ||
|
|
e609ede597 | ||
|
|
2ba69abe39 | ||
|
|
a76f515569 | ||
|
|
a663b8c313 | ||
|
|
f66fa16bd1 | ||
|
|
8390363abe | ||
|
|
6ff85d287a | ||
|
|
94c2072be8 | ||
|
|
64b9d53472 | ||
|
|
a5e7b92c5d | ||
|
|
2da9ba63e2 | ||
|
|
5d02a8f5db | ||
|
|
834d3749c6 | ||
|
|
1c90bb522e | ||
|
|
b70b058b66 | ||
|
|
b99beeb552 | ||
|
|
c799452973 | ||
|
|
fd48afb77d | ||
|
|
aaa68954c3 | ||
|
|
433233258b | ||
|
|
3eed61deba | ||
|
|
87e2a02e0c | ||
|
|
264d592012 | ||
|
|
0ad5094119 | ||
|
|
67952a9142 | ||
|
|
ca3d942b9b | ||
|
|
5470a1344d | ||
|
|
4390f8102b | ||
|
|
92129a2011 | ||
|
|
54dffa07f3 | ||
|
|
1cff4bb27a | ||
|
|
8087250476 | ||
|
|
485dc052ca | ||
|
|
45d39c2802 | ||
|
|
3b4b1c6878 | ||
|
|
ff4f07d76f | ||
|
|
fb6c8cd466 | ||
|
|
8464b0484f | ||
|
|
bee58fd09d | ||
|
|
d25557a5ef | ||
|
|
da3ca6604b | ||
|
|
74cba6c3b2 | ||
|
|
c09718b731 | ||
|
|
eacfa2a966 | ||
|
|
e7f228e240 | ||
|
|
fab82a7c25 | ||
|
|
fc9c34897a | ||
|
|
28cdd3f497 | ||
|
|
a009e26e95 | ||
|
|
ab908c23f4 | ||
|
|
ae21f66fe5 | ||
|
|
2d092ea280 | ||
|
|
0f9d39cdfd | ||
|
|
a64087d481 | ||
|
|
c85f3f4942 | ||
|
|
d7553279ff | ||
|
|
c86631b8a9 | ||
|
|
c1af63de9b | ||
|
|
2784b03b2d | ||
|
|
10bdf8c645 | ||
|
|
d63d9b2319 | ||
|
|
d5f2b69d0c | ||
|
|
6818eee859 | ||
|
|
e7f1398d85 | ||
|
|
880c01f8cc | ||
|
|
337c5e5e59 | ||
|
|
af52ea78c6 | ||
|
|
fe633d9ef9 | ||
|
|
e6cce283a7 | ||
|
|
c920236c54 | ||
|
|
6f86b4d220 | ||
|
|
a085e174c5 | ||
|
|
d3c08789a3 | ||
|
|
630488210b | ||
|
|
873f6ccfea | ||
|
|
af15f5d004 | ||
|
|
f328175e2f | ||
|
|
fc65d6393a | ||
|
|
271afb7eab | ||
|
|
76133dbea7 | ||
|
|
6efe31e6f5 | ||
|
|
9885bedb7d | ||
|
|
b6edb517e4 | ||
|
|
f023695f31 | ||
|
|
749ea8c30c | ||
|
|
c79f289d67 | ||
|
|
e516ce428a | ||
|
|
1ae259aecb | ||
|
|
c609e2fef9 | ||
|
|
8ff9c851ce | ||
|
|
5ef2b9fd54 | ||
|
|
511dc7a182 | ||
|
|
c668586caf | ||
|
|
390447862a | ||
|
|
7f2648a013 | ||
|
|
3227aa2c45 | ||
|
|
c88dc98b7c | ||
|
|
ed5b42071c | ||
|
|
804d9ee828 | ||
|
|
a90f721b74 | ||
|
|
106417ada7 | ||
|
|
fd0d3283e0 | ||
|
|
3e63e683a9 | ||
|
|
e415f25c8f | ||
|
|
e596e1fa7d | ||
|
|
d8ab2e6d03 | ||
|
|
e9d3d3e3cf | ||
|
|
3a5983e387 | ||
|
|
4efb661ae6 | ||
|
|
bcdb9c937c | ||
|
|
f45c0b9609 | ||
|
|
9ea162034a | ||
|
|
192e779db2 | ||
|
|
bda7557783 | ||
|
|
dc50c7539a | ||
|
|
bf97dfd998 | ||
|
|
c7f4131402 | ||
|
|
bd5e5beee0 | ||
|
|
7a493f151d | ||
|
|
0ea73c384f | ||
|
|
d8c416e8b2 | ||
|
|
9bf3724d25 | ||
|
|
fd49d39184 | ||
|
|
0fd790eb8d | ||
|
|
b18e95d6b3 | ||
|
|
47b5c68df4 | ||
|
|
ac3b246858 | ||
|
|
51a754547e | ||
|
|
76df60db2b | ||
|
|
f3befe530b | ||
|
|
59d4333e23 | ||
|
|
92177d9663 | ||
|
|
6a29b64850 | ||
|
|
73cb60d053 | ||
|
|
47bd998e94 | ||
|
|
e2cfa7bd11 | ||
|
|
006633082d | ||
|
|
bbf7454fc9 | ||
|
|
85cb5509c4 | ||
|
|
0e29f52841 | ||
|
|
02893e37d3 | ||
|
|
1dbb5188ba | ||
|
|
a4d35ace78 | ||
|
|
981a638b01 | ||
|
|
3969d8b028 | ||
|
|
889709213e | ||
|
|
333a92bcff | ||
|
|
cd39e417e1 | ||
|
|
1cebf406aa | ||
|
|
d7915fbca8 | ||
|
|
9169315cc1 | ||
|
|
3b70cd3226 | ||
|
|
a6101f0181 | ||
|
|
92c6485adf | ||
|
|
4df9314039 | ||
|
|
c8ad4d5deb | ||
|
|
13a2db2238 | ||
|
|
e8f9fb0f86 | ||
|
|
634bd2de48 | ||
|
|
f58fc6b22e | ||
|
|
fb052c8d25 | ||
|
|
e35490ba5b | ||
|
|
be1b979e51 | ||
|
|
3fd931d392 | ||
|
|
6c1dce2878 | ||
|
|
ad1260505d | ||
|
|
d92f8a1b8e | ||
|
|
22827f2cc7 | ||
|
|
b64370cd48 | ||
|
|
6c8e176cc0 | ||
|
|
057bda6cd7 | ||
|
|
8df2cce5c1 | ||
|
|
352898ae9e | ||
|
|
1bda665662 | ||
|
|
fad4c60499 | ||
|
|
47bb556327 | ||
|
|
4d00f1903a | ||
|
|
7344a03aa3 | ||
|
|
64af90111e | ||
|
|
3254a3feab | ||
|
|
d5054f9b99 | ||
|
|
db93090ea8 | ||
|
|
15c65595b8 | ||
|
|
e59e9ad6a9 | ||
|
|
e6c4dbfc6d | ||
|
|
424dd8a463 | ||
|
|
7b1a7629bc | ||
|
|
df1116a010 | ||
|
|
11916bac7e | ||
|
|
d675ae5cc5 | ||
|
|
43eeff8f15 | ||
|
|
ece9e7e240 | ||
|
|
1abbf00dcf | ||
|
|
10564514e8 | ||
|
|
ba7ec29dc0 | ||
|
|
85b595bd14 | ||
|
|
56c486abbf | ||
|
|
96fc5dc3a7 | ||
|
|
b09087d634 | ||
|
|
5e99513507 | ||
|
|
0a9d2f248e | ||
|
|
16ff055b42 | ||
|
|
89f57d4ff6 | ||
|
|
c4a2234a28 | ||
|
|
a3882763d8 | ||
|
|
787fa6bd0d | ||
|
|
a6b4e53dca | ||
|
|
00d25ae89c | ||
|
|
5776fcd955 | ||
|
|
86b5dba43b | ||
|
|
e888364d3c | ||
|
|
276f85c9e3 | ||
|
|
68eb422333 | ||
|
|
c0f54f899d | ||
|
|
65212535df | ||
|
|
106ac7c782 | ||
|
|
bc7b6a0e53 | ||
|
|
e5b89569fd | ||
|
|
938bfff3dd | ||
|
|
6835fcf3cf | ||
|
|
2554ee27d9 | ||
|
|
007cdf8787 | ||
|
|
a526daf310 | ||
|
|
ee34e1acc5 | ||
|
|
a08fbfa586 | ||
|
|
d29f57fd1d | ||
|
|
a4c5d1d94d | ||
|
|
17f1bb1632 | ||
|
|
3418504b4b | ||
|
|
0a78a592ff | ||
|
|
208c527fb3 | ||
|
|
28990285e2 | ||
|
|
c7ad8d29e9 | ||
|
|
dba8d1ff77 | ||
|
|
970bb804de | ||
|
|
517b5173f9 |
@@ -7,6 +7,7 @@ stages:
|
||||
- analysis
|
||||
- docs
|
||||
- flatpak
|
||||
- publish
|
||||
- deploy
|
||||
|
||||
.cache-paths: &cache-paths
|
||||
@@ -24,7 +25,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v32"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v33"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
|
||||
.only-default:
|
||||
@@ -57,6 +58,7 @@ style-check-diff:
|
||||
- "${CI_PROJECT_DIR}/_build/report*.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report*.html"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
|
||||
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
|
||||
@@ -170,6 +172,9 @@ macos:
|
||||
- export MESON_FORCE_BACKTRACE=1
|
||||
script:
|
||||
- meson -Dx11-backend=false
|
||||
-Dbroadway-backend=true
|
||||
-Dmacos-backend=true
|
||||
-Dmedia-gstreamer=disabled
|
||||
-Dintrospection=disabled
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
@@ -333,14 +338,11 @@ reference:
|
||||
paths:
|
||||
- _reference
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
publish-docs:
|
||||
stage: publish
|
||||
needs: ['reference']
|
||||
script:
|
||||
- mv _reference/ public/
|
||||
- cp .gitlab-ci/pages/* public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline"
|
||||
only:
|
||||
- master
|
||||
refs:
|
||||
- master
|
||||
|
||||
@@ -48,7 +48,9 @@ RUN dnf -y install \
|
||||
libcloudproviders-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
libjpeg-turbo-devel \
|
||||
libmount-devel \
|
||||
libpng-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libubsan \
|
||||
|
||||
@@ -15,7 +15,7 @@ meson \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dbroadway-backend=true \
|
||||
-Dvulkan=yes \
|
||||
-Dvulkan=enabled \
|
||||
-Dprofiler=true \
|
||||
--werror \
|
||||
${EXTRA_MESON_FLAGS:-} \
|
||||
|
||||
@@ -6,7 +6,7 @@ call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliar
|
||||
|
||||
:: FIXME: make warnings fatal
|
||||
pip3 install --upgrade --user meson==0.56.2 || goto :error
|
||||
meson _build || goto :error
|
||||
meson -Dmedia-gstreamer=disabled _build || goto :error
|
||||
ninja -C _build || goto :error
|
||||
|
||||
goto :EOF
|
||||
|
||||
@@ -40,7 +40,7 @@ export CCACHE_DIR="${CCACHE_BASEDIR}/_ccache"
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/2243
|
||||
# https://gitlab.gnome.org/GNOME/gtk/-/issues/3002
|
||||
|
||||
if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
|
||||
git clone https://gitlab.gnome.org/GNOME/glib.git _glib
|
||||
meson setup _glib_build _glib
|
||||
meson compile -C _glib_build
|
||||
@@ -48,7 +48,7 @@ if ! pkg-config --atleast-version=2.65.0 glib-2.0; then
|
||||
fi
|
||||
pkg-config --modversion glib-2.0
|
||||
|
||||
if ! pkg-config --atleast-version=1.47.0 pango; then
|
||||
if ! pkg-config --atleast-version=1.49.1 pango; then
|
||||
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
|
||||
meson setup _pango_build _pango
|
||||
meson compile -C _pango_build
|
||||
|
||||
188
NEWS
@@ -1,3 +1,191 @@
|
||||
Overview of Changes
|
||||
===================
|
||||
|
||||
* gsk:
|
||||
- Drop the GL renderer in favor of NGL
|
||||
|
||||
* css:
|
||||
- Add support for line-height
|
||||
- Add support for text-transform
|
||||
|
||||
* GtkTextView:
|
||||
- Add support for line height
|
||||
- Add support for text transforms
|
||||
|
||||
* Build:
|
||||
- Require Pango 1.49
|
||||
|
||||
|
||||
Overview of Changes in 4.4.0
|
||||
============================
|
||||
|
||||
* Input:
|
||||
- Match IBus for display of Compose sequences
|
||||
- Match IBus for handling of mismatches
|
||||
- Handle Escape in Compose sequences
|
||||
- Allow multiple dead keys
|
||||
- Support 32bit keysyms
|
||||
|
||||
* GtkCheckButton:
|
||||
- Activate when moving focus
|
||||
|
||||
* GtkLabel:
|
||||
- Propertly ignore double underscores for mnemonics
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Fix focus cycling
|
||||
|
||||
* GtkTextView:
|
||||
- Improve word selection
|
||||
- Fix block cursors on empty lines
|
||||
|
||||
* GdkToplevel:
|
||||
- Support the gnome-shell titlebar gesture protocol
|
||||
|
||||
* GdkDropTarget:
|
||||
- Allow creating drop targets in ui files
|
||||
|
||||
* gsk:
|
||||
- Handle partial color fonts correctly
|
||||
- Use harfbuzz for color font information
|
||||
- Avoid pango for glyph cache rendering
|
||||
- Shrink shadow extents
|
||||
|
||||
* Settings:
|
||||
- Change the default for gtk-split-cursor to FALSE
|
||||
|
||||
* Demos:
|
||||
- Small improvements to widget-factory
|
||||
- gtk-demo: Improve the hypertext demo
|
||||
- gtk-dem: Improve the clipboard demo
|
||||
|
||||
* X11:
|
||||
- Set WM_CLASS on toplevels
|
||||
|
||||
* Wayland:
|
||||
- Support wl_seat v7
|
||||
|
||||
* Windows:
|
||||
- Drop the local DND protocol
|
||||
- Avoid WGL if shaders don't work
|
||||
- Use WinPointer API
|
||||
|
||||
* Translation updates:
|
||||
Belarusian
|
||||
Friulian
|
||||
Hebrew
|
||||
Khmer
|
||||
Persian
|
||||
Polish
|
||||
|
||||
|
||||
Overview of Changes in 4.3.2
|
||||
============================
|
||||
|
||||
* GtkToggleButton:
|
||||
- Fix the actionable implementation
|
||||
|
||||
* GtkCheckButton:
|
||||
- Fix the actionable implementation
|
||||
- Cancel activation on when the pointer leaves
|
||||
|
||||
* GtkMenuButton:
|
||||
- Make activatable again
|
||||
- Add a way to have an icon + arrow
|
||||
|
||||
* GtkColorButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkFontButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkAppChooserButton:
|
||||
- Make activatable again
|
||||
|
||||
* GtkColumnView:
|
||||
- Fix double activation
|
||||
|
||||
* GtkLabel:
|
||||
- Fix mnemonics without markup
|
||||
|
||||
* GtkTreeView:
|
||||
- Clip header buttons
|
||||
|
||||
* GtkTextView:
|
||||
- Add api to get the RTL and LTR contexts
|
||||
- Fix some errors in text history grouping
|
||||
|
||||
* GtkText:
|
||||
- Don't show placeholder text on top of entry text
|
||||
- Add api to compute the cursor extents
|
||||
- Fix y coordinates for text selection
|
||||
|
||||
* GtkFileChooser:
|
||||
- Don't show Trash in the side bar
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Add scrollbars to long menus
|
||||
|
||||
* GtkActionMuxer:
|
||||
- Fix propagation of accel changes
|
||||
|
||||
* Introspection:
|
||||
- Annotate all filename arguments
|
||||
- Rename GtkMediaStream apis to avoid name collisions
|
||||
- Rename GtkDropTarget properties to avoid name collisions
|
||||
- Make GtkPasswordEntryBuffer introspectable
|
||||
|
||||
* Printing:
|
||||
- Remove the Google Cloud Print backend
|
||||
|
||||
* Theme:
|
||||
- Sync included icons with the Adwaita icon theme
|
||||
|
||||
* GSK:
|
||||
- Avoid overflowing the vertex counter
|
||||
- Handle negative scales correctly in the ngl renderer
|
||||
|
||||
* GDK:
|
||||
- Cleanup and simplify OpenGL setup code
|
||||
- Add a GdkDisplay::init_gl vfunc and gdk_display_prepare_gl() api
|
||||
- Require EGL 1.4
|
||||
- Fix EGL + NVidia
|
||||
|
||||
* Build:
|
||||
- Enable gstreamer by default
|
||||
- Disable Vulkan by default
|
||||
- Remove the sassc option
|
||||
- Remove options and checks for X11 extensions
|
||||
|
||||
* X11:
|
||||
- Stop using XComposite
|
||||
- Remove the Visual cache
|
||||
|
||||
* Wayland:
|
||||
- Fix some DND corner cases
|
||||
- Work with version 2 of pointer-gestures-v1
|
||||
- Look for cursor themes in $HOME/.icons
|
||||
|
||||
* Windows:
|
||||
- Fix SIGILL on x64 due to popcnt
|
||||
- Fix popup placement
|
||||
- Fix drag icon placement
|
||||
- Clean up HiDPI and WGL support
|
||||
- Default to WGL
|
||||
|
||||
* MacOs:
|
||||
- Fix input method support
|
||||
- Register known clipboard types for drop targets
|
||||
- Add initial DND support
|
||||
|
||||
* Translation updates:
|
||||
Brazilian Portuguese
|
||||
Portuguese
|
||||
Romanian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.3.1
|
||||
============================
|
||||
|
||||
|
||||
289
config.h.meson
@@ -1,289 +0,0 @@
|
||||
/* always defined to indicate that i18n is enabled */
|
||||
#define ENABLE_NLS 1
|
||||
|
||||
/* Use structured logging */
|
||||
#define G_LOG_STRUCTURED 1
|
||||
|
||||
/* The prefix for our gettext translation domains. */
|
||||
#mesondefine GETTEXT_PACKAGE
|
||||
|
||||
/* Disable deprecation warnings from glib */
|
||||
#mesondefine GLIB_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
/* Define the location where the catalogs will be installed */
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
/* Define to 1 if you have the `bind_textdomain_codeset' function. */
|
||||
#mesondefine HAVE_BIND_TEXTDOMAIN_CODESET
|
||||
|
||||
/* Have the cloudproviders library */
|
||||
#mesondefine HAVE_CLOUDPROVIDERS
|
||||
|
||||
/* define if we have colord */
|
||||
#mesondefine HAVE_COLORD
|
||||
|
||||
/* Define to 1 if you have the <crt_externs.h> header file. */
|
||||
#mesondefine HAVE_CRT_EXTERNS_H
|
||||
|
||||
/* Define to 1 if you have the `dcgettext' function. */
|
||||
#mesondefine HAVE_DCGETTEXT
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#mesondefine HAVE_DLFCN_H
|
||||
|
||||
/* Have the ffmpeg library */
|
||||
#mesondefine HAVE_FFMPEG
|
||||
|
||||
/* Define to 1 if you have the <ftw.h> header file. */
|
||||
#mesondefine HAVE_FTW_H
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#mesondefine HAVE_GETPAGESIZE
|
||||
|
||||
/* Define to 1 if you have the `getresuid' function. */
|
||||
#mesondefine HAVE_GETRESUID
|
||||
|
||||
/* Define if gio-unix is available */
|
||||
#mesondefine HAVE_GIO_UNIX
|
||||
|
||||
/* Define if GStreamer support is available */
|
||||
#mesondefine HAVE_GSTREAMER
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#mesondefine HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if the system has the type `IPrintDialogCallback'. */
|
||||
#mesondefine HAVE_IPRINTDIALOGCALLBACK
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#mesondefine HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `lstat' function. */
|
||||
#mesondefine HAVE_LSTAT
|
||||
|
||||
/* Define to 1 if you have the `mallinfo' function. */
|
||||
#mesondefine HAVE_MALLINFO
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#mesondefine HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
#mesondefine HAVE_MKSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mlock` function. */
|
||||
#mesondefine HAVE_MLOCK
|
||||
|
||||
/* Define to 1 if you have a working `mmap' system call. */
|
||||
#mesondefine HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have a working `madvise' system call. */
|
||||
#mesondefine HAVE_MADVISE
|
||||
|
||||
/* Define to 1 if you have the `posix_fallocate' function. */
|
||||
#mesondefine HAVE_POSIX_FALLOCATE
|
||||
|
||||
/* Have the Xrandr extension library */
|
||||
#mesondefine HAVE_RANDR
|
||||
|
||||
/* Have the Xrandr 1.5 extension library */
|
||||
#mesondefine HAVE_RANDR15
|
||||
|
||||
/* Define to 1 if you have the `sincos' function. */
|
||||
#mesondefine HAVE_SINCOS
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#mesondefine HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#mesondefine HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#mesondefine HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#mesondefine HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
#mesondefine HAVE_SYS_MMAN_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#mesondefine HAVE_SYS_PARAM_H
|
||||
|
||||
/* Have the sysprof-capture library */
|
||||
#mesondefine HAVE_SYSPROF
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#mesondefine HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#mesondefine HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#mesondefine HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#mesondefine HAVE_UNISTD_H
|
||||
|
||||
/* Have the XCOMPOSITE X extension */
|
||||
#mesondefine HAVE_XCOMPOSITE
|
||||
|
||||
/* Have the Xcursor library */
|
||||
#mesondefine HAVE_XCURSOR
|
||||
|
||||
/* Have the XDAMAGE X extension */
|
||||
#mesondefine HAVE_XDAMAGE
|
||||
|
||||
/* Have the XFIXES X extension */
|
||||
#mesondefine HAVE_XFIXES
|
||||
|
||||
/* Define to 1 if XFree Xinerama is available */
|
||||
#mesondefine HAVE_XFREE_XINERAMA
|
||||
|
||||
/* Have XGenericEvent */
|
||||
#mesondefine HAVE_XGENERICEVENTS
|
||||
|
||||
/* Define to use XKB extension */
|
||||
#mesondefine HAVE_XKB
|
||||
|
||||
/* Have the SYNC extension library */
|
||||
#mesondefine HAVE_XSYNC
|
||||
|
||||
/* Define to 1 if you have the `_lock_file' function */
|
||||
#mesondefine HAVE__LOCK_FILE
|
||||
|
||||
/* Define to 1 if you have the `flockfile' function */
|
||||
#mesondefine HAVE_FLOCKFILE
|
||||
|
||||
/* Define if _NL_MEASUREMENT_MEASUREMENT is available */
|
||||
#mesondefine HAVE__NL_MEASUREMENT_MEASUREMENT
|
||||
|
||||
/* Define if _NL_PAPER_HEIGHT is available */
|
||||
#mesondefine HAVE__NL_PAPER_HEIGHT
|
||||
|
||||
/* Define if _NL_PAPER_WIDTH is available */
|
||||
#mesondefine HAVE__NL_PAPER_WIDTH
|
||||
|
||||
/* Define if _NL_TIME_FIRST_WEEKDAY is available */
|
||||
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#mesondefine LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#mesondefine NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#mesondefine PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#mesondefine PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#mesondefine PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#mesondefine PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#mesondefine PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#mesondefine PACKAGE_VERSION
|
||||
|
||||
/* Use NSBundle functions to determine load paths for libraries, translations,
|
||||
etc. */
|
||||
#mesondefine QUARTZ_RELOCATION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#mesondefine STDC_HEADERS
|
||||
|
||||
/* Enable extensions on AIX 3, Interix. */
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if XInput 2.2 is available */
|
||||
#mesondefine XINPUT_2_2
|
||||
|
||||
/* Define to 1 if the X Window System is missing or not being used. */
|
||||
#mesondefine X_DISPLAY_MISSING
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#mesondefine _FILE_OFFSET_BITS
|
||||
|
||||
/* defines how to decorate public symbols while building */
|
||||
#mesondefine _GDK_EXTERN
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#mesondefine _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#mesondefine _MINIX
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#mesondefine _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#mesondefine _POSIX_SOURCE
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine gid_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#mesondefine uid_t
|
||||
|
||||
/* Define to 1 if linux/memfd.h exists */
|
||||
#mesondefine HAVE_LINUX_MEMFD_H
|
||||
|
||||
#mesondefine HAVE_LINUX_INPUT_H
|
||||
|
||||
#mesondefine HAVE_DEV_EVDEV_INPUT_H
|
||||
|
||||
#mesondefine GTK_SYSCONFDIR
|
||||
|
||||
#mesondefine GTK_LOCALEDIR
|
||||
|
||||
#mesondefine GTK_DATADIR
|
||||
|
||||
#mesondefine GTK_LIBDIR
|
||||
|
||||
#mesondefine GTK_PRINT_BACKENDS
|
||||
|
||||
#mesondefine HAVE_CAIRO_SCRIPT_INTERPRETER
|
||||
|
||||
#mesondefine HAVE_HARFBUZZ
|
||||
|
||||
#mesondefine HAVE_PANGOFT
|
||||
|
||||
#mesondefine ISO_CODES_PREFIX
|
||||
|
||||
/* Define if tracker3 is available */
|
||||
#mesondefine HAVE_TRACKER3
|
||||
|
||||
#mesondefine HAVE_F16C
|
||||
|
||||
/* Does the OS support GDesktopAppInfo? */
|
||||
#mesondefine HAVE_DESKTOPAPPINFO
|
||||
@@ -321,6 +321,7 @@
|
||||
<file>paintable_emblem.c</file>
|
||||
<file>paintable_mediastream.c</file>
|
||||
<file>paintable_svg.c</file>
|
||||
<file>paintable_symbolic.c</file>
|
||||
<file>panes.c</file>
|
||||
<file>password_entry.c</file>
|
||||
<file>peg_solitaire.c</file>
|
||||
|
||||
@@ -100,7 +100,11 @@ prepare_drag (GtkDragSource *source,
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
|
||||
else
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -129,7 +133,11 @@ copy_image (GtkWidget *widget,
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (demo->image));
|
||||
GValue value = G_VALUE_INIT;
|
||||
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
/* Textures can be serialized, paintables can't, so special case the textures */
|
||||
if (GDK_IS_TEXTURE (paintable))
|
||||
g_value_init (&value, GDK_TYPE_TEXTURE);
|
||||
else
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
g_value_set_object (&value, paintable);
|
||||
gdk_clipboard_set_value (clipboard, &value);
|
||||
g_value_unset (&value);
|
||||
@@ -138,24 +146,46 @@ copy_image (GtkWidget *widget,
|
||||
g_object_unref (paintable);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GdkClipboard *clipboard = GDK_CLIPBOARD (source);
|
||||
DemoImage *demo = DEMO_IMAGE (data);
|
||||
const GValue *value;
|
||||
|
||||
value = gdk_clipboard_read_value_finish (clipboard, result, NULL);
|
||||
if (value == NULL)
|
||||
{
|
||||
gtk_widget_error_bell (GTK_WIDGET (demo));
|
||||
g_object_unref (demo);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), g_value_get_object (value));
|
||||
g_object_unref (demo);
|
||||
}
|
||||
|
||||
static void
|
||||
paste_image (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
|
||||
DemoImage *demo = DEMO_IMAGE (widget);
|
||||
GdkContentProvider *content = gdk_clipboard_get_content (clipboard);
|
||||
GValue value = G_VALUE_INIT;
|
||||
GdkPaintable *paintable;
|
||||
GType type;
|
||||
|
||||
g_value_init (&value, GDK_TYPE_PAINTABLE);
|
||||
if (!gdk_content_provider_get_value (content, &value, NULL))
|
||||
return;
|
||||
if (gdk_content_formats_contain_gtype (gdk_clipboard_get_formats (clipboard), GDK_TYPE_TEXTURE))
|
||||
type = GDK_TYPE_TEXTURE;
|
||||
else
|
||||
type = GDK_TYPE_PAINTABLE;
|
||||
|
||||
paintable = GDK_PAINTABLE (g_value_get_object (&value));
|
||||
gtk_image_set_from_paintable (GTK_IMAGE (demo->image), paintable);
|
||||
g_value_unset (&value);
|
||||
gdk_clipboard_read_value_async (clipboard,
|
||||
type,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
paste_image_cb,
|
||||
g_object_ref (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -131,6 +131,19 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
#define VOID_ATTR(attr_name) \
|
||||
{ \
|
||||
tag = gtk_text_tag_table_lookup (table, #attr_name); \
|
||||
if (!tag) \
|
||||
{ \
|
||||
tag = gtk_text_tag_new (#attr_name); \
|
||||
g_object_set (tag, #attr_name, TRUE, NULL); \
|
||||
gtk_text_tag_table_add (table, tag); \
|
||||
g_object_unref (tag); \
|
||||
} \
|
||||
gtk_text_buffer_apply_tag (buffer, tag, start, end); \
|
||||
}
|
||||
|
||||
fg_alpha = bg_alpha = 1.;
|
||||
|
||||
attrs = pango_attr_iterator_get_attrs (iter);
|
||||
@@ -255,6 +268,29 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
INT_ATTR (insert_hyphens);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_LINE_HEIGHT:
|
||||
FLOAT_ATTR (line_height);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_ABSOLUTE_LINE_HEIGHT:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_WORD:
|
||||
VOID_ATTR (word);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SENTENCE:
|
||||
VOID_ATTR (sentence);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_BASELINE_SHIFT:
|
||||
INT_ATTR (baseline_shift);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_FONT_SCALE:
|
||||
INT_ATTR (font_scale);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_SHAPE:
|
||||
case PANGO_ATTR_ABSOLUTE_SIZE:
|
||||
case PANGO_ATTR_GRAVITY:
|
||||
@@ -263,6 +299,10 @@ insert_tags_for_attributes (GtkTextBuffer *buffer,
|
||||
case PANGO_ATTR_BACKGROUND_ALPHA:
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_TEXT_TRANSFORM:
|
||||
INT_ATTR (text_transform);
|
||||
break;
|
||||
|
||||
case PANGO_ATTR_INVALID:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
/* Pango/Font Rendering
|
||||
*
|
||||
* Demonstrates various aspects of font rendering.
|
||||
* Demonstrates various aspects of font rendering,
|
||||
* such as hinting, antialiasing and grid alignment.
|
||||
*
|
||||
* The demo lets you explore font rendering options
|
||||
* interactively to get a feeling for they affect the
|
||||
* shape and positioning of the glyphs.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -10,16 +15,21 @@ static GtkWidget *font_button = NULL;
|
||||
static GtkWidget *entry = NULL;
|
||||
static GtkWidget *image = NULL;
|
||||
static GtkWidget *hinting = NULL;
|
||||
static GtkWidget *anti_alias = NULL;
|
||||
static GtkWidget *hint_metrics = NULL;
|
||||
static GtkWidget *up_button = NULL;
|
||||
static GtkWidget *down_button = NULL;
|
||||
static GtkWidget *text_radio = NULL;
|
||||
static GtkWidget *show_grid = NULL;
|
||||
static GtkWidget *show_extents = NULL;
|
||||
static GtkWidget *show_pixels = NULL;
|
||||
static GtkWidget *show_outlines = NULL;
|
||||
|
||||
static PangoContext *context;
|
||||
|
||||
static int scale = 9;
|
||||
static int scale = 7;
|
||||
static double pixel_alpha = 1.0;
|
||||
static double outline_alpha = 0.0;
|
||||
|
||||
static void
|
||||
update_image (void)
|
||||
@@ -37,6 +47,8 @@ update_image (void)
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
cairo_antialias_t antialias;
|
||||
cairo_path_t *path;
|
||||
|
||||
if (!context)
|
||||
context = gtk_widget_create_pango_context (image);
|
||||
@@ -65,6 +77,13 @@ update_image (void)
|
||||
hintmetrics = CAIRO_HINT_METRICS_OFF;
|
||||
cairo_font_options_set_hint_metrics (fopt, hintmetrics);
|
||||
|
||||
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (anti_alias)))
|
||||
antialias = CAIRO_ANTIALIAS_GRAY;
|
||||
else
|
||||
antialias = CAIRO_ANTIALIAS_NONE;
|
||||
cairo_font_options_set_antialias (fopt, antialias);
|
||||
|
||||
pango_context_set_round_glyph_positions (context, hintmetrics == CAIRO_HINT_METRICS_ON);
|
||||
pango_cairo_context_set_font_options (context, fopt);
|
||||
cairo_font_options_destroy (fopt);
|
||||
pango_context_changed (context);
|
||||
@@ -85,10 +104,14 @@ update_image (void)
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, pixel_alpha);
|
||||
|
||||
cairo_move_to (cr, 10, 10);
|
||||
pango_cairo_show_layout (cr, layout);
|
||||
|
||||
pango_cairo_layout_path (cr, layout);
|
||||
path = cairo_copy_path (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
g_object_unref (layout);
|
||||
|
||||
@@ -127,7 +150,7 @@ update_image (void)
|
||||
|
||||
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (show_extents)))
|
||||
{
|
||||
cairo_set_source_rgba (cr, 0, 0, 1, 1);
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (logical.x)) - 0.5,
|
||||
@@ -140,7 +163,7 @@ update_image (void)
|
||||
cairo_line_to (cr, scale * (10 + pango_units_to_double (logical.x + logical.width)) + 1,
|
||||
scale * (10 + pango_units_to_double (baseline)) - 0.5);
|
||||
cairo_stroke (cr);
|
||||
cairo_set_source_rgba (cr, 1, 0, 0, 1);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_rectangle (cr,
|
||||
scale * (10 + pango_units_to_double (pink.x)) + 0.5,
|
||||
scale * (10 + pango_units_to_double (pink.y)) + 0.5,
|
||||
@@ -149,8 +172,36 @@ update_image (void)
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
for (int i = 0; i < path->num_data; i += path->data[i].header.length)
|
||||
{
|
||||
cairo_path_data_t *data = &path->data[i];
|
||||
switch (data->header.type)
|
||||
{
|
||||
case CAIRO_PATH_CURVE_TO:
|
||||
data[3].point.x *= scale; data[3].point.y *= scale;
|
||||
data[2].point.x *= scale; data[2].point.y *= scale;
|
||||
data[1].point.x *= scale; data[1].point.y *= scale;
|
||||
break;
|
||||
case CAIRO_PATH_LINE_TO:
|
||||
case CAIRO_PATH_MOVE_TO:
|
||||
data[1].point.x *= scale; data[1].point.y *= scale;
|
||||
break;
|
||||
case CAIRO_PATH_CLOSE_PATH:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
cairo_set_source_rgba (cr, 0, 0, 1, outline_alpha);
|
||||
cairo_move_to (cr, scale * 20 - 0.5, scale * 20 - 0.5);
|
||||
cairo_append_path (cr, path);
|
||||
cairo_stroke (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_path_destroy (path);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -158,10 +209,26 @@ update_image (void)
|
||||
PangoLayoutRun *run;
|
||||
PangoGlyphInfo *g;
|
||||
int i, j;
|
||||
GString *str;
|
||||
gunichar ch;
|
||||
|
||||
if (*text == '\0')
|
||||
text = " ";
|
||||
|
||||
ch = g_utf8_get_char (text);
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g_string_append_unichar (str, ch);
|
||||
g_string_append_unichar (str, 0x200c);
|
||||
}
|
||||
|
||||
layout = pango_layout_new (context);
|
||||
pango_layout_set_font_description (layout, desc);
|
||||
pango_layout_set_text (layout, "aaaa", -1);
|
||||
pango_layout_set_text (layout, str->str, -1);
|
||||
g_string_free (str, TRUE);
|
||||
pango_layout_get_extents (layout, &ink, &logical);
|
||||
pango_extents_to_pixels (&logical, NULL);
|
||||
|
||||
@@ -176,7 +243,7 @@ update_image (void)
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g = &(run->glyphs->glyphs[2*i]);
|
||||
g->geometry.width = PANGO_UNITS_ROUND (g->geometry.width * 3 / 2);
|
||||
}
|
||||
|
||||
@@ -184,7 +251,7 @@ update_image (void)
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
g = &(run->glyphs->glyphs[i]);
|
||||
g = &(run->glyphs->glyphs[2*i]);
|
||||
g->geometry.x_offset = i * (PANGO_SCALE / 4);
|
||||
g->geometry.y_offset = j * (PANGO_SCALE / 4);
|
||||
}
|
||||
@@ -203,7 +270,6 @@ update_image (void)
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2);
|
||||
|
||||
g_object_unref (pixbuf2);
|
||||
@@ -211,6 +277,78 @@ update_image (void)
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
|
||||
static gboolean fading = FALSE;
|
||||
static double start_pixel_alpha;
|
||||
static double end_pixel_alpha;
|
||||
static double start_outline_alpha;
|
||||
static double end_outline_alpha;
|
||||
static gint64 start_time;
|
||||
static gint64 end_time;
|
||||
|
||||
static double
|
||||
ease_out_cubic (double t)
|
||||
{
|
||||
double p = t - 1;
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
change_alpha (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
double t;
|
||||
|
||||
t = ease_out_cubic ((now - start_time) / (double) (end_time - start_time));
|
||||
|
||||
pixel_alpha = start_pixel_alpha + (end_pixel_alpha - start_pixel_alpha) * t;
|
||||
outline_alpha = start_outline_alpha + (end_outline_alpha - start_outline_alpha) * t;
|
||||
|
||||
update_image ();
|
||||
|
||||
if (now >= end_time)
|
||||
{
|
||||
fading = FALSE;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
start_alpha_fade (void)
|
||||
{
|
||||
gboolean pixels;
|
||||
gboolean outlines;
|
||||
|
||||
if (fading)
|
||||
return;
|
||||
|
||||
pixels = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_pixels));
|
||||
outlines = gtk_check_button_get_active (GTK_CHECK_BUTTON (show_outlines));
|
||||
|
||||
start_pixel_alpha = pixel_alpha;
|
||||
if (pixels && outlines)
|
||||
end_pixel_alpha = 0.5;
|
||||
else if (pixels)
|
||||
end_pixel_alpha = 1;
|
||||
else
|
||||
end_pixel_alpha = 0;
|
||||
|
||||
start_outline_alpha = outline_alpha;
|
||||
if (outlines)
|
||||
end_outline_alpha = 1.0;
|
||||
else
|
||||
end_outline_alpha = 0.0;
|
||||
|
||||
start_time = g_get_monotonic_time ();
|
||||
end_time = start_time + G_TIME_SPAN_SECOND / 2;
|
||||
|
||||
fading = TRUE;
|
||||
gtk_widget_add_tick_callback (window, change_alpha, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
update_buttons (void)
|
||||
{
|
||||
@@ -218,20 +356,26 @@ update_buttons (void)
|
||||
gtk_widget_set_sensitive (down_button, scale > 1);
|
||||
}
|
||||
|
||||
static void
|
||||
scale_up (void)
|
||||
static gboolean
|
||||
scale_up (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
scale += 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
scale_down (void)
|
||||
static gboolean
|
||||
scale_down (GtkWidget *widget,
|
||||
GVariant *args,
|
||||
gpointer user_data)
|
||||
{
|
||||
scale -= 1;
|
||||
update_buttons ();
|
||||
update_image ();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
@@ -252,20 +396,26 @@ do_fontrendering (GtkWidget *do_widget)
|
||||
entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
|
||||
image = GTK_WIDGET (gtk_builder_get_object (builder, "image"));
|
||||
hinting = GTK_WIDGET (gtk_builder_get_object (builder, "hinting"));
|
||||
anti_alias = GTK_WIDGET (gtk_builder_get_object (builder, "antialias"));
|
||||
hint_metrics = GTK_WIDGET (gtk_builder_get_object (builder, "hint_metrics"));
|
||||
text_radio = GTK_WIDGET (gtk_builder_get_object (builder, "text_radio"));
|
||||
show_grid = GTK_WIDGET (gtk_builder_get_object (builder, "show_grid"));
|
||||
show_extents = GTK_WIDGET (gtk_builder_get_object (builder, "show_extents"));
|
||||
show_pixels = GTK_WIDGET (gtk_builder_get_object (builder, "show_pixels"));
|
||||
show_outlines = GTK_WIDGET (gtk_builder_get_object (builder, "show_outlines"));
|
||||
|
||||
g_signal_connect (up_button, "clicked", G_CALLBACK (scale_up), NULL);
|
||||
g_signal_connect (down_button, "clicked", G_CALLBACK (scale_down), NULL);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (font_button, "notify::font-desc", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hinting, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (anti_alias, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (hint_metrics, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (text_radio, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_grid, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_extents, "notify::active", G_CALLBACK (update_image), NULL);
|
||||
g_signal_connect (show_pixels, "notify::active", G_CALLBACK (start_alpha_fade), NULL);
|
||||
g_signal_connect (show_outlines, "notify::active", G_CALLBACK (start_alpha_fade), NULL);
|
||||
|
||||
update_image ();
|
||||
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkAdjustment" id="scale_adj">
|
||||
<property name="upper">24</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">4</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="default-width">1080</property>
|
||||
<property name="default-height">430</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<child type="title">
|
||||
@@ -87,35 +82,62 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Hinting</property>
|
||||
<property name="xalign">1</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<object class="GtkCheckButton" id="show_pixels">
|
||||
<property name="label">Show _Pixels</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="active">1</property>
|
||||
<layout>
|
||||
<property name="column">3</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
<object class="GtkCheckButton" id="show_outlines">
|
||||
<property name="label">Show _Outline</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">3</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">_Hinting</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="mnemonic-widget">hinting</property>
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="hinting">
|
||||
<property name="active">0</property>
|
||||
<property name="valign">center</property>
|
||||
<items>
|
||||
<item translatable="yes" id="none">None</item>
|
||||
<item translatable="yes" id="slight">Slight</item>
|
||||
<item translatable="yes" id="medium">Medium</item>
|
||||
<item translatable="yes" id="full">Full</item>
|
||||
</items>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="hint_metrics">
|
||||
<property name="label">Hint Metrics</property>
|
||||
<object class="GtkCheckButton" id="antialias">
|
||||
<property name="label">_Antialias</property>
|
||||
<property name="use-underline">1</property>
|
||||
<property name="active">1</property>
|
||||
<layout>
|
||||
<property name="column">4</property>
|
||||
<property name="row">1</property>
|
||||
@@ -123,21 +145,31 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_extents">
|
||||
<property name="label">Show Extents</property>
|
||||
<property name="active">1</property>
|
||||
<object class="GtkCheckButton" id="hint_metrics">
|
||||
<property name="label">Hint _Metrics</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">5</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_extents">
|
||||
<property name="label">Show _Extents</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="show_grid">
|
||||
<property name="active">1</property>
|
||||
<property name="label">Show Grid</property>
|
||||
<property name="label">Show _Grid</property>
|
||||
<property name="use-underline">1</property>
|
||||
<layout>
|
||||
<property name="column">5</property>
|
||||
<property name="column">6</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -148,8 +180,19 @@
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger"><Control>plus</property>
|
||||
<property name="action">activate</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="column">7</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -160,8 +203,19 @@
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkShortcutController">
|
||||
<property name="scope">managed</property>
|
||||
<child>
|
||||
<object class="GtkShortcut">
|
||||
<property name="trigger"><Control>minus</property>
|
||||
<property name="action">activate</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<layout>
|
||||
<property name="column">6</property>
|
||||
<property name="column">7</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
@@ -170,7 +224,7 @@
|
||||
<object class="GtkLabel">
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">7</property>
|
||||
<property name="column">8</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
@@ -61,12 +61,26 @@ show_page (GtkTextView *text_view,
|
||||
int page)
|
||||
{
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter iter, start;
|
||||
GtkTextMark *mark;
|
||||
GtkWidget *child;
|
||||
GtkTextChildAnchor *anchor;
|
||||
GtkEventController *controller;
|
||||
GtkTextTag *bold, *mono, *nobreaks;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (text_view);
|
||||
|
||||
bold = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
mono = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
nobreaks = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"allow-breaks", FALSE,
|
||||
NULL);
|
||||
|
||||
gtk_text_buffer_set_text (buffer, "", 0);
|
||||
gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
|
||||
gtk_text_buffer_begin_irreversible_action (buffer);
|
||||
@@ -104,17 +118,22 @@ show_page (GtkTextView *text_view,
|
||||
}
|
||||
else if (page == 2)
|
||||
{
|
||||
GtkTextTag *tag;
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / tag / ", -1, tag, NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "tag", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -132,20 +151,26 @@ show_page (GtkTextView *text_view,
|
||||
"behavior of mouse and key presses, “lock” a range of text so the "
|
||||
"user can't edit it, or countless other things.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
else if (page == 3)
|
||||
{
|
||||
GtkTextTag *tag;
|
||||
mark = gtk_text_buffer_create_mark (buffer, "mark", &iter, TRUE);
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"weight", PANGO_WEIGHT_BOLD,
|
||||
"scale", PANGO_SCALE_X_LARGE,
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, tag, NULL);
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL,
|
||||
"family", "monospace",
|
||||
NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, " / ˈhaɪ pərˌtɛkst / ", -1, tag, NULL);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "hypertext", -1, bold, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
||||
gtk_text_buffer_insert_with_tags (buffer, &iter, "ˈhaɪ pərˌtɛkst", -1, mono, NULL);
|
||||
gtk_text_buffer_insert (buffer, &iter, " /", -1);
|
||||
gtk_text_buffer_get_iter_at_mark (buffer, &start, mark);
|
||||
gtk_text_buffer_apply_tag (buffer, nobreaks, &start, &iter);
|
||||
gtk_text_buffer_insert (buffer, &iter, " ", -1);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
|
||||
child = gtk_image_new_from_icon_name ("audio-volume-high-symbolic");
|
||||
@@ -159,6 +184,8 @@ show_page (GtkTextView *text_view,
|
||||
"Machine-readable text that is not sequential but is organized "
|
||||
"so that related items of information are connected.\n", -1);
|
||||
insert_link (buffer, &iter, "Go back", 1);
|
||||
|
||||
gtk_text_buffer_delete_mark (buffer, mark);
|
||||
}
|
||||
gtk_text_buffer_end_irreversible_action (buffer);
|
||||
}
|
||||
@@ -358,7 +385,7 @@ do_hypertext (GtkWidget *do_widget)
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view);
|
||||
|
||||
@@ -58,7 +58,7 @@ do_markup (GtkWidget *do_widget)
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 680);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
stack = gtk_stack_new ();
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
Text sizes: <span size="xx-small">tiny</span> <span size="x-small">very small</span> <span size="small">small</span> <span size="medium">normal</span> <span size="large">large</span> <span size="x-large">very large</span> <span size="xx-large">huge</span>
|
||||
Text sizes: <span size="xx-small">tiny </span><span size="x-small">very small </span><span size="small">small </span><span size="medium">normal </span><span size="large">large </span><span size="x-large">very large </span><span size="xx-large">huge</span>
|
||||
|
||||
Text styles: <span style="normal">Normal</span> <span style="italic">Italic</span> <span style="oblique">Olique</span>
|
||||
|
||||
Text weights: <span weight="thin">thin</span> <span weight="light">light</span> <span weight="normal">normal</span> <span weight="bold">bold</span> <span weight="ultraheavy">ultraheavy</span>
|
||||
|
||||
Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</span>rs</span> and <span background="pink">backgrounds</span>
|
||||
|
||||
@@ -15,6 +19,12 @@ OpenType font features: <span font_desc="sans regular" font_features="dlig=0">fe
|
||||
|
||||
Shortcuts: <tt>Monospace</tt> – <b>Bold</b> – <i>Italic</i> – <big>Big</big> – <small>Small</small> – <u>Underlined</u> – <s>Strikethrough</s> – Super<sup>script</sup> – Sub<sub>script</sub>
|
||||
|
||||
<span allow_breaks="false">A</span> hyphenation algorithm is a set of rules, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as <span allow_breaks="false">impeach‧ment</span> or <span allow_breaks="false">im‧peachment</span> but not <span allow_breaks="false">impe‧achment.</span>
|
||||
hyphenation algorithm is a <span allow_breaks="false" style="italic">set of rules</span>, especially one codified for implementation in a computer program, that decides at which points a word can be broken over two lines with a hyphen. For example, a hyphenation algorithm might decide that impeachment can be broken as impeach‧ment or im‧peachment but not impe‧achment.
|
||||
|
||||
<span insert_hyphens="false">one/two three/four five/six seven/eight nine/ten</span>
|
||||
|
||||
<span line_height='1.33'>Line height: This is an example of widely spaced text. It was achieved by setting the line-height factor to 1.33. You can set the line-height factor to any value between 0 and 10.
|
||||
Note that the line height affects the spacing between paragraphs as well as between the wrapped lines inside a paragraph.</span>
|
||||
|
||||
Transforms: <span text_transform='uppercase'>straße</span> <span text_transform='capitalize'>up, up and away</span>
|
||||
|
||||
|
||||
@@ -21,8 +21,10 @@ do_menu (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
@@ -31,11 +33,23 @@ do_menu (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
|
||||
gtk_range_set_value (GTK_RANGE (scale), 1.0);
|
||||
gtk_box_append (GTK_BOX (box), scale);
|
||||
|
||||
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -67,6 +67,7 @@ demos = files([
|
||||
'paintable_animated.c',
|
||||
'paintable_emblem.c',
|
||||
'paintable_mediastream.c',
|
||||
'paintable_symbolic.c',
|
||||
'panes.c',
|
||||
'password_entry.c',
|
||||
'peg_solitaire.c',
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.Demo4.desktop</id>
|
||||
<id>org.gtk.Demo4</id>
|
||||
<launchable type="desktop-id">org.gtk.Demo4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Demo</name>
|
||||
<summary>Program to demonstrate GTK functions</summary>
|
||||
<description>
|
||||
@@ -30,6 +31,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
||||
@@ -45,26 +45,27 @@ struct _GtkNuclearIconClass
|
||||
* so that it can be called from all the other demos, too.
|
||||
*/
|
||||
void
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
double rotation,
|
||||
gboolean draw_background)
|
||||
gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation)
|
||||
{
|
||||
#define RADIUS 0.3
|
||||
cairo_t *cr;
|
||||
double size;
|
||||
|
||||
if (draw_background)
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 },
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_append_color (snapshot,
|
||||
background,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
size = MIN (width, height);
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT ((width - size) / 2.0,
|
||||
(height - size) / 2.0,
|
||||
size, size));
|
||||
gdk_cairo_set_source_rgba (cr, foreground);
|
||||
cairo_translate (cr, width / 2.0, height / 2.0);
|
||||
cairo_scale (cr, size, size);
|
||||
cairo_rotate (cr, rotation);
|
||||
@@ -94,9 +95,10 @@ gtk_nuclear_icon_snapshot (GdkPaintable *paintable,
|
||||
*/
|
||||
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
nuclear->rotation,
|
||||
TRUE);
|
||||
nuclear->rotation);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
void gtk_nuclear_snapshot (GtkSnapshot *snapshot,
|
||||
const GdkRGBA *foreground,
|
||||
const GdkRGBA *background,
|
||||
double width,
|
||||
double height,
|
||||
double rotation,
|
||||
gboolean draw_background);
|
||||
double rotation);
|
||||
|
||||
GdkPaintable * gtk_nuclear_icon_new (double rotation);
|
||||
GdkPaintable * gtk_nuclear_animation_new (gboolean draw_background);
|
||||
|
||||
@@ -65,9 +65,12 @@ gtk_nuclear_animation_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
nuclear->draw_background
|
||||
? &(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 } /* yellow */
|
||||
: &(GdkRGBA) { 0, 0, 0, 0 }, /* transparent */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS,
|
||||
nuclear->draw_background);
|
||||
2 * G_PI * nuclear->progress / MAX_PROGRESS);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
|
||||
@@ -73,9 +73,10 @@ gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
|
||||
|
||||
/* We call the function from the previous example here. */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
|
||||
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
|
||||
width, height,
|
||||
2 * G_PI * nuclear->progress / DURATION,
|
||||
TRUE);
|
||||
2 * G_PI * nuclear->progress / DURATION);
|
||||
}
|
||||
|
||||
static GdkPaintable *
|
||||
@@ -150,7 +151,7 @@ gtk_nuclear_media_stream_step (gpointer data)
|
||||
* call our pause function to pause the stream.
|
||||
*/
|
||||
if (nuclear->progress >= DURATION)
|
||||
gtk_media_stream_ended (GTK_MEDIA_STREAM (nuclear));
|
||||
gtk_media_stream_stream_ended (GTK_MEDIA_STREAM (nuclear));
|
||||
|
||||
/* The timeout function is removed by the pause function,
|
||||
* so we can just always return this value.
|
||||
@@ -267,11 +268,11 @@ gtk_nuclear_media_stream_init (GtkNuclearMediaStream *nuclear)
|
||||
* However, media streams need to tell GTK once they are initialized,
|
||||
* so we do that here.
|
||||
*/
|
||||
gtk_media_stream_prepared (GTK_MEDIA_STREAM (nuclear),
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
DURATION);
|
||||
gtk_media_stream_stream_prepared (GTK_MEDIA_STREAM (nuclear),
|
||||
FALSE,
|
||||
TRUE,
|
||||
TRUE,
|
||||
DURATION);
|
||||
}
|
||||
|
||||
/* And finally, we add the simple constructor we declared in the header. */
|
||||
|
||||
208
demos/gtk-demo/paintable_symbolic.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/* Paintable/Symbolic Paintable
|
||||
*
|
||||
* GdkPaintables can be made to follow the theme's colors. GTK calls
|
||||
* icons that do this symbolic icons, paintables that want to have
|
||||
* the same effect can implement the GtkSymbolicPaintable interface.
|
||||
*
|
||||
* We will adapt the original paintable example by adding the ability
|
||||
* to recolor the paintable based on the symbolic colors.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "paintable.h"
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
/* First, add the boilerplate for the object itself.
|
||||
* This part would normally go in the header.
|
||||
*/
|
||||
#define GTK_TYPE_NUCLEAR_SYMBOLIC (gtk_nuclear_symbolic_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (GtkNuclearSymbolic, gtk_nuclear_symbolic, GTK, NUCLEAR_SYMBOLIC, GObject)
|
||||
|
||||
/* Declare a few warning levels, so we can pick colors based on them */
|
||||
typedef enum
|
||||
{
|
||||
WARNING_NONE,
|
||||
WARNING_ALERT,
|
||||
WARNING_EMERGENCY
|
||||
} WarningLevel;
|
||||
|
||||
/* Declare the struct. */
|
||||
struct _GtkNuclearSymbolic
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
WarningLevel warning_level;
|
||||
};
|
||||
|
||||
struct _GtkNuclearSymbolicClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
/* Add a function to draw the nuclear icon in the given colors */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot_symbolic (GtkSymbolicPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height,
|
||||
const GdkRGBA *colors,
|
||||
gsize n_colors)
|
||||
{
|
||||
GtkNuclearSymbolic *self = GTK_NUCLEAR_SYMBOLIC (paintable);
|
||||
static const GdkRGBA transparent = { 0, };
|
||||
const GdkRGBA *bg_color;
|
||||
|
||||
/* select the right background color from the warning level */
|
||||
switch (self->warning_level)
|
||||
{
|
||||
case WARNING_NONE:
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
case WARNING_ALERT:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_WARNING];
|
||||
break;
|
||||
case WARNING_EMERGENCY:
|
||||
bg_color = &colors[GTK_SYMBOLIC_COLOR_ERROR];
|
||||
break;
|
||||
default:
|
||||
/* This should never happen, but we better do defensive coding
|
||||
* with this critical icon */
|
||||
g_assert_not_reached ();
|
||||
bg_color = &transparent;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Draw the icon with the selected warning color */
|
||||
gtk_nuclear_snapshot (snapshot,
|
||||
&colors[GTK_SYMBOLIC_COLOR_FOREGROUND],
|
||||
bg_color,
|
||||
width, height,
|
||||
0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init (GtkSymbolicPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot_symbolic = gtk_nuclear_symbolic_snapshot_symbolic;
|
||||
}
|
||||
|
||||
/* We need to implement the functionality required by the GdkPaintable interface */
|
||||
static void
|
||||
gtk_nuclear_symbolic_snapshot (GdkPaintable *paintable,
|
||||
GdkSnapshot *snapshot,
|
||||
double width,
|
||||
double height)
|
||||
{
|
||||
/* Calling this function without passing a color is a neat trick
|
||||
* to make GTK use default colors and otherwise forward the call
|
||||
* to the snapshotting function above.
|
||||
*/
|
||||
gtk_symbolic_paintable_snapshot_symbolic (GTK_SYMBOLIC_PAINTABLE (paintable),
|
||||
snapshot,
|
||||
width, height,
|
||||
NULL, 0);
|
||||
}
|
||||
|
||||
static GdkPaintableFlags
|
||||
gtk_nuclear_symbolic_get_flags (GdkPaintable *paintable)
|
||||
{
|
||||
/* This image has a static size, but the contents may change:
|
||||
* We draw different things when the warning level changes.
|
||||
*/
|
||||
return GDK_PAINTABLE_STATIC_SIZE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_paintable_init (GdkPaintableInterface *iface)
|
||||
{
|
||||
iface->snapshot = gtk_nuclear_symbolic_snapshot;
|
||||
iface->get_flags = gtk_nuclear_symbolic_get_flags;
|
||||
}
|
||||
|
||||
/* When defining the GType, we need to implement bot the GdkPaintable
|
||||
* and the GtkSymbolicPaintable interface */
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkNuclearSymbolic, gtk_nuclear_symbolic, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
|
||||
gtk_nuclear_symbolic_paintable_init)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_SYMBOLIC_PAINTABLE,
|
||||
gtk_nuclear_symbolic_symbolic_paintable_init))
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_class_init (GtkNuclearSymbolicClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_nuclear_symbolic_init (GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
}
|
||||
|
||||
/* And finally, we add the simple constructor we declared in the header. */
|
||||
GdkPaintable *
|
||||
gtk_nuclear_symbolic_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_NUCLEAR_SYMBOLIC, NULL);
|
||||
}
|
||||
|
||||
/* Add some fun feature to the button */
|
||||
static void
|
||||
nuclear_button_clicked (GtkButton *button,
|
||||
GtkNuclearSymbolic *nuclear)
|
||||
{
|
||||
if (nuclear->warning_level >= WARNING_EMERGENCY)
|
||||
{
|
||||
/* On maximum warning level, reset the warning */
|
||||
nuclear->warning_level = WARNING_NONE;
|
||||
/* And sometimes (but not always to confuse people)
|
||||
* close the window.
|
||||
*/
|
||||
if (g_random_boolean ())
|
||||
gtk_window_close (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise just increase the warning level */
|
||||
nuclear->warning_level++;
|
||||
}
|
||||
|
||||
/* Don't forget to emit the signal causing the paintable to redraw.
|
||||
* Changing the warning level changes the background color after all.
|
||||
*/
|
||||
gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paintable_symbolic (GtkWidget *do_widget)
|
||||
{
|
||||
GdkPaintable *nuclear;
|
||||
GtkWidget *image, *button;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Don't click!");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), button);
|
||||
|
||||
nuclear = gtk_nuclear_symbolic_new ();
|
||||
image = gtk_image_new_from_paintable (nuclear);
|
||||
|
||||
gtk_button_set_child (GTK_BUTTON (button), image);
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (nuclear_button_clicked), nuclear);
|
||||
g_object_unref (nuclear);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* Peg Solitaire
|
||||
* #Keywords: GtkGridView, game
|
||||
*
|
||||
* This demo demonstrates how to use drag'n'drop to implement peg solitaire.
|
||||
* This demo demonstrates how to use drag-and-drop to implement peg solitaire.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -98,7 +98,7 @@ solitaire_peg_init (SolitairePeg *peg)
|
||||
|
||||
/* Add a little setter for the peg's position.
|
||||
* We want to track those so that we can check for legal moves
|
||||
* during drag'n'drop operations.
|
||||
* during drag-and-drop operations.
|
||||
*/
|
||||
static void
|
||||
solitaire_peg_set_position (SolitairePeg *peg,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.IconBrowser4.desktop</id>
|
||||
<id>org.gtk.IconBrowser4</id>
|
||||
<launchable type="desktop-id">org.gtk.IconBrowser4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Icon Browser</name>
|
||||
<summary>Program to browse themed icons</summary>
|
||||
<description>
|
||||
@@ -29,6 +30,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "gtkrendererpaintableprivate.h"
|
||||
|
||||
#include "gsk/gskrendernodeparserprivate.h"
|
||||
#include "gsk/gl/gskglrenderer.h"
|
||||
#include "gsk/ngl/gsknglrenderer.h"
|
||||
#ifdef GDK_WINDOWING_BROADWAY
|
||||
#include "gsk/broadway/gskbroadwayrenderer.h"
|
||||
@@ -61,7 +60,7 @@ struct _NodeEditorWindow
|
||||
|
||||
GtkWidget *renderer_listbox;
|
||||
GListStore *renderers;
|
||||
GdkPaintable *paintable;
|
||||
GskRenderNode *node;
|
||||
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
@@ -168,7 +167,6 @@ static void
|
||||
text_changed (GtkTextBuffer *buffer,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
char *text;
|
||||
GBytes *bytes;
|
||||
GtkTextIter iter;
|
||||
@@ -179,10 +177,12 @@ text_changed (GtkTextBuffer *buffer,
|
||||
text_buffer_remove_all_tags (self->text_buffer);
|
||||
bytes = g_bytes_new_take (text, strlen (text));
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
|
||||
/* If this is too slow, go fix the parser performance */
|
||||
node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
self->node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
g_bytes_unref (bytes);
|
||||
if (node)
|
||||
if (self->node)
|
||||
{
|
||||
/* XXX: Is this code necessary or can we have API to turn nodes into paintables? */
|
||||
GtkSnapshot *snapshot;
|
||||
@@ -191,10 +191,9 @@ text_changed (GtkTextBuffer *buffer,
|
||||
guint i;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
gsk_render_node_get_bounds (self->node, &bounds);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
gtk_snapshot_append_node (snapshot, self->node);
|
||||
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
|
||||
@@ -338,15 +337,9 @@ text_view_query_tooltip_cb (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
load_bytes (NodeEditorWindow *self,
|
||||
GBytes *bytes)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL))
|
||||
{
|
||||
g_bytes_unref (bytes);
|
||||
@@ -362,6 +355,105 @@ load_file_contents (NodeEditorWindow *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
load_file_contents (NodeEditorWindow *self,
|
||||
GFile *file)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
return load_bytes (self, bytes);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare_cb (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
if (self->node == NULL)
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GSK_TYPE_RENDER_NODE, self->node);
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_done_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GOutputStream *stream = G_OUTPUT_STREAM (source);
|
||||
GdkDrop *drop = g_object_get_data (source, "drop");
|
||||
GdkDragAction action = 0;
|
||||
GBytes *bytes;
|
||||
|
||||
if (g_output_stream_splice_finish (stream, res, NULL) >= 0)
|
||||
{
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
|
||||
if (load_bytes (self, bytes))
|
||||
action = GDK_ACTION_COPY;
|
||||
}
|
||||
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, action);
|
||||
g_object_unref (drop);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
on_picture_drop_read_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
NodeEditorWindow *self = data;
|
||||
GdkDrop *drop = GDK_DROP (source);
|
||||
GInputStream *input;
|
||||
GOutputStream *output;
|
||||
|
||||
input = gdk_drop_read_finish (drop, res, NULL, NULL);
|
||||
if (input == NULL)
|
||||
{
|
||||
g_object_unref (self);
|
||||
gdk_drop_finish (drop, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
output = g_memory_output_stream_new_resizable ();
|
||||
g_object_set_data (G_OBJECT (output), "drop", drop);
|
||||
g_object_ref (drop);
|
||||
|
||||
g_output_stream_splice_async (output,
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_done_cb,
|
||||
self);
|
||||
g_object_unref (output);
|
||||
g_object_unref (input);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop_cb (GtkDropTargetAsync *dest,
|
||||
GdkDrop *drop,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
gdk_drop_read_async (drop,
|
||||
(const char *[2]) { "application/x-gtk-render-node", NULL },
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_picture_drop_read_cb,
|
||||
g_object_ref (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
file_changed_cb (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
@@ -736,6 +828,7 @@ node_editor_window_finalize (GObject *object)
|
||||
|
||||
g_array_free (self->errors, TRUE);
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
g_clear_object (&self->renderers);
|
||||
|
||||
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
|
||||
@@ -778,12 +871,9 @@ node_editor_window_realize (GtkWidget *widget)
|
||||
NULL,
|
||||
"Default");
|
||||
#endif
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_gl_renderer_new (),
|
||||
"OpenGL");
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_ngl_renderer_new (),
|
||||
"NGL");
|
||||
"OpenGL");
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
node_editor_window_add_renderer (self,
|
||||
gsk_vulkan_renderer_new (),
|
||||
@@ -848,6 +938,8 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
|
||||
@@ -200,6 +200,19 @@
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTargetAsync">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">application/x-gtk-render-node</property>
|
||||
<signal name="drop" handler="on_picture_drop_cb" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.PrintEditor4.desktop</id>
|
||||
<id>org.gtk.PrintEditor4</id>
|
||||
<launchable type="desktop-id">org.gtk.PrintEditor4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Print Editor</name>
|
||||
<summary>Program to demonstrate GTK printing</summary>
|
||||
<description>
|
||||
@@ -24,6 +25,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="3.99.0" date="2020-07-30">
|
||||
<description>
|
||||
|
||||
@@ -721,7 +721,6 @@ static const char ui_info[] =
|
||||
" <item>"
|
||||
" <attribute name='label'>_New</attribute>"
|
||||
" <attribute name='action'>app.new</attribute>"
|
||||
" <attribute name='accel'><Primary>n</attribute>"
|
||||
" </item>"
|
||||
" <item>"
|
||||
" <attribute name='label'>_Open</attribute>"
|
||||
@@ -730,12 +729,10 @@ static const char ui_info[] =
|
||||
" <item>"
|
||||
" <attribute name='label'>_Save</attribute>"
|
||||
" <attribute name='action'>app.save</attribute>"
|
||||
" <attribute name='accel'><Primary>s</attribute>"
|
||||
" </item>"
|
||||
" <item>"
|
||||
" <attribute name='label'>Save _As...</attribute>"
|
||||
" <attribute name='action'>app.save-as</attribute>"
|
||||
" <attribute name='accel'><Primary>s</attribute>"
|
||||
" </item>"
|
||||
" </section>"
|
||||
" <section>"
|
||||
@@ -756,7 +753,6 @@ static const char ui_info[] =
|
||||
" <item>"
|
||||
" <attribute name='label'>_Quit</attribute>"
|
||||
" <attribute name='action'>app.quit</attribute>"
|
||||
" <attribute name='accel'><Primary>q</attribute>"
|
||||
" </item>"
|
||||
" </section>"
|
||||
" </submenu>"
|
||||
@@ -766,7 +762,6 @@ static const char ui_info[] =
|
||||
" <item>"
|
||||
" <attribute name='label'>_About Print Editor</attribute>"
|
||||
" <attribute name='action'>app.about</attribute>"
|
||||
" <attribute name='accel'><Primary>a</attribute>"
|
||||
" </item>"
|
||||
" </section>"
|
||||
" </submenu>"
|
||||
@@ -794,6 +789,15 @@ startup (GApplication *app)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GMenuModel *menubar;
|
||||
struct {
|
||||
const char *action_and_target;
|
||||
const char *accelerators[2];
|
||||
} accels[] = {
|
||||
{ "app.new", { "<Control>n", NULL } },
|
||||
{ "app.quit", { "<Control>q", NULL } },
|
||||
{ "app.save", { "<Control>s", NULL } },
|
||||
{ "app.about", { "<Control>a", NULL } },
|
||||
};
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_add_from_string (builder, ui_info, -1, NULL);
|
||||
@@ -802,6 +806,9 @@ startup (GApplication *app)
|
||||
|
||||
gtk_application_set_menubar (GTK_APPLICATION (app), menubar);
|
||||
|
||||
for (int i = 0; i < G_N_ELEMENTS (accels); i++)
|
||||
gtk_application_set_accels_for_action (GTK_APPLICATION (app), accels[i].action_and_target, accels[i].accelerators);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
|
||||
BIN
demos/widget-factory/beach.jpg
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
demos/widget-factory/nyc.jpg
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
@@ -1,8 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>org.gtk.WidgetFactory4.desktop</id>
|
||||
<id>org.gtk.WidgetFactory4</id>
|
||||
<launchable type="desktop-id">org.gtk.WidgetFactory4.desktop</launchable>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>LGPL-2.0+</project_license>
|
||||
<project_license>LGPL-2.1-or-later</project_license>
|
||||
<name>GTK Widget Factory</name>
|
||||
<summary>Program to demonstrate GTK functions</summary>
|
||||
<description>
|
||||
@@ -31,6 +32,7 @@
|
||||
<translation type="gettext">gtk-4.0</translation>
|
||||
<update_contact>matthias.clasen_at_gmail.com</update_contact>
|
||||
<developer_name>Matthias Clasen and others</developer_name>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<releases>
|
||||
<release version="@BUILD_VERSION@" date="@BUILD_DATE@">
|
||||
<description>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.9 MiB |
@@ -696,6 +696,37 @@ on_range_to_changed (GtkSpinButton *to)
|
||||
gtk_spin_button_set_value (from, v2);
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
on_picture_drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, gtk_picture_get_paintable (GTK_PICTURE (picture)));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_picture_drop (GtkDropTarget *dest,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GdkPaintable *paintable;
|
||||
|
||||
picture = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
|
||||
paintable = g_value_get_object (value);
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
info_bar_response (GtkWidget *infobar, int response_id)
|
||||
{
|
||||
@@ -1182,7 +1213,7 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
GtkWidget *child;
|
||||
int i;
|
||||
const char *resources[] = {
|
||||
"sunset.jpg", "snowy.jpg", "portland-rose.jpg"
|
||||
"sunset.jpg", "portland-rose.jpg", "beach.jpg", "nyc.jpg"
|
||||
};
|
||||
|
||||
if (GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (flowbox), "populated")))
|
||||
@@ -1997,6 +2028,7 @@ activate (GApplication *app)
|
||||
const char *accelerators[2];
|
||||
} accels[] = {
|
||||
{ "app.about", { "F1", NULL } },
|
||||
{ "app.shortcuts", { "<Control>question", NULL } },
|
||||
{ "app.quit", { "<Control>q", NULL } },
|
||||
{ "app.open-in", { "<Control>n", NULL } },
|
||||
{ "win.dark", { "<Control>d", NULL } },
|
||||
@@ -2039,6 +2071,8 @@ activate (GApplication *app)
|
||||
"on_page_combo_changed", (GCallback)on_page_combo_changed,
|
||||
"on_range_from_changed", (GCallback)on_range_from_changed,
|
||||
"on_range_to_changed", (GCallback)on_range_to_changed,
|
||||
"on_picture_drag_prepare", (GCallback)on_picture_drag_prepare,
|
||||
"on_picture_drop", (GCallback)on_picture_drop,
|
||||
"tab_close_cb", (GCallback)tab_close_cb,
|
||||
"increase_icon_size", (GCallback)increase_icon_size,
|
||||
"decrease_icon_size", (GCallback)decrease_icon_size,
|
||||
|
||||
@@ -115,7 +115,8 @@
|
||||
<gresource prefix="/org/gtk/WidgetFactory4">
|
||||
<file>gtk-logo.webm</file>
|
||||
<file>sunset.jpg</file>
|
||||
<file>snowy.jpg</file>
|
||||
<file>portland-rose.jpg</file>
|
||||
<file>nyc.jpg</file>
|
||||
<file>beach.jpg</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
@@ -1051,22 +1051,9 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="hexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkFrame" id="frame1">
|
||||
<property name="valign">start</property>
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Video</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<object class="GtkFrame">
|
||||
<child>
|
||||
<object class="GtkVideo">
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="autoplay">1</property>
|
||||
<property name="loop">1</property>
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/gtk-logo.webm</property>
|
||||
@@ -1075,66 +1062,78 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<object class="GtkFrame">
|
||||
<child type="label">
|
||||
<object class="GtkLabel" id="label1">
|
||||
<property name="label" translatable="yes"><b>Text Styles</b></property>
|
||||
<property name="use-markup">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="vexpand">1</property>
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="vscrollbar-policy">automatic</property>
|
||||
<property name="propagate-natural-height">1</property>
|
||||
<property name="propagate-natural-width">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Large Title</property>
|
||||
<style><class name="large-title"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 1</property>
|
||||
<style><class name="title-1"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 2</property>
|
||||
<style><class name="title-2"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 3</property>
|
||||
<style><class name="title-3"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Title 4</property>
|
||||
<style><class name="title-4"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Heading</property>
|
||||
<style><class name="heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Body</property>
|
||||
<style><class name="body"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption Heading</property>
|
||||
<style><class name="caption-heading"/></style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Caption</property>
|
||||
<style><class name="caption"/></style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -1251,8 +1250,21 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box6">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/sunset.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1265,8 +1277,21 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box7">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/nyc.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1278,10 +1303,22 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="position">2</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">vertical</property>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/beach.jpg</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<property name="actions">copy</property>
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropTarget">
|
||||
<property name="actions">copy</property>
|
||||
<property name="formats">GdkTexture</property>
|
||||
<signal name="drop" handler="on_picture_drop" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
@@ -1299,7 +1336,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box9">
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
</property>
|
||||
@@ -2902,7 +2939,7 @@ bad things might happen.</property>
|
||||
|
||||
<action-widgets>
|
||||
<action-widget response="cancel">cancel_info_dialog</action-widget>
|
||||
<action-widget response="ok">doit_info_dialog</action-widget>
|
||||
<action-widget response="ok" default="true">doit_info_dialog</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
<object class="GtkDialog" id="action_dialog">
|
||||
|
||||
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
||||
@@ -13,7 +13,7 @@ devhelp = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "Cairo"
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
expand_content_md_files = [
|
||||
]
|
||||
|
||||
gdk4_toml = configure_file(input: 'gdk4.toml.in', output: 'gdk4.toml', configuration: toml_conf)
|
||||
gdk4x11_toml = configure_file(input: 'gdk4-x11.toml.in', output: 'gdk4-x11.toml', configuration: toml_conf)
|
||||
gdk4wayland_toml = configure_file(input: 'gdk4-wayland.toml.in', output: 'gdk4-wayland.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gdk4_toml = configure_file(
|
||||
input: 'gdk4.toml.in',
|
||||
output: 'gdk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4',
|
||||
)
|
||||
|
||||
custom_target('gdk4-doc',
|
||||
input: [ gdk4_toml, gdk_gir[0] ],
|
||||
output: 'gdk4',
|
||||
@@ -28,6 +32,14 @@ if get_option('gtk_doc')
|
||||
)
|
||||
|
||||
if x11_enabled
|
||||
gdk4x11_toml = configure_file(
|
||||
input: 'gdk4-x11.toml.in',
|
||||
output: 'gdk4-x11.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-x11',
|
||||
)
|
||||
|
||||
custom_target('gdk4-x11-doc',
|
||||
input: [ gdk4x11_toml, gdk_x11_gir[0] ],
|
||||
output: 'gdk4-x11',
|
||||
@@ -52,6 +64,14 @@ if get_option('gtk_doc')
|
||||
endif
|
||||
|
||||
if wayland_enabled
|
||||
gdk4wayland_toml = configure_file(
|
||||
input: 'gdk4-wayland.toml.in',
|
||||
output: 'gdk4-wayland.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gdk4-wayland',
|
||||
)
|
||||
|
||||
custom_target('gdk4-wayland-doc',
|
||||
input: [ gdk4wayland_toml, gdk_wayland_gir[0] ],
|
||||
output: 'gdk4-wayland',
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable/"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
gsk4_toml = configure_file(input: 'gsk4.toml.in', output: 'gsk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gsk4_toml = configure_file(
|
||||
input: 'gsk4.toml.in',
|
||||
output: 'gsk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gsk4',
|
||||
)
|
||||
|
||||
custom_target('gsk4-doc',
|
||||
input: [ gsk4_toml, gsk_gir[0] ],
|
||||
output: 'gsk4',
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
||||
@@ -162,6 +162,8 @@ done with
|
||||
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|
||||
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|
||||
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|
||||
|text-transform| [CSS Text Level 3](https://www.w3.org/TR/css-text-3/#text-transform-property) | CSS allows full-width and full-size-kana. Since 4.6 |
|
||||
|line-height| [CSS Inline Layout Level 3](https://www.w3.org/TR/css-inline-3/#line-height-property) | Since 4.6 |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|
||||
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|
||||
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|
||||
|
||||
54
docs/reference/gtk/drag-and-drop.md
Normal file
@@ -0,0 +1,54 @@
|
||||
Title: Drag-and-Drop in GTK
|
||||
|
||||
Drag-and-Drop (DND) is a user interaction pattern where users drag a UI element
|
||||
from one place to another, either inside a single application or between
|
||||
different application windows.
|
||||
|
||||
When the element is 'dropped', data is transferred from the source to the
|
||||
destination, according to the drag action that is negotiated between both
|
||||
sides. Most commonly, that is a _copy_, but it can also be a _move_ or a
|
||||
_link_, depending on the kind of data and how the drag operation has been
|
||||
set up.
|
||||
|
||||
This chapter gives an overview over how Drag-and-Drop is handled with event
|
||||
controllers in GTK.
|
||||
|
||||
## Drag sources
|
||||
|
||||
To make data available via DND, you create a [class@Gtk.DragSource]. Drag sources
|
||||
are event controllers, which initiate a Drag-and-Drop operation when the user clicks
|
||||
and drags the widget.
|
||||
|
||||
A drag source can be set up ahead of time, with the desired drag action(s) and the data
|
||||
to be transferred. But it is also possible to provide the data when a drag operation
|
||||
is about to begin, by connecting to the [signal@Gtk.DragSource::prepare] signal.
|
||||
|
||||
The GtkDragSource emits the [signal@Gtk.DragSource::drag-begin] signal when the DND
|
||||
operation starts, and the [signal@Gtk.DragSource::drag-end] signal when it is done.
|
||||
But it is not normally necessary to handle these signals. One case in which a ::drag-end
|
||||
handler is necessary is to implement `GDK_ACTION_MOVE`.
|
||||
|
||||
## Drop targets
|
||||
|
||||
To receive data via DND, you create a [class@Gtk.DropTarget], and tell it what kind of
|
||||
data to accept. You need to connect to the [signal@Gtk.DropTarget::drop] signal to receive
|
||||
the data when a DND operation occurs.
|
||||
|
||||
While a DND operation is ongoing, GTK provides updates when the pointer moves over
|
||||
the widget to which the drop target is associated. The [signal@Gtk.DropTarget::enter],
|
||||
[signal@Gtk.DropTarget::leave] and [signal@Gtk.DropTarget::motion] signals get emitted
|
||||
for this purpose.
|
||||
|
||||
GtkDropTarget provides a simple API, and only provides the data when it has been completely
|
||||
transferred. If you need to handle the data transfer yourself (for example to provide progress
|
||||
information during the transfer), you can use the more complicated [class@Gtk.DropTargetAsync].
|
||||
|
||||
## Other considerations
|
||||
|
||||
It is sometimes necessary to update the UI of the destination while a DND operation is ongoing,
|
||||
say to scroll or expand a view, or to switch pages. Typically, such UI changes are triggered
|
||||
by hovering over the widget in question.
|
||||
|
||||
[class@Gtk.DropControllerMotion] is an event controller that can help with implementing such
|
||||
behaviors. It is very similar to [class@Gtk.EventControllerMotion], but provides events during
|
||||
a DND operation.
|
||||
@@ -161,19 +161,19 @@ activate (GtkApplication *app,
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *button;
|
||||
GtkWidget *box;
|
||||
|
||||
window = gtk_application_window_new (app);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Window");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
button = gtk_button_new_with_label ("Hello World");
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), button);
|
||||
|
||||
gtk_widget_show (window);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,8 @@ display, unless specified otherwise.
|
||||
<para>
|
||||
<command>gtk4-launch</command> takes at least one argument, the name of
|
||||
the application to launch. The name should match application desktop file name,
|
||||
as residing in /usr/share/application, with or without the '.desktop' suffix.
|
||||
as residing in the applications subdirectories of the XDG data directories, with
|
||||
or without the '.desktop' suffix.
|
||||
</para>
|
||||
<para>
|
||||
If called with more than one argument, the rest of them besides the application
|
||||
@@ -71,4 +72,14 @@ application.
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1><title>Environment</title>
|
||||
<para>Some environment variables affect the behavior of <command>gtk4-launch</command>.</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>XDG_DATA_HOME</option>, <option>XDG_DATA_DIRS</option></term>
|
||||
<listitem><para>The environment variables specifying the XDG dta directories.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -14,7 +14,7 @@ search_index = true
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."Graphene-1.0"]
|
||||
name = "Graphene"
|
||||
@@ -57,6 +57,7 @@ content_files = [
|
||||
"initialization.md",
|
||||
"actions.md",
|
||||
"input-handling.md",
|
||||
"drag-and-drop.md",
|
||||
"drawing-model.md",
|
||||
"css-overview.md",
|
||||
"css-properties.md",
|
||||
|
||||
@@ -137,6 +137,14 @@ capture phase, and key bindings locally, during the target phase.
|
||||
Under the hood, all shortcuts are represented as instances of `GtkShortcut`,
|
||||
and they are managed by `GtkShortcutController`.
|
||||
|
||||
## Text input
|
||||
|
||||
When actual text input is needed (i.e. not just keyboard shortcuts),
|
||||
input method support can be added to a widget by connecting an input
|
||||
method context and listening to its `::commit` signal. To create a new
|
||||
input method context, use gtk_im_multicontext_new(), to provide it with
|
||||
input, use gtk_event_controller_key_set_im_context().
|
||||
|
||||
## Event controllers and gestures
|
||||
|
||||
Event controllers are standalone objects that can perform
|
||||
|
||||
@@ -27,9 +27,15 @@ expand_content_md_files = [
|
||||
'visual_index.md'
|
||||
]
|
||||
|
||||
gtk4_toml = configure_file(input: 'gtk4.toml.in', output: 'gtk4.toml', configuration: toml_conf)
|
||||
|
||||
if get_option('gtk_doc')
|
||||
gtk4_toml = configure_file(
|
||||
input: 'gtk4.toml.in',
|
||||
output: 'gtk4.toml',
|
||||
configuration: toml_conf,
|
||||
install: true,
|
||||
install_dir: docs_dir / 'gtk4',
|
||||
)
|
||||
|
||||
custom_target('gtk4-doc',
|
||||
input: [ gtk4_toml, gtk_gir[0] ],
|
||||
output: 'gtk4',
|
||||
|
||||
@@ -99,6 +99,12 @@ you should stop using `GdkVisual` APIs, since this object not longer
|
||||
exists in GTK 4. Most of its APIs are deprecated already and not
|
||||
useful when dealing with RGBA visuals.
|
||||
|
||||
### Stop using `gtk_widget_set_app_paintable`
|
||||
|
||||
This is gone in GTK4 with no direct replacement. But for some usecases there
|
||||
are alternatives. If you want to make the background transparent, you can set
|
||||
the background color to, for example, `rgba(255, 255, 255, 0)` using CSS instead.
|
||||
|
||||
### Stop using `GtkBox` padding, fill and expand child properties
|
||||
|
||||
GTK 4 removes these [class@Gtk.Box] child properties, so you should stop using
|
||||
@@ -133,7 +139,7 @@ or `gtk_style_context_get_color()` only accept the context's current
|
||||
state for their state argument. You should update all callers to pass
|
||||
the current state.
|
||||
|
||||
### Stop using `gdk_pixbuf_get_from_window()` and `gdk_cairo_set_source_surface()`
|
||||
### Stop using `gdk_pixbuf_get_from_window()` and `gdk_cairo_set_source_window()`
|
||||
|
||||
These functions are not supported in GTK 4. Instead, either use
|
||||
backend-specific APIs, or render your widgets using
|
||||
@@ -243,6 +249,10 @@ in GTK 3, you can prepare for the switch by using `gtk_widget_destroy()`
|
||||
only on toplevel windows, and replace all other uses with
|
||||
`gtk_container_remove()` or `g_object_unref()`.
|
||||
|
||||
### Stop using the GtkWidget.destroy vfunc
|
||||
|
||||
Instead of implementing GtkWidget.destroy, you can implement GObject.dispose.
|
||||
|
||||
### Reduce the use of generic container APIs
|
||||
|
||||
GTK 4 removes `gtk_container_add()` and `gtk_container_remove()`. While there
|
||||
@@ -1349,3 +1359,4 @@ of tree models, and widgets instead of cell renderers.
|
||||
|
||||
To learn more about the new list widgets, you can read the [List Widget
|
||||
Overview](#ListWidget).
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
// A map between namespaces and base URLs for their online documentation
|
||||
baseURLs = [
|
||||
[ 'Gdk', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://gnome.pages.gitlab.gnome.org/gtk/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://gnome.pages.gitlab.gnome.org/gtk/gsk4/' ],
|
||||
[ 'Gtk', 'https://gnome.pages.gitlab.gnome.org/gtk/gtk4/' ],
|
||||
[ 'Pango', 'https://gnome.pages/gitlab.gnome.org/pango/pango/' ],
|
||||
[ 'PangoCairo', 'https://gnome.pages.gitlab.gnome.org/pango/pangocairo/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk4/' ],
|
||||
[ 'GdkWayland', 'https://docs.gtk.org/gdk4-wayland/' ],
|
||||
[ 'GdkX11', 'https://docs.gtk.org/gdk4-x11/' ],
|
||||
[ 'Gsk', 'https://docs.gtk.org/gsk4/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk4/' ],
|
||||
[ 'Pango', 'https://docs.gtk.org/Pango/' ],
|
||||
[ 'PangoCairo', 'https://docs.gtk.org/PangoCairo/' ],
|
||||
]
|
||||
|
||||
@@ -14,14 +14,19 @@ instructions, binary downloads, etc, can be found
|
||||
The Win32 GDK backend can be influenced with some additional environment
|
||||
variables.
|
||||
|
||||
### GDK_IGNORE_WINTAB
|
||||
### GDK_WIN32_TABLET_INPUT_API
|
||||
|
||||
If this variable is set, GTK doesn't use the Wintab API for tablet support.
|
||||
If this variable is set, it determines the API that GTK uses for tablet support.
|
||||
The possible values are:
|
||||
|
||||
### GDK_USE_WINTAB
|
||||
`none`
|
||||
: Disables tablet support
|
||||
|
||||
If this variable is set, GTK uses the Wintab API for tablet support.
|
||||
This is the default.
|
||||
`wintab`
|
||||
: Use the Wintab API
|
||||
|
||||
`winpointer`
|
||||
: Use the Windows Pointer Input Stack API. This is the default.
|
||||
|
||||
## Windows-specific handling of cursors
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ gidocgen = find_program('gi-docgen', required: get_option('gtk_doc'))
|
||||
|
||||
docs_dir = gtk_datadir / 'doc'
|
||||
|
||||
if get_option('gtk_doc') and not build_gir
|
||||
error('API reference requires introspection.')
|
||||
endif
|
||||
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('gtk')
|
||||
|
||||
@@ -197,6 +197,17 @@ text_buffer_changed_cb (GtkTextBuffer *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_changed (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (gtk_window_is_fullscreen (GTK_WINDOW (object)))
|
||||
gtk_button_set_icon_name (GTK_BUTTON (user_data), "view-restore-symbolic");
|
||||
else
|
||||
gtk_button_set_icon_name (GTK_BUTTON (user_data), "view-fullscreen-symbolic");
|
||||
}
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "copy", window_copy, NULL, NULL, NULL },
|
||||
{ "paste", window_paste, NULL, NULL, NULL },
|
||||
@@ -214,7 +225,6 @@ new_window (GApplication *app,
|
||||
GtkWidget *window, *grid, *scrolled, *view;
|
||||
GtkWidget *toolbar;
|
||||
GtkWidget *button;
|
||||
GtkWidget *sw, *box, *label;
|
||||
|
||||
window = gtk_application_window_new (GTK_APPLICATION (app));
|
||||
gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
|
||||
@@ -226,6 +236,7 @@ new_window (GApplication *app,
|
||||
gtk_window_set_child (GTK_WINDOW (window), grid);
|
||||
|
||||
toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_widget_add_css_class (toolbar, "toolbar");
|
||||
button = gtk_toggle_button_new ();
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "format-justify-left");
|
||||
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::left");
|
||||
@@ -241,21 +252,18 @@ new_window (GApplication *app,
|
||||
gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::right");
|
||||
gtk_box_append (GTK_BOX (toolbar), button);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
gtk_widget_set_halign (box, GTK_ALIGN_END);
|
||||
label = gtk_label_new ("Fullscreen:");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
sw = gtk_switch_new ();
|
||||
gtk_widget_set_valign (sw, GTK_ALIGN_CENTER);
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (sw), "win.fullscreen");
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
gtk_box_append (GTK_BOX (toolbar), box);
|
||||
button = gtk_toggle_button_new ();
|
||||
gtk_button_set_icon_name (GTK_BUTTON (button), "view-fullscreen-symbolic");
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (button), "win.fullscreen");
|
||||
gtk_box_append (GTK_BOX (toolbar), button);
|
||||
g_signal_connect (window, "notify::fullscreened", G_CALLBACK (fullscreen_changed), button);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), toolbar, 0, 0, 1, 1);
|
||||
|
||||
scrolled = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_hexpand (scrolled, TRUE);
|
||||
gtk_widget_set_vexpand (scrolled, TRUE);
|
||||
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (scrolled), TRUE);
|
||||
view = gtk_text_view_new ();
|
||||
|
||||
g_object_set_data ((GObject*)window, "bloatpad-text", view);
|
||||
@@ -345,6 +353,7 @@ static void
|
||||
combo_changed (GtkComboBox *combo,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDialog *dialog = user_data;
|
||||
GtkEntry *entry = g_object_get_data (user_data, "entry");
|
||||
const char *action;
|
||||
char **accels;
|
||||
@@ -360,6 +369,17 @@ combo_changed (GtkComboBox *combo,
|
||||
g_strfreev (accels);
|
||||
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), str);
|
||||
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
entry_changed (GtkEntry *entry,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkDialog *dialog = user_data;
|
||||
|
||||
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -373,7 +393,7 @@ response (GtkDialog *dialog,
|
||||
const char *str;
|
||||
char **accels;
|
||||
|
||||
if (response_id == GTK_RESPONSE_CLOSE)
|
||||
if (response_id == GTK_RESPONSE_CANCEL)
|
||||
{
|
||||
gtk_window_destroy (GTK_WINDOW (dialog));
|
||||
return;
|
||||
@@ -389,6 +409,8 @@ response (GtkDialog *dialog,
|
||||
|
||||
gtk_application_set_accels_for_action (gtk_window_get_application (user_data), action, (const char **) accels);
|
||||
g_strfreev (accels);
|
||||
|
||||
gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_APPLY, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -403,22 +425,41 @@ edit_accels (GSimpleAction *action,
|
||||
GtkWidget *dialog;
|
||||
int i;
|
||||
|
||||
dialog = gtk_dialog_new ();
|
||||
dialog = gtk_dialog_new_with_buttons ("Accelerators",
|
||||
NULL,
|
||||
GTK_DIALOG_USE_HEADER_BAR,
|
||||
"Close", GTK_RESPONSE_CANCEL,
|
||||
"Set", GTK_RESPONSE_APPLY,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_application (GTK_WINDOW (dialog), app);
|
||||
actions = gtk_application_list_action_descriptions (app);
|
||||
|
||||
combo = gtk_combo_box_text_new ();
|
||||
g_object_set (gtk_dialog_get_content_area (GTK_DIALOG (dialog)),
|
||||
"margin-top", 10,
|
||||
"margin-bottom", 10,
|
||||
"margin-start", 10,
|
||||
"margin-end", 10,
|
||||
"spacing", 10,
|
||||
NULL);
|
||||
|
||||
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), combo);
|
||||
for (i = 0; actions[i]; i++)
|
||||
gtk_combo_box_text_append (GTK_COMBO_BOX_TEXT (combo), actions[i], actions[i]);
|
||||
g_signal_connect (combo, "changed", G_CALLBACK (combo_changed), dialog);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_widget_set_hexpand (entry, TRUE);
|
||||
g_signal_connect (entry, "notify::text", G_CALLBACK (entry_changed), dialog);
|
||||
|
||||
gtk_box_append (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), entry);
|
||||
gtk_dialog_add_button (GTK_DIALOG (dialog), "Close", GTK_RESPONSE_CLOSE);
|
||||
gtk_dialog_add_button (GTK_DIALOG (dialog), "Set", GTK_RESPONSE_APPLY);
|
||||
g_signal_connect (dialog, "response", G_CALLBACK (response), dialog);
|
||||
g_object_set_data (G_OBJECT (dialog), "combo", combo);
|
||||
g_object_set_data (G_OBJECT (dialog), "entry", entry);
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,10 @@
|
||||
<gresource prefix="/org/gtk/bloatpad">
|
||||
<file preprocess="xml-stripblanks">gtk/menus.ui</file>
|
||||
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
|
||||
<file>icons/16x16/actions/format-justify-center-symbolic.symbolic.png</file>
|
||||
<file>icons/16x16/actions/format-justify-left-symbolic.symbolic.png</file>
|
||||
<file>icons/16x16/actions/format-justify-right-symbolic.symbolic.png</file>
|
||||
<file>icons/16x16/actions/view-fullscreen-symbolic.symbolic.png</file>
|
||||
<file>icons/16x16/actions/view-restore-symbolic.symbolic.png</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
||||
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 115 B |
|
After Width: | Height: | Size: 117 B |
|
After Width: | Height: | Size: 207 B |
|
After Width: | Height: | Size: 204 B |
@@ -132,7 +132,6 @@ activate (GtkApplication *app,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *drawing_area;
|
||||
GtkGesture *drag;
|
||||
GtkGesture *press;
|
||||
@@ -142,14 +141,11 @@ activate (GtkApplication *app,
|
||||
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_window_set_child (GTK_WINDOW (window), frame);
|
||||
|
||||
drawing_area = gtk_drawing_area_new ();
|
||||
/* set a minimum size */
|
||||
gtk_widget_set_size_request (drawing_area, 100, 100);
|
||||
|
||||
gtk_frame_set_child (GTK_FRAME (frame), drawing_area);
|
||||
gtk_window_set_child (GTK_WINDOW (window), drawing_area);
|
||||
|
||||
gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (drawing_area), draw_cb, NULL, NULL);
|
||||
|
||||
|
||||
@@ -13,19 +13,19 @@ activate (GtkApplication *app,
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *button;
|
||||
GtkWidget *box;
|
||||
|
||||
window = gtk_application_window_new (app);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Window");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
button = gtk_button_new_with_label ("Hello World");
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
|
||||
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (print_hello), NULL);
|
||||
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_window_set_child (GTK_WINDOW (window), button);
|
||||
|
||||
gtk_widget_show (window);
|
||||
}
|
||||
|
||||
50
examples/labels.js
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env -S GI_TYPELIB_PATH=${PWD}/build/gtk:${GI_TYPELIB_PATH} LD_PRELOAD=${LD_PRELOAD}:${PWD}/build/gtk/libgtk-4.so gjs
|
||||
|
||||
imports.gi.versions['Gtk'] = '4.0';
|
||||
|
||||
const GObject = imports.gi.GObject;
|
||||
const Gtk = imports.gi.Gtk;
|
||||
|
||||
const DemoWidget = GObject.registerClass({
|
||||
GTypeName: 'DemoWidget',
|
||||
}, class DemoWidget extends Gtk.Widget {
|
||||
|
||||
_init(params = {}) {
|
||||
super._init(params);
|
||||
|
||||
let layout_manager = new Gtk.GridLayout ();
|
||||
this.set_layout_manager (layout_manager);
|
||||
this.label1 = new Gtk.Label({ label: "Red",
|
||||
hexpand: true,
|
||||
vexpand: true });
|
||||
this.label1.set_parent (this);
|
||||
let child1 = layout_manager.get_layout_child (this.label1);
|
||||
child1.set_row (0);
|
||||
child1.set_column (0);
|
||||
|
||||
this.label2 = new Gtk.Label({ label: "Green",
|
||||
hexpand: true,
|
||||
vexpand: true });
|
||||
this.label2.set_parent (this);
|
||||
let child2 = layout_manager.get_layout_child (this.label2);
|
||||
child2.set_row (0);
|
||||
child2.set_column (1);
|
||||
}
|
||||
});
|
||||
|
||||
// Create a new application
|
||||
let app = new Gtk.Application({ application_id: 'org.gtk.exampleapp' });
|
||||
|
||||
// When the application is launched…
|
||||
app.connect('activate', () => {
|
||||
// … create a new window …
|
||||
let win = new Gtk.ApplicationWindow({ application: app });
|
||||
// … with a button in it …
|
||||
let widget = new DemoWidget();
|
||||
win.set_child(widget);
|
||||
win.present();
|
||||
});
|
||||
|
||||
// Run the application
|
||||
app.run([]);
|
||||
|
||||
61
examples/squares.py
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env -S GI_TYPELIB_PATH=${PWD}/build/gtk:${GI_TYPELIB_PATH} LD_PRELOAD=${LD_PRELOAD}:${PWD}/build/gtk/libgtk-4.so python3
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('Gdk', '4.0')
|
||||
gi.require_version('Gtk', '4.0')
|
||||
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Graphene
|
||||
|
||||
|
||||
class DemoWidget(Gtk.Widget):
|
||||
|
||||
__gtype_name__ = "DemoWidget"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def do_measure(self, orientation, for_size: int):
|
||||
# We need some space to draw
|
||||
return 100, 200, -1, -1
|
||||
|
||||
def do_snapshot(self, snapshot):
|
||||
# Draw four color squares
|
||||
color = Gdk.RGBA()
|
||||
rect = Graphene.Rect.alloc()
|
||||
|
||||
width = self.get_width() / 2
|
||||
height = self.get_height() / 2
|
||||
|
||||
Gdk.RGBA.parse(color, "red")
|
||||
rect.init(0, 0, width, height)
|
||||
snapshot.append_color(color, rect)
|
||||
|
||||
Gdk.RGBA.parse(color, "green")
|
||||
rect.init(width, 0, width, height)
|
||||
snapshot.append_color(color, rect)
|
||||
|
||||
Gdk.RGBA.parse(color, "yellow")
|
||||
rect.init(0, height, width, height)
|
||||
snapshot.append_color(color, rect)
|
||||
|
||||
Gdk.RGBA.parse(color, "blue")
|
||||
rect.init(width, height, width, height)
|
||||
snapshot.append_color(color, rect)
|
||||
|
||||
def on_activate(app):
|
||||
# Create a new window
|
||||
win = Gtk.ApplicationWindow(application=app)
|
||||
win.set_title("Squares")
|
||||
icon = DemoWidget()
|
||||
win.set_child(icon)
|
||||
win.present()
|
||||
|
||||
# Create a new application
|
||||
app = Gtk.Application(application_id='org.gtk.exampleapp')
|
||||
app.connect('activate', on_activate)
|
||||
|
||||
# Run the application
|
||||
app.run(None)
|
||||
@@ -12,7 +12,7 @@ new_window (GApplication *app,
|
||||
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (window), TRUE);
|
||||
gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Sunny");
|
||||
gtk_window_set_icon_name (GTK_WINDOW (window), "sunny");
|
||||
gtk_window_set_icon_name (GTK_WINDOW (window), "weather-clear-symbolic");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
@@ -78,7 +78,7 @@ show_about (GSimpleAction *action,
|
||||
gtk_show_about_dialog (NULL,
|
||||
"program-name", "Sunny",
|
||||
"title", "About Sunny",
|
||||
"logo-icon-name", "sunny",
|
||||
"logo-icon-name", "weather-clear-symbolic",
|
||||
"comments", "A cheap Bloatpad clone.",
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ void gdk_broadway_display_show_keyboard (GdkBroadwayDis
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_broadway_display_hide_keyboard (GdkBroadwayDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
int gdk_broadway_display_get_surface_scale (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
void gdk_broadway_display_set_surface_scale (GdkDisplay *display,
|
||||
int scale);
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include <gdk/gdktextureprivate.h>
|
||||
#include "gdk-private.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
@@ -361,6 +362,29 @@ gdk_broadway_display_set_surface_scale (GdkDisplay *display,
|
||||
gdk_monitor_set_scale_factor (self->monitor, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_broadway_display_get_surface_scale:
|
||||
* @display: (type GdkBroadwayDisplay): the display
|
||||
*
|
||||
* Gets the surface scale that was previously set by the client or
|
||||
* gdk_broadway_display_set_surface_scale().
|
||||
*
|
||||
* Returns: the scale for surfaces
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
int
|
||||
gdk_broadway_display_get_surface_scale (GdkDisplay *display)
|
||||
{
|
||||
GdkBroadwayDisplay *self;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_BROADWAY_DISPLAY (display), 1);
|
||||
|
||||
self = GDK_BROADWAY_DISPLAY (display);
|
||||
|
||||
return self->scale_factor;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
gdk_broadway_display_get_monitors (GdkDisplay *display)
|
||||
{
|
||||
@@ -440,7 +464,7 @@ gdk_broadway_display_flush_in_idle (GdkDisplay *display)
|
||||
if (broadway_display->idle_flush_id == 0)
|
||||
{
|
||||
broadway_display->idle_flush_id = g_idle_add (flush_idle, g_object_ref (display));
|
||||
g_source_set_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
gdk_source_set_static_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,4 +57,11 @@ guint gdk_parse_debug_var (const char *variable,
|
||||
# define g_memdup2(mem,size) g_memdup((mem),(size))
|
||||
#endif
|
||||
|
||||
void gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name);
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 69, 1)
|
||||
#define g_source_set_static_name(source, name) g_source_set_name ((source), (name))
|
||||
#endif
|
||||
|
||||
#endif /* __GDK__PRIVATE_H__ */
|
||||
|
||||
18
gdk/gdk.c
@@ -127,10 +127,12 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "gl-legacy", GDK_DEBUG_GL_LEGACY, "Use a legacy OpenGL context" },
|
||||
{ "gl-gles", GDK_DEBUG_GL_GLES, "Use a GLES OpenGL context" },
|
||||
{ "gl-debug", GDK_DEBUG_GL_DEBUG, "Insert debugging information in OpenGL" },
|
||||
{ "gl-egl", GDK_DEBUG_GL_EGL, "Use EGL on X11 or Windows" },
|
||||
{ "gl-glx", GDK_DEBUG_GL_GLX, "Use GLX on X11" },
|
||||
{ "gl-wgl", GDK_DEBUG_GL_WGL, "Use WGL on Windows" },
|
||||
{ "vulkan-disable", GDK_DEBUG_VULKAN_DISABLE, "Disable Vulkan support" },
|
||||
{ "vulkan-validate", GDK_DEBUG_VULKAN_VALIDATE, "Load the Vulkan validation layer" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings" },
|
||||
{ "default-settings",GDK_DEBUG_DEFAULT_SETTINGS, "Force default values for xsettings", TRUE },
|
||||
};
|
||||
|
||||
|
||||
@@ -412,3 +414,17 @@ gdk_find_base_dir (const char *text,
|
||||
return dir;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_source_set_static_name_by_id (guint tag,
|
||||
const char *name)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
g_return_if_fail (tag > 0);
|
||||
|
||||
source = g_main_context_find_source_by_id (NULL, tag);
|
||||
if (source == NULL)
|
||||
return;
|
||||
|
||||
g_source_set_static_name (source, name);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ cairo_region_t *
|
||||
gdk_cairo_region_create_from_surface
|
||||
(cairo_surface_t *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_6_FOR(gdk_gl_texture_new)
|
||||
void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
GdkSurface *surface,
|
||||
int source,
|
||||
|
||||
@@ -635,7 +635,7 @@ gdk_clipboard_read_internal (GdkClipboard *clipboard,
|
||||
/**
|
||||
* gdk_clipboard_read_async:
|
||||
* @clipboard: a `GdkClipboard`
|
||||
* @mime_types: a %NULL-terminated array of mime types to choose from
|
||||
* @mime_types: (array zero-terminated=1): a %NULL-terminated array of mime types to choose from
|
||||
* @io_priority: the I/O priority of the request
|
||||
* @cancellable: (nullable): optional `GCancellable` object
|
||||
* @callback: (scope async): callback to call when the request is satisfied
|
||||
@@ -1253,9 +1253,15 @@ gdk_clipboard_set_content (GdkClipboard *clipboard,
|
||||
* @...: value contents conforming to @type
|
||||
*
|
||||
* Sets the clipboard to contain the value collected from the given varargs.
|
||||
*
|
||||
* Values should be passed the same way they are passed to other value
|
||||
* collecting APIs, such as [`method@GObject.Object.set`] or
|
||||
* [`id@g_signal_emit`].
|
||||
*
|
||||
* ```c
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_TEXT_BUFFER, buffer);
|
||||
* gdk_clipboard_set (clipboard, GTK_TYPE_STRING, "Hello World");
|
||||
*
|
||||
* gdk_clipboard_set (clipboard, GDK_TYPE_TEXTURE, some_texture);
|
||||
* ```
|
||||
*/
|
||||
void
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkrgbaprivate.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
@@ -553,6 +555,8 @@ gdk_content_deserialize_async (GInputStream *stream,
|
||||
Deserializer *deserializer;
|
||||
|
||||
g_return_if_fail (G_IS_INPUT_STREAM (stream));
|
||||
g_return_if_fail (mime_type != NULL);
|
||||
g_return_if_fail (G_TYPE_IS_VALUE_TYPE (type));
|
||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
@@ -591,7 +595,10 @@ gdk_content_deserialize_finish (GAsyncResult *result,
|
||||
g_return_val_if_fail (GDK_IS_CONTENT_DESERIALIZER (result), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
deserializer = GDK_CONTENT_DESERIALIZER (result);
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
if (G_VALUE_TYPE (value) == 0)
|
||||
g_value_init (value, G_VALUE_TYPE (&deserializer->value));
|
||||
else
|
||||
g_return_val_if_fail (G_VALUE_HOLDS (value, G_VALUE_TYPE (&deserializer->value)), FALSE);
|
||||
|
||||
if (deserializer->error)
|
||||
{
|
||||
@@ -650,6 +657,88 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
|
||||
deserializer);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer data)
|
||||
{
|
||||
GdkContentDeserializer *deserializer = GDK_CONTENT_DESERIALIZER (source);
|
||||
GdkTexture *texture;
|
||||
GValue *value;
|
||||
GError *error = NULL;
|
||||
|
||||
texture = g_task_propagate_pointer (G_TASK (res), &error);
|
||||
if (texture == NULL)
|
||||
{
|
||||
gdk_content_deserializer_return_error (deserializer, error);
|
||||
return;
|
||||
}
|
||||
|
||||
value = gdk_content_deserializer_get_value (deserializer);
|
||||
g_value_take_object (value, texture);
|
||||
gdk_content_deserializer_return_success (deserializer);
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
read_all_data (GInputStream *source,
|
||||
GError **error)
|
||||
{
|
||||
GOutputStream *output;
|
||||
gssize size;
|
||||
GBytes *bytes;
|
||||
|
||||
output = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
|
||||
size = g_output_stream_splice (output, source, 0, NULL, error);
|
||||
if (size == -1)
|
||||
{
|
||||
g_object_unref (output);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_output_stream_close (output, NULL, NULL);
|
||||
bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output));
|
||||
g_object_unref (output);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
deserialize_texture_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GdkContentDeserializer *deserializer = source_object;
|
||||
GBytes *bytes;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture = NULL;
|
||||
|
||||
bytes = read_all_data (gdk_content_deserializer_get_input_stream (deserializer), &error);
|
||||
if (bytes)
|
||||
{
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
if (texture)
|
||||
g_task_return_pointer (task, texture, g_object_unref);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_deserializer (GdkContentDeserializer *deserializer)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (deserializer,
|
||||
gdk_content_deserializer_get_cancellable (deserializer),
|
||||
texture_deserializer_finish,
|
||||
NULL);
|
||||
g_task_run_in_thread (task, deserialize_texture_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
string_deserializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -858,48 +947,65 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_deserializer ("image/png",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
gdk_content_register_deserializer ("image/tiff",
|
||||
GDK_TYPE_TEXTURE,
|
||||
texture_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
{
|
||||
/* Turning pngs and tiffs into textures is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "tiff"))
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_TEXTURE,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
gdk_content_register_deserializer (*m,
|
||||
GDK_TYPE_PIXBUF,
|
||||
pixbuf_deserializer,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
@@ -179,6 +179,76 @@ gdk_content_formats_new_for_gtype (GType type)
|
||||
return gdk_content_formats_new_take (data, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_parse:
|
||||
* @string: the string to parse
|
||||
*
|
||||
* Parses the given @string into `GdkContentFormats` and
|
||||
* returns the formats.
|
||||
*
|
||||
* Strings printed via [method@Gdk.ContentFormats.to_string]
|
||||
* can be read in again successfully using this function.
|
||||
*
|
||||
* If @string does not describe valid content formats, %NULL
|
||||
* is returned.
|
||||
*
|
||||
* Returns: (nullable): the content formats if @string is valid
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
GdkContentFormats *
|
||||
gdk_content_formats_parse (const char *string)
|
||||
{
|
||||
GdkContentFormatsBuilder *builder;
|
||||
char **split;
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (string != NULL, NULL);
|
||||
|
||||
split = g_strsplit_set (string, "\t\n\f\r ", -1); /* same as g_ascii_isspace() */
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
|
||||
/* first the GTypes */
|
||||
for (i = 0; split[i] != NULL; i++)
|
||||
{
|
||||
GType type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
type = g_type_from_name (split[i]);
|
||||
if (type != 0)
|
||||
gdk_content_formats_builder_add_gtype (builder, type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* then the mime types */
|
||||
for (; split[i] != NULL; i++)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
if (split[i][0] == 0)
|
||||
continue;
|
||||
|
||||
mime_type = gdk_intern_mime_type (split[i]);
|
||||
if (mime_type)
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (split[i] != NULL)
|
||||
{
|
||||
g_strfreev (split);
|
||||
gdk_content_formats_builder_unref (builder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_strfreev (split);
|
||||
return gdk_content_formats_builder_free_to_formats (builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_content_formats_ref:
|
||||
* @formats: a `GdkContentFormats`
|
||||
@@ -227,10 +297,8 @@ gdk_content_formats_unref (GdkContentFormats *formats)
|
||||
*
|
||||
* Prints the given @formats into a string for human consumption.
|
||||
*
|
||||
* This is meant for debugging and logging.
|
||||
*
|
||||
* The form of the representation may change at any time and is
|
||||
* not guaranteed to stay identical.
|
||||
* The result of this function can later be parsed with
|
||||
* [func@Gdk.ContentFormats.parse].
|
||||
*/
|
||||
void
|
||||
gdk_content_formats_print (GdkContentFormats *formats,
|
||||
@@ -241,20 +309,18 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
g_return_if_fail (formats != NULL);
|
||||
g_return_if_fail (string != NULL);
|
||||
|
||||
g_string_append (string, "{ ");
|
||||
for (i = 0; i < formats->n_gtypes; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, g_type_name (formats->gtypes[i]));
|
||||
}
|
||||
for (i = 0; i < formats->n_mime_types; i++)
|
||||
{
|
||||
if (i > 0 || formats->n_gtypes > 0)
|
||||
g_string_append (string, ", ");
|
||||
g_string_append (string, " ");
|
||||
g_string_append (string, formats->mime_types[i]);
|
||||
}
|
||||
g_string_append (string, " }");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,6 +329,8 @@ gdk_content_formats_print (GdkContentFormats *formats,
|
||||
*
|
||||
* Prints the given @formats into a human-readable string.
|
||||
*
|
||||
* The resulting string can be parsed with [func@Gdk.ContentFormats.parse].
|
||||
*
|
||||
* This is a small wrapper around [method@Gdk.ContentFormats.print]
|
||||
* to help when debugging.
|
||||
*
|
||||
|
||||
@@ -40,6 +40,8 @@ GdkContentFormats * gdk_content_formats_new (const char
|
||||
guint n_mime_types);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_new_for_gtype (GType type);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
GdkContentFormats * gdk_content_formats_parse (const char *string);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkContentFormats * gdk_content_formats_ref (GdkContentFormats *formats);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
||||
@@ -80,7 +80,7 @@ gdk_content_provider_value_get_value (GdkContentProvider *provider,
|
||||
{
|
||||
GdkContentProviderValue *content = GDK_CONTENT_PROVIDER_VALUE (provider);
|
||||
|
||||
if (G_VALUE_HOLDS (value, G_VALUE_TYPE (&content->value)))
|
||||
if (G_VALUE_HOLDS (&content->value, G_VALUE_TYPE (value)))
|
||||
{
|
||||
g_value_copy (&content->value, value);
|
||||
return TRUE;
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#include "filetransferportalprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gdkrgba.h"
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <string.h>
|
||||
@@ -606,6 +609,7 @@ gdk_content_serialize_finish (GAsyncResult *result,
|
||||
|
||||
/*** SERIALIZERS ***/
|
||||
|
||||
|
||||
static void
|
||||
pixbuf_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
@@ -658,6 +662,82 @@ pixbuf_serializer (GdkContentSerializer *serializer)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer_finish (GObject *source,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkContentSerializer *serializer = GDK_CONTENT_SERIALIZER (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_task_propagate_boolean (G_TASK (res), &error))
|
||||
gdk_content_serializer_return_error (serializer, error);
|
||||
else
|
||||
gdk_content_serializer_return_success (serializer);
|
||||
}
|
||||
|
||||
static void
|
||||
serialize_texture_in_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GdkContentSerializer *serializer = source_object;
|
||||
const GValue *value;
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes = NULL;
|
||||
GError *error = NULL;
|
||||
gboolean result = FALSE;
|
||||
|
||||
value = gdk_content_serializer_get_value (serializer);
|
||||
texture = g_value_get_object (value);
|
||||
|
||||
if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/png") == 0)
|
||||
bytes = gdk_save_png (texture);
|
||||
else if (strcmp (gdk_content_serializer_get_mime_type (serializer), "image/tiff") == 0)
|
||||
bytes = gdk_save_tiff (texture);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
GInputStream *input = g_memory_input_stream_new_from_bytes (bytes);
|
||||
gssize spliced;
|
||||
|
||||
spliced = g_output_stream_splice (gdk_content_serializer_get_output_stream (serializer),
|
||||
input,
|
||||
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
&error);
|
||||
g_object_unref (input);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
result = spliced != -1;
|
||||
}
|
||||
else
|
||||
g_set_error_literal (&error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Saving png failed");
|
||||
|
||||
if (result)
|
||||
g_task_return_boolean (task, result);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_serializer (GdkContentSerializer *serializer)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (serializer,
|
||||
gdk_content_serializer_get_cancellable (serializer),
|
||||
texture_serializer_finish,
|
||||
NULL);
|
||||
g_task_run_in_thread (task, serialize_texture_in_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
string_serializer_finish (GObject *source,
|
||||
GAsyncResult *result,
|
||||
@@ -877,51 +957,66 @@ init (void)
|
||||
|
||||
initialized = TRUE;
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/png",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
"image/tiff",
|
||||
texture_serializer,
|
||||
NULL, NULL);
|
||||
|
||||
formats = gdk_pixbuf_get_formats ();
|
||||
|
||||
/* Make sure png comes first */
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char *name;
|
||||
|
||||
char *name;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
if (g_str_equal (name, "png"))
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
{
|
||||
formats = g_slist_delete_link (formats, f);
|
||||
formats = g_slist_prepend (formats, fmt);
|
||||
|
||||
g_free (name);
|
||||
|
||||
break;
|
||||
}
|
||||
g_free (name);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
}
|
||||
|
||||
for (f = formats; f; f = f->next)
|
||||
{
|
||||
GdkPixbufFormat *fmt = f->data;
|
||||
char **mimes, **m;
|
||||
char *name;
|
||||
|
||||
if (!gdk_pixbuf_format_is_writable (fmt))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
name = gdk_pixbuf_format_get_name (fmt);
|
||||
mimes = gdk_pixbuf_format_get_mime_types (fmt);
|
||||
for (m = mimes; *m; m++)
|
||||
{
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
{
|
||||
/* Turning textures into pngs or tiffs is handled above */
|
||||
if (!g_str_equal (name, "png") &&
|
||||
!g_str_equal (name, "tiff"))
|
||||
gdk_content_register_serializer (GDK_TYPE_TEXTURE,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
gdk_content_register_serializer (GDK_TYPE_PIXBUF,
|
||||
*m,
|
||||
pixbuf_serializer,
|
||||
gdk_pixbuf_format_get_name (fmt),
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
g_strfreev (mimes);
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
@@ -41,10 +41,12 @@ typedef enum {
|
||||
GDK_DEBUG_GL_LEGACY = 1 << 15,
|
||||
GDK_DEBUG_GL_GLES = 1 << 16,
|
||||
GDK_DEBUG_GL_DEBUG = 1 << 17,
|
||||
GDK_DEBUG_GL_GLX = 1 << 18,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 19,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 20,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 21
|
||||
GDK_DEBUG_GL_EGL = 1 << 18,
|
||||
GDK_DEBUG_GL_GLX = 1 << 19,
|
||||
GDK_DEBUG_GL_WGL = 1 << 20,
|
||||
GDK_DEBUG_VULKAN_DISABLE = 1 << 21,
|
||||
GDK_DEBUG_VULKAN_VALIDATE = 1 << 22,
|
||||
GDK_DEBUG_DEFAULT_SETTINGS= 1 << 23,
|
||||
} GdkDebugFlags;
|
||||
|
||||
extern guint _gdk_debug_flags;
|
||||
|
||||
216
gdk/gdkdisplay.c
@@ -77,6 +77,23 @@ enum {
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef struct _GdkDisplayPrivate GdkDisplayPrivate;
|
||||
|
||||
struct _GdkDisplayPrivate {
|
||||
/* The base context that all other contexts inherit from.
|
||||
* This context is never exposed to public API and is
|
||||
* allowed to have a %NULL surface.
|
||||
*/
|
||||
GdkGLContext *gl_context;
|
||||
GError *gl_error;
|
||||
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
};
|
||||
|
||||
static void gdk_display_dispose (GObject *object);
|
||||
static void gdk_display_finalize (GObject *object);
|
||||
|
||||
@@ -85,7 +102,7 @@ static GdkAppLaunchContext *gdk_display_real_get_app_launch_context (GdkDisplay
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkDisplay, gdk_display, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_display_get_property (GObject *object,
|
||||
@@ -119,10 +136,14 @@ gdk_display_real_make_default (GdkDisplay *display)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
static GdkGLContext *
|
||||
gdk_display_default_init_gl (GdkDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GdkSeat *
|
||||
@@ -134,6 +155,12 @@ gdk_display_real_get_default_seat (GdkDisplay *display)
|
||||
return display->seats->data;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_real_opened (GdkDisplay *display)
|
||||
{
|
||||
_gdk_display_manager_add_display (gdk_display_manager_get (), display);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_class_init (GdkDisplayClass *class)
|
||||
{
|
||||
@@ -143,10 +170,11 @@ gdk_display_class_init (GdkDisplayClass *class)
|
||||
object_class->dispose = gdk_display_dispose;
|
||||
object_class->get_property = gdk_display_get_property;
|
||||
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->opened = gdk_display_real_opened;
|
||||
class->make_default = gdk_display_real_make_default;
|
||||
class->get_app_launch_context = gdk_display_real_get_app_launch_context;
|
||||
class->init_gl = gdk_display_default_init_gl;
|
||||
class->get_default_seat = gdk_display_real_get_default_seat;
|
||||
class->opened = gdk_display_real_opened;
|
||||
|
||||
/**
|
||||
* GdkDisplay:composited: (attributes org.gtk.Property.get=gdk_display_is_composited)
|
||||
@@ -294,6 +322,8 @@ free_device_grabs_foreach (gpointer key,
|
||||
static void
|
||||
gdk_display_init (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
display->double_click_time = 250;
|
||||
display->double_click_distance = 5;
|
||||
|
||||
@@ -304,22 +334,26 @@ gdk_display_init (GdkDisplay *display)
|
||||
|
||||
g_queue_init (&display->queued_events);
|
||||
|
||||
display->debug_flags = _gdk_debug_flags;
|
||||
priv->debug_flags = _gdk_debug_flags;
|
||||
|
||||
display->composited = TRUE;
|
||||
display->rgba = TRUE;
|
||||
display->input_shapes = TRUE;
|
||||
priv->composited = TRUE;
|
||||
priv->rgba = TRUE;
|
||||
priv->input_shapes = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_dispose (GObject *object)
|
||||
{
|
||||
GdkDisplay *display = GDK_DISPLAY (object);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
_gdk_display_manager_remove_display (gdk_display_manager_get (), display);
|
||||
|
||||
g_queue_clear (&display->queued_events);
|
||||
|
||||
g_clear_object (&priv->gl_context);
|
||||
g_clear_error (&priv->gl_error);
|
||||
|
||||
G_OBJECT_CLASS (gdk_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -998,21 +1032,25 @@ gdk_display_get_primary_clipboard (GdkDisplay *display)
|
||||
gboolean
|
||||
gdk_display_supports_input_shapes (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->input_shapes;
|
||||
return priv->input_shapes;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_input_shapes (GdkDisplay *display,
|
||||
gboolean input_shapes)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->input_shapes == input_shapes)
|
||||
if (priv->input_shapes == input_shapes)
|
||||
return;
|
||||
|
||||
display->input_shapes = input_shapes;
|
||||
priv->input_shapes = input_shapes;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_INPUT_SHAPES]);
|
||||
}
|
||||
@@ -1157,32 +1195,136 @@ gdk_display_get_keymap (GdkDisplay *display)
|
||||
return GDK_DISPLAY_GET_CLASS (display)->get_keymap (display);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_make_gl_context_current:
|
||||
* @display: a `GdkDisplay`
|
||||
* @context: (optional): a `GdkGLContext`
|
||||
*
|
||||
* Makes the given @context the current GL context, or unsets
|
||||
* the current GL context if @context is %NULL.
|
||||
*/
|
||||
gboolean
|
||||
gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context)
|
||||
static void
|
||||
gdk_display_init_gl (GdkDisplay *self)
|
||||
{
|
||||
return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
GdkGLContext *context;
|
||||
gint64 before G_GNUC_UNUSED;
|
||||
gint64 before2 G_GNUC_UNUSED;
|
||||
|
||||
before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (self, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (&priv->gl_error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return;
|
||||
}
|
||||
|
||||
context = GDK_DISPLAY_GET_CLASS (self)->init_gl (self, &priv->gl_error);
|
||||
if (context == NULL)
|
||||
return;
|
||||
|
||||
before2 = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (!gdk_gl_context_realize (context, &priv->gl_error))
|
||||
{
|
||||
g_object_unref (context);
|
||||
return;
|
||||
}
|
||||
|
||||
gdk_profiler_end_mark (before2, "realize OpenGL context", NULL);
|
||||
|
||||
/* Only assign after realize, so GdkGLContext::realize() can use
|
||||
* gdk_display_get_gl_context() == NULL to differentiate between
|
||||
* the display's context and any other context.
|
||||
*/
|
||||
priv->gl_context = context;
|
||||
|
||||
gdk_profiler_end_mark (before, "initialize OpenGL", NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_prepare_gl:
|
||||
* @self: a `GdkDisplay`
|
||||
* @error: return location for a `GError`
|
||||
*
|
||||
* Checks that OpenGL is available for @self and ensures that it is
|
||||
* properly initialized.
|
||||
* When this fails, an @error will be set describing the error and this
|
||||
* function returns %FALSE.
|
||||
*
|
||||
* Note that even if this function succeeds, creating a `GdkGLContext`
|
||||
* may still fail.
|
||||
*
|
||||
* This function is idempotent. Calling it multiple times will just
|
||||
* return the same value or error.
|
||||
*
|
||||
* You never need to call this function, GDK will call it automatically
|
||||
* as needed. But you can use it as a check when setting up code that
|
||||
* might make use of OpenGL.
|
||||
*
|
||||
* Returns: %TRUE if the display supports OpenGL
|
||||
*
|
||||
* Since: 4.4
|
||||
**/
|
||||
gboolean
|
||||
gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (priv->gl_context)
|
||||
return TRUE;
|
||||
|
||||
if (priv->gl_error != NULL)
|
||||
{
|
||||
if (error)
|
||||
*error = g_error_copy (priv->gl_error);
|
||||
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_display_init_gl (self);
|
||||
|
||||
/* try again */
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_display_get_gl_context:
|
||||
* @self: the `GdkDisplay`
|
||||
*
|
||||
* Gets the GL context returned from [vfunc@Gdk.Display.init_gl]
|
||||
* previously.
|
||||
*
|
||||
* If that function has not been called yet or did fail, %NULL is
|
||||
* returned.
|
||||
* Call [method@Gdk.Display.prepare_gl] to avoid this.
|
||||
*
|
||||
* Returns: The `GdkGLContext`
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_display_get_gl_context (GdkDisplay *self)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
return priv->gl_context;
|
||||
}
|
||||
|
||||
GdkDebugFlags
|
||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||
{
|
||||
return display ? display->debug_flags : _gdk_debug_flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
GdkDebugFlags flags)
|
||||
{
|
||||
display->debug_flags = flags;
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
priv->debug_flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1207,21 +1349,25 @@ gdk_display_set_debug_flags (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_composited (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->composited;
|
||||
return priv->composited;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean composited)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->composited == composited)
|
||||
if (priv->composited == composited)
|
||||
return;
|
||||
|
||||
display->composited = composited;
|
||||
priv->composited = composited;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_COMPOSITED]);
|
||||
}
|
||||
@@ -1248,21 +1394,25 @@ gdk_display_set_composited (GdkDisplay *display,
|
||||
gboolean
|
||||
gdk_display_is_rgba (GdkDisplay *display)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
|
||||
|
||||
return display->rgba;
|
||||
return priv->rgba;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba)
|
||||
{
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
g_return_if_fail (GDK_IS_DISPLAY (display));
|
||||
|
||||
if (display->rgba == rgba)
|
||||
if (priv->rgba == rgba)
|
||||
return;
|
||||
|
||||
display->rgba = rgba;
|
||||
priv->rgba = rgba;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (display), props[PROP_RGBA]);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,10 @@ gboolean gdk_display_is_rgba (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_display_supports_input_shapes (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_display_prepare_gl (GdkDisplay *self,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay *gdk_display_get_default (void);
|
||||
|
||||
|
||||
@@ -102,11 +102,6 @@ struct _GdkDisplay
|
||||
|
||||
guint vulkan_refcount;
|
||||
#endif /* GDK_RENDERING_VULKAN */
|
||||
guint rgba : 1;
|
||||
guint composited : 1;
|
||||
guint input_shapes : 1;
|
||||
|
||||
GdkDebugFlags debug_flags;
|
||||
|
||||
GList *seats;
|
||||
};
|
||||
@@ -145,8 +140,8 @@ struct _GdkDisplayClass
|
||||
|
||||
GdkKeymap * (*get_keymap) (GdkDisplay *display);
|
||||
|
||||
gboolean (*make_gl_context_current) (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * (*init_gl) (GdkDisplay *display,
|
||||
GError **error);
|
||||
|
||||
GdkSeat * (*get_default_seat) (GdkDisplay *display);
|
||||
|
||||
@@ -211,8 +206,7 @@ GdkSurface * gdk_display_create_surface (GdkDisplay *display
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean gdk_display_make_gl_context_current (GdkDisplay *display,
|
||||
GdkGLContext *context);
|
||||
GdkGLContext * gdk_display_get_gl_context (GdkDisplay *display);
|
||||
|
||||
void gdk_display_set_rgba (GdkDisplay *display,
|
||||
gboolean rgba);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
typedef struct _GdkDrawContextPrivate GdkDrawContextPrivate;
|
||||
|
||||
struct _GdkDrawContextPrivate {
|
||||
GdkDisplay *display;
|
||||
GdkSurface *surface;
|
||||
|
||||
cairo_region_t *frame_region;
|
||||
@@ -77,6 +78,7 @@ gdk_draw_context_dispose (GObject *gobject)
|
||||
priv->surface->draw_contexts = g_slist_remove (priv->surface->draw_contexts, context);
|
||||
g_clear_object (&priv->surface);
|
||||
}
|
||||
g_clear_object (&priv->display);
|
||||
|
||||
G_OBJECT_CLASS (gdk_draw_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
@@ -92,10 +94,31 @@ gdk_draw_context_set_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
if (priv->display != NULL)
|
||||
{
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_value_dup_object (value);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SURFACE:
|
||||
priv->surface = g_value_dup_object (value);
|
||||
g_assert (priv->surface != NULL);
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->surface)
|
||||
{
|
||||
priv->surface->draw_contexts = g_slist_prepend (priv->surface->draw_contexts, context);
|
||||
if (priv->display)
|
||||
{
|
||||
g_assert (priv->display == gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->display = g_object_ref (gdk_surface_get_display (priv->surface));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -148,7 +171,8 @@ gdk_draw_context_class_init (GdkDrawContextClass *klass)
|
||||
P_("Display"),
|
||||
P_("The GDK display used to create the context"),
|
||||
GDK_TYPE_DISPLAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
@@ -228,7 +252,7 @@ gdk_draw_context_get_display (GdkDrawContext *context)
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DRAW_CONTEXT (context), NULL);
|
||||
|
||||
return priv->surface ? gdk_surface_get_display (priv->surface) : NULL;
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -294,8 +294,11 @@ gdk_drop_finalize (GObject *object)
|
||||
|
||||
/* someone forgot to send a LEAVE signal */
|
||||
g_warn_if_fail (!priv->entered);
|
||||
|
||||
/* Should we emit finish() here if necessary?
|
||||
* For now that's the backends' job */
|
||||
* For now that's the backends' job
|
||||
*/
|
||||
g_warn_if_fail (priv->state != GDK_DROP_STATE_DROPPING);
|
||||
|
||||
g_clear_object (&priv->device);
|
||||
g_clear_object (&priv->drag);
|
||||
@@ -571,7 +574,7 @@ gdk_drop_get_drag (GdkDrop *self)
|
||||
* the ones provided by [method@Gdk.Drop.get_actions]. Those actions may
|
||||
* change in the future, even depending on the actions you provide here.
|
||||
*
|
||||
* The @preferred action is a hint to the drag'n'drop mechanism about which
|
||||
* The @preferred action is a hint to the drag-and-drop mechanism about which
|
||||
* action to use when multiple actions are possible.
|
||||
*
|
||||
* This function should be called by drag destinations in response to
|
||||
@@ -862,7 +865,7 @@ gdk_drop_read_value_internal (GdkDrop *self,
|
||||
* then call [method@Gdk.Drop.read_value_finish] to get the resulting
|
||||
* `GValue`.
|
||||
*
|
||||
* For local drag'n'drop operations that are available in the given
|
||||
* For local drag-and-drop operations that are available in the given
|
||||
* `GType`, the value will be copied directly. Otherwise, GDK will
|
||||
* try to use [func@Gdk.content_deserialize_async] to convert the data.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "gdkinternals.h"
|
||||
#include "gdkframeclockprivate.h"
|
||||
#include "gdk.h"
|
||||
#include "gdk-private.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
@@ -307,12 +308,15 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
|
||||
if (priv->flush_idle_id == 0 && RUN_FLUSH_IDLE (priv))
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
priv->flush_idle_id = g_timeout_add_full (GDK_PRIORITY_EVENTS + 1,
|
||||
min_interval,
|
||||
gdk_frame_clock_flush_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_source_set_name_by_id (priv->flush_idle_id, "[gtk] gdk_frame_clock_flush_idle");
|
||||
source = g_main_context_find_source_by_id (NULL, priv->flush_idle_id);
|
||||
g_source_set_static_name (source, "[gtk] gdk_frame_clock_flush_idle");
|
||||
}
|
||||
|
||||
if (!priv->in_paint_idle &&
|
||||
@@ -324,7 +328,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle,
|
||||
gdk_frame_clock_paint_idle,
|
||||
g_object_ref (clock_idle),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_source_set_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
gdk_source_set_static_name_by_id (priv->paint_idle_id, "[gtk] gdk_frame_clock_paint_idle");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* @width: The width of the region to draw
|
||||
* @height: The height of the region to draw
|
||||
*
|
||||
* The main way to draw GL content in GTK.
|
||||
* The main way to not draw GL content in GTK.
|
||||
*
|
||||
* It takes a render buffer ID (@source_type == GL_RENDERBUFFER) or a texture
|
||||
* id (@source_type == GL_TEXTURE) and draws it onto @cr with an OVER operation,
|
||||
@@ -319,6 +319,12 @@ gdk_gl_texture_quads (GdkGLContext *paint_context,
|
||||
* with alpha components, so make sure you use GL_TEXTURE if using alpha.
|
||||
*
|
||||
* Calling this may change the current GL context.
|
||||
*
|
||||
* Deprecated: 4.6: The function is overly complex and produces broken output
|
||||
* in various combinations of arguments. If you want to draw with GL textures
|
||||
* in GTK, use [ctor@Gdk.GLTexture.new]; if you want to use that texture in
|
||||
* Cairo, use [method@Gdk.Texture.download] to download the data into a Cairo
|
||||
* image surface.
|
||||
*/
|
||||
void
|
||||
gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
|
||||
@@ -89,8 +89,6 @@
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
typedef struct {
|
||||
GdkGLContext *shared_context;
|
||||
|
||||
int major;
|
||||
int minor;
|
||||
int gl_version;
|
||||
@@ -127,7 +125,28 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, GDK_TYPE_DRAW_CONTEXT)
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
|
||||
typedef struct _MaskedContext MaskedContext;
|
||||
|
||||
static inline MaskedContext *
|
||||
mask_context (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
{
|
||||
return (MaskedContext *) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (context) | (surfaceless ? 1 : 0));
|
||||
}
|
||||
|
||||
static inline GdkGLContext *
|
||||
unmask_context (MaskedContext *mask)
|
||||
{
|
||||
return GDK_GL_CONTEXT (GSIZE_TO_POINTER (GPOINTER_TO_SIZE (mask) & ~(gsize) 1));
|
||||
}
|
||||
|
||||
static void
|
||||
unref_unmasked (gpointer data)
|
||||
{
|
||||
g_object_unref (unmask_context (data));
|
||||
}
|
||||
|
||||
static GPrivate thread_current_context = G_PRIVATE_INIT (unref_unmasked);
|
||||
|
||||
static void
|
||||
gdk_gl_context_clear_old_updated_area (GdkGLContext *context)
|
||||
@@ -144,17 +163,14 @@ static void
|
||||
gdk_gl_context_dispose (GObject *gobject)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (gobject);
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
gdk_gl_context_clear_old_updated_area (context);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (unmask_context (current) == context)
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
|
||||
g_clear_object (&priv->shared_context);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -174,17 +190,10 @@ gdk_gl_context_set_property (GObject *gobject,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
{
|
||||
GdkGLContext *context = g_value_get_object (value);
|
||||
|
||||
if (context != NULL)
|
||||
priv->shared_context = g_object_ref (context);
|
||||
}
|
||||
g_assert (g_value_get_object (value) == NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -198,12 +207,10 @@ gdk_gl_context_get_property (GObject *gobject,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private ((GdkGLContext *) gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SHARED_CONTEXT:
|
||||
g_value_set_object (value, priv->shared_context);
|
||||
g_value_set_object (value, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -222,64 +229,83 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
guchar *copy = NULL;
|
||||
guint gl_format;
|
||||
guint gl_type;
|
||||
guint bpp;
|
||||
GLint gl_internalformat;
|
||||
GLint gl_format;
|
||||
GLint gl_type;
|
||||
gsize bpp;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
if (priv->use_es)
|
||||
if (!priv->use_es && data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
/* GLES only supports rgba, so convert if necessary */
|
||||
if (data_format != GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
}
|
||||
|
||||
bpp = 4;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (priv->use_es && data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB16F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA16F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32_FLOAT)
|
||||
{
|
||||
gl_internalformat = GL_RGB32F;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED)
|
||||
{
|
||||
gl_internalformat = GL_RGBA32F;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
}
|
||||
else /* Fall-back, convert to GLES format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
data_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
stride = width * 4;
|
||||
data = copy;
|
||||
gl_internalformat = GL_RGBA8;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data_format == GDK_MEMORY_DEFAULT) /* Cairo surface format */
|
||||
{
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
bpp = 4;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_R8G8B8) /* Pixmap non-alpha data */
|
||||
{
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else if (data_format == GDK_MEMORY_B8G8R8)
|
||||
{
|
||||
gl_format = GL_BGR;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
bpp = 3;
|
||||
}
|
||||
else /* Fall-back, convert to cairo-surface-format */
|
||||
{
|
||||
copy = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (copy, width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
data, stride, data_format,
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
bpp = 4;
|
||||
data = copy;
|
||||
gl_format = GL_BGRA;
|
||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
|
||||
/* GL_UNPACK_ROW_LENGTH is available on desktop GL, OpenGL ES >= 3.0, or if
|
||||
* the GL_EXT_unpack_subimage extension for OpenGL ES 2.0 is available
|
||||
@@ -288,7 +314,7 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
else if ((!priv->use_es ||
|
||||
@@ -296,14 +322,14 @@ gdk_gl_context_upload_texture (GdkGLContext *context,
|
||||
{
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, stride / bpp);
|
||||
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, data);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, data);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
glTexImage2D (texture_target, 0, GL_RGBA, width, height, 0, gl_format, gl_type, NULL);
|
||||
glTexImage2D (texture_target, 0, gl_internalformat, width, height, 0, gl_format, gl_type, NULL);
|
||||
for (i = 0; i < height; i++)
|
||||
glTexSubImage2D (texture_target, 0, 0, i, width, 1, gl_format, gl_type, data + (i * stride));
|
||||
}
|
||||
@@ -333,23 +359,27 @@ gdk_gl_context_real_get_damage (GdkGLContext *context)
|
||||
});
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_real_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
if (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (self)) != gdk_draw_context_get_display (GDK_DRAW_CONTEXT (other)))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: Should we check es or legacy here? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_context_real_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkSurface *surface;
|
||||
GdkGLContext *shared;
|
||||
cairo_region_t *damage;
|
||||
int ww, wh;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->begin_frame (GDK_DRAW_CONTEXT (shared), region);
|
||||
return;
|
||||
}
|
||||
|
||||
damage = GDK_GL_CONTEXT_GET_CLASS (context)->get_damage (context);
|
||||
|
||||
if (context->old_updated_area[1])
|
||||
@@ -379,15 +409,6 @@ static void
|
||||
gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkGLContext *context = GDK_GL_CONTEXT (draw_context);
|
||||
GdkGLContext *shared;
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared)
|
||||
{
|
||||
GDK_DRAW_CONTEXT_GET_CLASS (GDK_DRAW_CONTEXT (shared))->end_frame (GDK_DRAW_CONTEXT (shared), painted);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -406,6 +427,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
|
||||
klass->realize = gdk_gl_context_real_realize;
|
||||
klass->get_damage = gdk_gl_context_real_get_damage;
|
||||
klass->is_shared = gdk_gl_context_real_is_shared;
|
||||
|
||||
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
|
||||
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
|
||||
@@ -414,7 +436,13 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
/**
|
||||
* GdkGLContext:shared-context: (attributes org.gtk.Property.get=gdk_gl_context_get_shared_context)
|
||||
*
|
||||
* The `GdkGLContext` that this context is sharing data with, or %NULL
|
||||
* Always %NULL
|
||||
*
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
obj_pspecs[PROP_SHARED_CONTEXT] =
|
||||
g_param_spec_object ("shared-context",
|
||||
@@ -423,7 +451,8 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
GDK_TYPE_GL_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_DEPRECATED);
|
||||
|
||||
gobject_class->set_property = gdk_gl_context_set_property;
|
||||
gobject_class->get_property = gdk_gl_context_get_property;
|
||||
@@ -441,6 +470,21 @@ gdk_gl_context_init (GdkGLContext *self)
|
||||
priv->use_es = -1;
|
||||
}
|
||||
|
||||
/* Must have called gdk_display_prepare_gl() before */
|
||||
GdkGLContext *
|
||||
gdk_gl_context_new_for_surface (GdkSurface *surface)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkGLContext *shared = gdk_display_get_gl_context (display);
|
||||
|
||||
/* assert gdk_display_prepare_gl() had been called */
|
||||
g_assert (shared);
|
||||
|
||||
return g_object_new (G_OBJECT_TYPE (shared),
|
||||
"surface", surface,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GdkGLContextPaintData *
|
||||
gdk_gl_context_get_paint_data (GdkGLContext *context)
|
||||
{
|
||||
@@ -812,6 +856,44 @@ gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
priv->is_legacy = !!is_legacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_is_shared:
|
||||
* @self: a `GdkGLContext`
|
||||
* @other: the `GdkGLContext` that should be compatible with @self
|
||||
*
|
||||
* Checks if the two GL contexts can share resources.
|
||||
*
|
||||
* When they can, the texture IDs from @other can be used in @self. This
|
||||
* is particularly useful when passing `GdkGLTexture` objects between
|
||||
* different contexts.
|
||||
*
|
||||
* Contexts created for the same display with the same properties will
|
||||
* always be compatible, even if they are created for different surfaces.
|
||||
* For other contexts it depends on the GL backend.
|
||||
*
|
||||
* Both contexts must be realized for this check to succeed. If either one
|
||||
* is not, this function will return %FALSE.
|
||||
*
|
||||
* Returns: %TRUE if the two GL contexts are compatible.
|
||||
*
|
||||
* Since: 4.4
|
||||
*/
|
||||
gboolean
|
||||
gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
GdkGLContextPrivate *priv_other = gdk_gl_context_get_instance_private (other);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (self), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (other), FALSE);
|
||||
|
||||
if (!priv->realized || !priv_other->realized)
|
||||
return FALSE;
|
||||
|
||||
return GDK_GL_CONTEXT_GET_CLASS (self)->is_shared (self, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_set_use_es:
|
||||
* @context: a `GdkGLContext`
|
||||
@@ -1092,12 +1174,16 @@ void
|
||||
gdk_gl_context_make_current (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current, *masked_context;
|
||||
gboolean surfaceless;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_CONTEXT (context));
|
||||
|
||||
surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context));
|
||||
masked_context = mask_context (context, surfaceless);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == context)
|
||||
if (current == masked_context)
|
||||
return;
|
||||
|
||||
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
|
||||
@@ -1114,11 +1200,15 @@ gdk_gl_context_make_current (GdkGLContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)), context))
|
||||
if (!GDK_GL_CONTEXT_GET_CLASS (context)->make_current (context, surfaceless))
|
||||
{
|
||||
g_private_replace (&thread_current_context, g_object_ref (context));
|
||||
gdk_gl_context_check_extensions (context);
|
||||
g_warning ("gdk_gl_context_make_current() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref (context);
|
||||
g_private_replace (&thread_current_context, masked_context);
|
||||
gdk_gl_context_check_extensions (context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1157,18 +1247,22 @@ gdk_gl_context_get_surface (GdkGLContext *context)
|
||||
* gdk_gl_context_get_shared_context: (attributes org.gtk.Method.get_property=shared-context)
|
||||
* @context: a `GdkGLContext`
|
||||
*
|
||||
* Retrieves the `GdkGLContext` that this @context share data with.
|
||||
* Used to retrieves the `GdkGLContext` that this @context share data with.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): a `GdkGLContext`
|
||||
* As many contexts can share data now and no single shared context exists
|
||||
* anymore, this function has been deprecated and now always returns %NULL.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): %NULL
|
||||
*
|
||||
* Deprecated: 4.4: Use [method@Gdk.GLContext.is_shared] to check if contexts
|
||||
* can be shared.
|
||||
*/
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_shared_context (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
|
||||
return priv->shared_context;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1208,12 +1302,14 @@ gdk_gl_context_get_version (GdkGLContext *context,
|
||||
void
|
||||
gdk_gl_context_clear_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current != NULL)
|
||||
{
|
||||
if (gdk_display_make_gl_context_current (gdk_draw_context_get_display (GDK_DRAW_CONTEXT (current)), NULL))
|
||||
GdkGLContext *context = unmask_context (current);
|
||||
|
||||
if (GDK_GL_CONTEXT_GET_CLASS (context)->clear_current (context))
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
}
|
||||
}
|
||||
@@ -1228,11 +1324,11 @@ gdk_gl_context_clear_current (void)
|
||||
GdkGLContext *
|
||||
gdk_gl_context_get_current (void)
|
||||
{
|
||||
GdkGLContext *current;
|
||||
MaskedContext *current;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
|
||||
return current;
|
||||
return unmask_context (current);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -45,8 +45,8 @@ GType gdk_gl_context_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkDisplay * gdk_gl_context_get_display (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkSurface * gdk_gl_context_get_surface (GdkGLContext *context);
|
||||
GDK_DEPRECATED_IN_4_4_FOR(gdk_gl_context_is_shared)
|
||||
GdkGLContext * gdk_gl_context_get_shared_context (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_get_version (GdkGLContext *context,
|
||||
@@ -54,6 +54,9 @@ void gdk_gl_context_get_version (GdkGLContext *
|
||||
int *minor);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_gl_context_is_legacy (GdkGLContext *context);
|
||||
GDK_AVAILABLE_IN_4_4
|
||||
gboolean gdk_gl_context_is_shared (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_gl_context_set_required_version (GdkGLContext *context,
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/* Version requirements for EGL contexts.
|
||||
*
|
||||
* If you add support for EGL to your backend, please require this.
|
||||
*/
|
||||
#define GDK_EGL_MIN_VERSION_MAJOR (1)
|
||||
#define GDK_EGL_MIN_VERSION_MINOR (4)
|
||||
|
||||
#define GDK_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
#define GDK_IS_GL_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GL_CONTEXT))
|
||||
#define GDK_GL_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GL_CONTEXT, GdkGLContextClass))
|
||||
@@ -45,10 +52,16 @@ struct _GdkGLContextClass
|
||||
{
|
||||
GdkDrawContextClass parent_class;
|
||||
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
gboolean (* realize) (GdkGLContext *context,
|
||||
GError **error);
|
||||
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
gboolean (* make_current) (GdkGLContext *context,
|
||||
gboolean surfaceless);
|
||||
gboolean (* clear_current) (GdkGLContext *context);
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
|
||||
gboolean (* is_shared) (GdkGLContext *self,
|
||||
GdkGLContext *other);
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -73,6 +86,8 @@ typedef struct {
|
||||
guint use_es : 1;
|
||||
} GdkGLContextPaintData;
|
||||
|
||||
GdkGLContext * gdk_gl_context_new_for_surface (GdkSurface *surface);
|
||||
|
||||
void gdk_gl_context_set_is_legacy (GdkGLContext *context,
|
||||
gboolean is_legacy);
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkcairo.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@@ -37,7 +38,7 @@ struct _GdkGLTexture {
|
||||
GdkGLContext *context;
|
||||
guint id;
|
||||
|
||||
cairo_surface_t *saved;
|
||||
GdkTexture *saved;
|
||||
|
||||
GDestroyNotify destroy;
|
||||
gpointer data;
|
||||
@@ -64,50 +65,239 @@ gdk_gl_texture_dispose (GObject *object)
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
cairo_surface_destroy (self->saved);
|
||||
self->saved = NULL;
|
||||
}
|
||||
g_clear_object (&self->saved);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
typedef struct _InvokeData
|
||||
{
|
||||
GdkGLTexture *self;
|
||||
volatile int spinlock;
|
||||
GFunc func;
|
||||
gpointer data;
|
||||
} InvokeData;
|
||||
|
||||
static gboolean
|
||||
gdk_gl_texture_invoke_callback (gpointer data)
|
||||
{
|
||||
InvokeData *invoke = data;
|
||||
GdkGLContext *context;
|
||||
|
||||
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
|
||||
|
||||
invoke->func (invoke->self, invoke->data);
|
||||
|
||||
g_atomic_int_set (&invoke->spinlock, 1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
gdk_gl_texture_run (GdkGLTexture *self,
|
||||
GFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
InvokeData invoke = { self, 0, func, data };
|
||||
|
||||
g_main_context_invoke (NULL, gdk_gl_texture_invoke_callback, &invoke);
|
||||
|
||||
while (g_atomic_int_get (&invoke.spinlock) == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_texture (gpointer texture_,
|
||||
gpointer result_)
|
||||
{
|
||||
GdkTexture *texture = texture_;
|
||||
GdkTexture **result = result_;
|
||||
GdkMemoryFormat format;
|
||||
GLint internal_format, gl_format, gl_type;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
GBytes *bytes;
|
||||
|
||||
glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
|
||||
|
||||
switch (internal_format)
|
||||
{
|
||||
case GL_RGB8:
|
||||
format = GDK_MEMORY_R8G8B8;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
format = GDK_MEMORY_R16G16B16;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16:
|
||||
format = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_SHORT;
|
||||
break;
|
||||
|
||||
case GL_RGB16F:
|
||||
format = GDK_MEMORY_R16G16B16_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA16F:
|
||||
format = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_HALF_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGB32F:
|
||||
format = GDK_MEMORY_R32G32B32_FLOAT;
|
||||
gl_format = GL_RGB;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
case GL_RGBA32F:
|
||||
format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_FLOAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Texture in unexpected format 0x%X (%d). File a bug about adding it to GTK", internal_format, internal_format);
|
||||
/* fallback to the dumbest possible format
|
||||
* so that even age old GLES can do it */
|
||||
format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
}
|
||||
|
||||
stride = gdk_memory_format_bytes_per_pixel (format) * texture->width;
|
||||
data = g_malloc (stride * texture->height);
|
||||
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
gl_format,
|
||||
gl_type,
|
||||
data);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
*result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
bytes,
|
||||
stride);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_gl_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
GdkTexture *result;
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
area->width, area->height,
|
||||
stride);
|
||||
if (self->saved)
|
||||
return g_object_ref (self->saved);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_texture, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_BGRA,
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV,
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
GL_UNSIGNED_BYTE,
|
||||
#else
|
||||
#error "Unknown byte order for gdk_gl_texture_download()"
|
||||
#endif
|
||||
data);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
cairo_set_source_surface (cr, self->saved, 0, 0);
|
||||
cairo_paint (cr);
|
||||
gdk_texture_download (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
if (gdk_gl_context_get_use_es (self->context) ||
|
||||
stride != texture->width * 4)
|
||||
{
|
||||
GdkSurface *gl_surface;
|
||||
|
||||
gl_surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, gl_surface, self->id, GL_TEXTURE, 1,
|
||||
area->x, area->y,
|
||||
area->width, area->height);
|
||||
GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download (texture, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download, data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_do_download_float (gpointer texture,
|
||||
gpointer data)
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
|
||||
int width, height, y;
|
||||
float *copy;
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_download_float (self->saved, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
if (stride == width * 4)
|
||||
{
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
|
||||
return;
|
||||
}
|
||||
|
||||
copy = g_new (float, width * height * 4);
|
||||
|
||||
gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, copy);
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (data + y * stride, copy + y * 4 * width, 4 * width);
|
||||
|
||||
g_free (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -116,7 +306,9 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_gl_texture_download_texture;
|
||||
texture_class->download = gdk_gl_texture_download;
|
||||
texture_class->download_float = gdk_gl_texture_download_float;
|
||||
gobject_class->dispose = gdk_gl_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -150,24 +342,10 @@ gdk_gl_texture_get_id (GdkGLTexture *self)
|
||||
void
|
||||
gdk_gl_texture_release (GdkGLTexture *self)
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GdkTexture *texture;
|
||||
cairo_t *cr;
|
||||
|
||||
g_return_if_fail (GDK_IS_GL_TEXTURE (self));
|
||||
g_return_if_fail (self->saved == NULL);
|
||||
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
texture->width, texture->height);
|
||||
|
||||
cr = cairo_create (self->saved);
|
||||
|
||||
surface = gdk_gl_context_get_surface (self->context);
|
||||
gdk_cairo_draw_from_gl (cr, surface, self->id, GL_TEXTURE, 1, 0, 0,
|
||||
texture->width, texture->height);
|
||||
|
||||
cairo_destroy (cr);
|
||||
self->saved = gdk_texture_download_texture (GDK_TEXTURE (self));
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkhslaprivate.h"
|
||||
#include "gdkhslaprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
_gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float min;
|
||||
@@ -31,21 +31,21 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
float green;
|
||||
float blue;
|
||||
float delta;
|
||||
|
||||
|
||||
g_return_if_fail (hsla != NULL);
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
red = rgba->red;
|
||||
green = rgba->green;
|
||||
blue = rgba->blue;
|
||||
|
||||
|
||||
if (red > green)
|
||||
{
|
||||
if (red > blue)
|
||||
max = red;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (green < blue)
|
||||
min = green;
|
||||
else
|
||||
@@ -57,25 +57,25 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
max = green;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
|
||||
if (red < blue)
|
||||
min = red;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
|
||||
|
||||
hsla->lightness = (max + min) / 2;
|
||||
hsla->saturation = 0;
|
||||
hsla->hue = 0;
|
||||
hsla->alpha = rgba->alpha;
|
||||
|
||||
|
||||
if (max != min)
|
||||
{
|
||||
if (hsla->lightness <= 0.5)
|
||||
hsla->saturation = (max - min) / (max + min);
|
||||
else
|
||||
hsla->saturation = (max - min) / (2 - max - min);
|
||||
|
||||
|
||||
delta = max -min;
|
||||
if (red == max)
|
||||
hsla->hue = (green - blue) / delta;
|
||||
@@ -83,7 +83,7 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
hsla->hue = 2 + (blue - red) / delta;
|
||||
else if (blue == max)
|
||||
hsla->hue = 4 + (red - green) / delta;
|
||||
|
||||
|
||||
hsla->hue *= 60;
|
||||
if (hsla->hue < 0.0)
|
||||
hsla->hue += 360;
|
||||
@@ -92,22 +92,22 @@ _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
|
||||
void
|
||||
_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GtkHSLA *hsla)
|
||||
const GdkHSLA *hsla)
|
||||
{
|
||||
float hue;
|
||||
float lightness;
|
||||
float saturation;
|
||||
float m1, m2;
|
||||
|
||||
|
||||
lightness = hsla->lightness;
|
||||
saturation = hsla->saturation;
|
||||
|
||||
|
||||
if (lightness <= 0.5)
|
||||
m2 = lightness * (1 + saturation);
|
||||
else
|
||||
m2 = lightness + saturation - lightness * saturation;
|
||||
m1 = 2 * lightness - m2;
|
||||
|
||||
|
||||
rgba->alpha = hsla->alpha;
|
||||
|
||||
if (saturation == 0)
|
||||
@@ -123,7 +123,7 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -132,13 +132,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->red = m1;
|
||||
|
||||
|
||||
hue = hsla->hue;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->green = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -147,13 +147,13 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->green = m1;
|
||||
|
||||
|
||||
hue = hsla->hue - 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
|
||||
if (hue < 60)
|
||||
rgba->blue = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
@@ -166,8 +166,8 @@ _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
_gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
float factor)
|
||||
{
|
||||
g_return_if_fail (dest != NULL);
|
||||
@@ -22,23 +22,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkHSLA GtkHSLA;
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
|
||||
struct _GtkHSLA {
|
||||
struct _GdkHSLA {
|
||||
float hue;
|
||||
float saturation;
|
||||
float lightness;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
void _gtk_hsla_init_from_rgba (GtkHSLA *hsla,
|
||||
void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba);
|
||||
/* Yes, I can name that function like this! */
|
||||
void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GtkHSLA *hsla);
|
||||
const GdkHSLA *hsla);
|
||||
|
||||
void _gtk_hsla_shade (GtkHSLA *dest,
|
||||
const GtkHSLA *src,
|
||||
void _gdk_hsla_shade (GdkHSLA *dest,
|
||||
const GdkHSLA *src,
|
||||
float factor);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gsk/ngl/fp16private.h"
|
||||
|
||||
/**
|
||||
* GdkMemoryTexture:
|
||||
@@ -49,6 +50,10 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
@@ -58,9 +63,19 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return 4;
|
||||
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
return 3;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return 6;
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return 8;
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
return 12;
|
||||
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return 16;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
@@ -69,6 +84,41 @@ gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
static gsize
|
||||
gdk_memory_format_alignment (GdkMemoryFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
return G_ALIGNOF (guchar);
|
||||
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (guint16);
|
||||
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
return G_ALIGNOF (float);
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return G_ALIGNOF (double);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_dispose (GObject *object)
|
||||
{
|
||||
@@ -79,22 +129,41 @@ gdk_memory_texture_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (gdk_memory_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
gdk_memory_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
return g_object_ref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL)
|
||||
+ area->x * gdk_memory_format_bytes_per_pixel (self->format)
|
||||
+ area->y * self->stride,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
area->width, area->height);
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_memory_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
|
||||
|
||||
gdk_memory_convert_to_float (data, stride,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
self->format,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -103,7 +172,9 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
|
||||
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
texture_class->download_texture = gdk_memory_texture_download_texture;
|
||||
texture_class->download = gdk_memory_texture_download;
|
||||
texture_class->download_float = gdk_memory_texture_download_float;
|
||||
gobject_class->dispose = gdk_memory_texture_dispose;
|
||||
}
|
||||
|
||||
@@ -112,6 +183,41 @@ gdk_memory_texture_init (GdkMemoryTexture *self)
|
||||
{
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_memory_sanitize (GBytes *bytes,
|
||||
int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
gsize stride,
|
||||
gsize *out_stride)
|
||||
{
|
||||
gsize align, size, copy_stride, bpp;
|
||||
const guchar *data;
|
||||
guchar *copy;
|
||||
int y;
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
align = gdk_memory_format_alignment (format);
|
||||
|
||||
if (GPOINTER_TO_SIZE (data) % align == 0 &&
|
||||
stride % align == 0)
|
||||
{
|
||||
*out_stride = stride;
|
||||
return g_bytes_ref (bytes);
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
copy_stride = bpp * width;
|
||||
/* align to multiples of 4, just to be sure */
|
||||
copy_stride = (copy_stride + 3) & ~3;
|
||||
copy = g_malloc (copy_stride * height);
|
||||
for (y = 0; y < height; y++)
|
||||
memcpy (copy + y * copy_stride, data + y * stride, bpp * width);
|
||||
|
||||
*out_stride = copy_stride;
|
||||
return g_bytes_new_take (copy, copy_stride * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new:
|
||||
* @width: the width of the texture
|
||||
@@ -136,13 +242,20 @@ gdk_memory_texture_new (int width,
|
||||
{
|
||||
GdkMemoryTexture *self;
|
||||
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
|
||||
bytes = gdk_memory_sanitize (bytes, width, height, format, stride, &stride);
|
||||
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
NULL);
|
||||
|
||||
self->format = format;
|
||||
self->bytes = g_bytes_ref (bytes);
|
||||
self->bytes = bytes;
|
||||
self->stride = stride;
|
||||
|
||||
return GDK_TEXTURE (self);
|
||||
@@ -283,6 +396,109 @@ SWIZZLE_PREMULTIPLY (3,0,1,2, 0,1,2,3)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 3,0,1,2)
|
||||
SWIZZLE_PREMULTIPLY (3,0,1,2, 0,3,2,1)
|
||||
|
||||
#define CONVERT_FUNC(name,suffix,R,G,B,A,step) \
|
||||
static void \
|
||||
convert_ ## name ## _to_ ## suffix (guchar *dest_data, \
|
||||
gsize dest_stride, \
|
||||
const guchar *src_data, \
|
||||
gsize src_stride, \
|
||||
gsize width, \
|
||||
gsize height) \
|
||||
{ \
|
||||
gsize x, y; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
guchar conv[4]; \
|
||||
convert_pixel_ ## name (conv, src_data + step * x); \
|
||||
dest_data[4 * x + R] = conv[0]; \
|
||||
dest_data[4 * x + G] = conv[1]; \
|
||||
dest_data[4 * x + B] = conv[2]; \
|
||||
dest_data[4 * x + A] = conv[3]; \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CONVERT_FUNCS(name,step) \
|
||||
CONVERT_FUNC(name, download_le, 2, 1, 0, 3, step) \
|
||||
CONVERT_FUNC(name, download_be, 1, 2, 3, 0, step) \
|
||||
CONVERT_FUNC(name, gles_rgba, 0, 1, 2, 3, step) \
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16 (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest_data[0] = (guchar)(src[0] >> 8);
|
||||
dest_data[1] = (guchar)(src[1] >> 8);
|
||||
dest_data[2] = (guchar)(src[2] >> 8);
|
||||
dest_data[3] = (guchar)(src[3] >> 8);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
half_to_float4(tmp, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb16f, 3 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba16f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float src[4];
|
||||
half_to_float4((const guint16 *) src_data, src);
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba16f, 4 * sizeof (guint16))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgb32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = 0xFF;
|
||||
}
|
||||
CONVERT_FUNCS(rgb32f, 3 * sizeof (float))
|
||||
|
||||
static inline void
|
||||
convert_pixel_rgba32f (guchar *dest_data, const guchar *src_data)
|
||||
{
|
||||
float *src = (float *) src_data;
|
||||
dest_data[0] = CLAMP (src[0] * 256.f, 0.f, 255.f);
|
||||
dest_data[1] = CLAMP (src[1] * 256.f, 0.f, 255.f);
|
||||
dest_data[2] = CLAMP (src[2] * 256.f, 0.f, 255.f);
|
||||
dest_data[3] = CLAMP (src[3] * 256.f, 0.f, 255.f);
|
||||
}
|
||||
CONVERT_FUNCS(rgba32f, 4 * sizeof (float))
|
||||
|
||||
typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
@@ -290,7 +506,7 @@ typedef void (* ConversionFunc) (guchar *dest_data,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
static ConversionFunc converters[GDK_MEMORY_N_FORMATS][GDK_MEMORY_N_CONVERSIONS] =
|
||||
{
|
||||
{ convert_memcpy, convert_swizzle3210, convert_swizzle2103 },
|
||||
{ convert_swizzle3210, convert_memcpy, convert_swizzle3012 },
|
||||
@@ -300,21 +516,192 @@ static ConversionFunc converters[GDK_MEMORY_N_FORMATS][3] =
|
||||
{ convert_swizzle_premultiply_3210_3012, convert_swizzle_premultiply_0123_3012, convert_swizzle_premultiply_3012_3012 },
|
||||
{ convert_swizzle_premultiply_3210_0321, convert_swizzle_premultiply_0123_0321, convert_swizzle_premultiply_3012_0321 },
|
||||
{ convert_swizzle_opaque_3210, convert_swizzle_opaque_0123, convert_swizzle_opaque_3012 },
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 }
|
||||
{ convert_swizzle_opaque_3012, convert_swizzle_opaque_0321, convert_swizzle_opaque_3210 },
|
||||
{ convert_rgb16_to_download_le, convert_rgb16_to_download_be, convert_rgb16_to_gles_rgba },
|
||||
{ convert_rgba16_to_download_le, convert_rgba16_to_download_be, convert_rgba16_to_gles_rgba },
|
||||
{ convert_rgb16f_to_download_le, convert_rgb16f_to_download_be, convert_rgb16f_to_gles_rgba },
|
||||
{ convert_rgba16f_to_download_le, convert_rgba16f_to_download_be, convert_rgba16f_to_gles_rgba },
|
||||
{ convert_rgb32f_to_download_le, convert_rgb32f_to_download_be, convert_rgb32f_to_gles_rgba },
|
||||
{ convert_rgba32f_to_download_le, convert_rgba32f_to_download_be, convert_rgba32f_to_gles_rgba }
|
||||
};
|
||||
|
||||
void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
g_assert (dest_format < 3);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
converters[src_format][dest_format] (dest_data, dest_stride, src_data, src_stride, width, height);
|
||||
}
|
||||
|
||||
#define CONVERT_FLOAT(R,G,B,A,premultiply) G_STMT_START {\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
if (A >= 0) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[4 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[4 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[4 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = src_data[4 * x + A] / 255.0f; \
|
||||
if (premultiply) \
|
||||
{ \
|
||||
dest_data[4 * x + 0] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 1] *= dest_data[4 * x + 3]; \
|
||||
dest_data[4 * x + 2] *= dest_data[4 * x + 3]; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
dest_data[4 * x + 0] = src_data[3 * x + R] / 255.0f; \
|
||||
dest_data[4 * x + 1] = src_data[3 * x + G] / 255.0f; \
|
||||
dest_data[4 * x + 2] = src_data[3 * x + B] / 255.0f; \
|
||||
dest_data[4 * x + 3] = 1.0; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
#define CONVERT_FLOAT_PIXEL(func,step) G_STMT_START{\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
for (x = 0; x < width; x++) \
|
||||
{ \
|
||||
func (dest_data + 4 * x, src_data + step * x); \
|
||||
} \
|
||||
\
|
||||
dest_data += dest_stride; \
|
||||
src_data += src_stride; \
|
||||
} \
|
||||
}G_STMT_END
|
||||
|
||||
static inline void
|
||||
convert_rgb16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const guint16 *src = (const guint16 *) src_data;
|
||||
dest[0] = src[0] / 65535.f;
|
||||
dest[1] = src[1] / 65535.f;
|
||||
dest[2] = src[2] / 65535.f;
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
guint16 tmp[4];
|
||||
memcpy(tmp, src_data, sizeof(guint16) * 3);
|
||||
tmp[3] = FP16_ONE;
|
||||
half_to_float4 (tmp, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba16f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
half_to_float4 ((const guint16 *) src_data, dest);
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgb32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = 1.0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
convert_rgba32f_to_float (float *dest, const guchar *src_data)
|
||||
{
|
||||
const float *src = (const float *) src_data;
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
dest[3] = src[3];
|
||||
}
|
||||
|
||||
void
|
||||
gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
gsize x, y;
|
||||
|
||||
switch (src_format)
|
||||
{
|
||||
case GDK_MEMORY_B8G8R8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8_PREMULTIPLIED:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8A8:
|
||||
CONVERT_FLOAT (2, 1, 0, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8R8G8B8:
|
||||
CONVERT_FLOAT (1, 2, 3, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8A8:
|
||||
CONVERT_FLOAT (0, 1, 2, 3, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_A8B8G8R8:
|
||||
CONVERT_FLOAT (3, 2, 1, 0, TRUE);
|
||||
break;
|
||||
case GDK_MEMORY_R8G8B8:
|
||||
CONVERT_FLOAT (0, 1, 2, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_B8G8R8:
|
||||
CONVERT_FLOAT (2, 1, 0, -1, FALSE);
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb16f_to_float, 3 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba16f_to_float, 4 * sizeof (guint16));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32_FLOAT:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgb32f_to_float, 3 * sizeof (float));
|
||||
break;
|
||||
case GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
CONVERT_FLOAT_PIXEL (convert_rgba32f_to_float, 4 * sizeof (float));
|
||||
break;
|
||||
|
||||
case GDK_MEMORY_N_FORMATS:
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,20 @@ G_BEGIN_DECLS
|
||||
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
|
||||
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
|
||||
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
|
||||
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
|
||||
* blue, alpha. The color values are premultiplied with the alpha value.
|
||||
* Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16_FLOAT: 3 half-float values; for red, green, blue.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: 4 half-float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_B32G32R32_FLOAT: 3 float values; for blue, green, red.
|
||||
* The data is opaque. Since 4.6
|
||||
* @GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: 4 float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since 4.6
|
||||
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
|
||||
* more formats get added, so do not rely on its concrete integer.
|
||||
*
|
||||
@@ -67,6 +81,12 @@ typedef enum {
|
||||
GDK_MEMORY_A8B8G8R8,
|
||||
GDK_MEMORY_R8G8B8,
|
||||
GDK_MEMORY_B8G8R8,
|
||||
GDK_MEMORY_R16G16B16,
|
||||
GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
|
||||
GDK_MEMORY_R16G16B16_FLOAT,
|
||||
GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
|
||||
GDK_MEMORY_R32G32B32_FLOAT,
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
|
||||
GDK_MEMORY_N_FORMATS
|
||||
} GdkMemoryFormat;
|
||||
|
||||
@@ -29,7 +29,21 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
#define GDK_MEMORY_CAIRO_FORMAT_ARGB32 GDK_MEMORY_DEFAULT
|
||||
typedef enum {
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_DOWNLOAD_BIT_ENDIAN,
|
||||
GDK_MEMORY_CONVERT_GLES_RGBA,
|
||||
|
||||
GDK_MEMORY_N_CONVERSIONS
|
||||
} GdkMemoryConversion;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_LITTLE_ENDIAN
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define GDK_MEMORY_CONVERT_DOWNLOAD GDK_MEMORY_CONVERT_DOWNLOAD_BIG_ENDIAN
|
||||
#else
|
||||
#error "Unknown byte order for GDK_MEMORY_CONVERT_DOWNLOAD"
|
||||
#endif
|
||||
|
||||
gsize gdk_memory_format_bytes_per_pixel (GdkMemoryFormat format);
|
||||
|
||||
@@ -37,14 +51,22 @@ GdkMemoryFormat gdk_memory_texture_get_format (GdkMemoryTexture *
|
||||
const guchar * gdk_memory_texture_get_data (GdkMemoryTexture *self);
|
||||
gsize gdk_memory_texture_get_stride (GdkMemoryTexture *self);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryConversion dest_format,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
void gdk_memory_convert_to_float (float *dest_data,
|
||||
gsize dest_stride,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -70,17 +70,17 @@ typedef enum {
|
||||
* snapshot at or 0 if none. This is purely a hint. The object must still
|
||||
* be able to render at any size.
|
||||
* @get_intrinsic_aspect_ratio: The preferred aspect ratio for this object
|
||||
* or 0 if none. If both [vfunc@Gdk.PaintableInterface.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.PaintableInterface.get_intrinsic_height] return non-zero
|
||||
* or 0 if none. If both [vfunc@Gdk.Paintable.get_intrinsic_width]
|
||||
* and [vfunc@Gdk.Paintable.get_intrinsic_height] return non-zero
|
||||
* values, this function should return the aspect ratio computed from those.
|
||||
*
|
||||
* The list of functions that can be implemented for the `GdkPaintable`
|
||||
* interface.
|
||||
*
|
||||
* Note that apart from the [vfunc@Gdk.PaintableInterface.snapshot] function,
|
||||
* Note that apart from the [vfunc@Gdk.Paintable.snapshot] function,
|
||||
* no virtual function of this interface is mandatory to implement, though it
|
||||
* is a good idea to implement [vfunc@Gdk.PaintableInterface.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.PaintableInterface.get_flags] if the
|
||||
* is a good idea to implement [vfunc@Gdk.Paintable.get_current_image]
|
||||
* for non-static paintables and [vfunc@Gdk.Paintable.get_flags] if the
|
||||
* image is not dynamic as the default implementation returns no flags and
|
||||
* that will make the implementation likely quite slow.
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "gdkhslaprivate.h"
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkRGBA, gdk_rgba,
|
||||
gdk_rgba_copy, gdk_rgba_free)
|
||||
@@ -186,6 +187,7 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
const char *spec)
|
||||
{
|
||||
gboolean has_alpha;
|
||||
gboolean is_hsl;
|
||||
double r, g, b, a;
|
||||
char *str = (char *) spec;
|
||||
char *p;
|
||||
@@ -196,11 +198,26 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
if (strncmp (str, "rgba", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = FALSE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "rgb", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = FALSE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
else if (strncmp (str, "hsla", 4) == 0)
|
||||
{
|
||||
has_alpha = TRUE;
|
||||
is_hsl = TRUE;
|
||||
str += 4;
|
||||
}
|
||||
else if (strncmp (str, "hsl", 3) == 0)
|
||||
{
|
||||
has_alpha = FALSE;
|
||||
is_hsl = TRUE;
|
||||
a = 1;
|
||||
str += 3;
|
||||
}
|
||||
@@ -291,10 +308,22 @@ gdk_rgba_parse (GdkRGBA *rgba,
|
||||
|
||||
if (rgba)
|
||||
{
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
if (is_hsl)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
hsla.hue = r * 255;
|
||||
hsla.saturation = CLAMP (g, 0, 1);
|
||||
hsla.lightness = CLAMP (b, 0, 1);
|
||||
hsla.alpha = CLAMP (a, 0, 1);
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba->red = CLAMP (r, 0, 1);
|
||||
rgba->green = CLAMP (g, 0, 1);
|
||||
rgba->blue = CLAMP (b, 0, 1);
|
||||
rgba->alpha = CLAMP (a, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -462,6 +491,47 @@ parse_color_channel (GtkCssParser *parser,
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
parse_hsla_color_channel (GtkCssParser *parser,
|
||||
guint arg,
|
||||
gpointer data)
|
||||
{
|
||||
GdkHSLA *hsla = data;
|
||||
double dvalue;
|
||||
|
||||
switch (arg)
|
||||
{
|
||||
case 0:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->hue = dvalue;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->saturation = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
if (!gtk_css_parser_consume_percentage (parser, &dvalue))
|
||||
return 0;
|
||||
hsla->lightness = CLAMP (dvalue, 0.0, 100.0) / 100.0;
|
||||
return 1;
|
||||
|
||||
case 3:
|
||||
if (!gtk_css_parser_consume_number (parser, &dvalue))
|
||||
return 0;
|
||||
|
||||
hsla->alpha = CLAMP (dvalue, 0.0, 1.0) / 1.0;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rgba_init_chars (GdkRGBA *rgba,
|
||||
const char s[8])
|
||||
@@ -501,6 +571,18 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
{
|
||||
return gtk_css_parser_consume_function (parser, 4, 4, parse_color_channel, rgba);
|
||||
}
|
||||
else if (gtk_css_token_is_function (token, "hsl") || gtk_css_token_is_function (token, "hsla"))
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
hsla.alpha = 1.0;
|
||||
|
||||
if (!gtk_css_parser_consume_function (parser, 3, 4, parse_hsla_color_channel, &hsla))
|
||||
return FALSE;
|
||||
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
|
||||
{
|
||||
|
||||
@@ -1065,87 +1065,23 @@ gdk_surface_get_mapped (GdkSurface *surface)
|
||||
return GDK_SURFACE_IS_MAPPED (surface);
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_shared_data_gl_context (GdkSurface *surface)
|
||||
{
|
||||
static int in_shared_data_creation;
|
||||
GdkDisplay *display;
|
||||
GdkGLContext *context;
|
||||
|
||||
if (in_shared_data_creation)
|
||||
return NULL;
|
||||
|
||||
in_shared_data_creation = 1;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "gdk-gl-shared-data-context");
|
||||
if (context == NULL)
|
||||
{
|
||||
GError *error = NULL;
|
||||
context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to create shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (context, &error);
|
||||
if (context == NULL)
|
||||
{
|
||||
g_warning ("Failed to realize shared context: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
|
||||
g_object_set_data (G_OBJECT (display), "gdk-gl-shared-data-context", context);
|
||||
}
|
||||
|
||||
in_shared_data_creation = 0;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
GError **error)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (surface->display, GL_DISABLE))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("GL support disabled via GDK_DEBUG"));
|
||||
return NULL;
|
||||
}
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
if (surface->gl_paint_context == NULL)
|
||||
{
|
||||
GdkSurfaceClass *class = GDK_SURFACE_GET_CLASS (surface);
|
||||
|
||||
if (class->create_gl_context == NULL)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("The current backend does not support OpenGL"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surface->gl_paint_context =
|
||||
class->create_gl_context (surface, TRUE, NULL, &internal_error);
|
||||
surface->gl_paint_context = gdk_surface_create_gl_context (surface, error);
|
||||
if (surface->gl_paint_context == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (internal_error != NULL)
|
||||
if (!gdk_gl_context_realize (surface->gl_paint_context, error))
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gdk_gl_context_realize (surface->gl_paint_context, &internal_error);
|
||||
if (internal_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, internal_error);
|
||||
g_clear_object (&(surface->gl_paint_context));
|
||||
g_clear_object (&surface->gl_paint_context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1170,19 +1106,13 @@ GdkGLContext *
|
||||
gdk_surface_create_gl_context (GdkSurface *surface,
|
||||
GError **error)
|
||||
{
|
||||
GdkGLContext *paint_context;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
paint_context = gdk_surface_get_paint_gl_context (surface, error);
|
||||
if (paint_context == NULL)
|
||||
if (!gdk_display_prepare_gl (surface->display, error))
|
||||
return NULL;
|
||||
|
||||
return GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface,
|
||||
FALSE,
|
||||
paint_context,
|
||||
error);
|
||||
return gdk_gl_context_new_for_surface (surface);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -160,10 +160,6 @@ struct _GdkSurfaceClass
|
||||
|
||||
void (* set_opaque_region) (GdkSurface *surface,
|
||||
cairo_region_t *region);
|
||||
GdkGLContext *(*create_gl_context) (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error);
|
||||
void (* request_layout) (GdkSurface *surface);
|
||||
gboolean (* compute_size) (GdkSurface *surface);
|
||||
};
|
||||
@@ -266,7 +262,6 @@ void _gdk_surface_update_size (GdkSurface *surface);
|
||||
|
||||
GdkGLContext * gdk_surface_get_paint_gl_context (GdkSurface *surface,
|
||||
GError **error);
|
||||
GdkGLContext * gdk_surface_get_shared_data_gl_context (GdkSurface *surface);
|
||||
|
||||
gboolean gdk_surface_handle_event (GdkEvent *event);
|
||||
GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface,
|
||||
|
||||
323
gdk/gdktexture.c
@@ -46,6 +46,11 @@
|
||||
#include "gdksnapshot.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
#include "loaders/gdktiffprivate.h"
|
||||
#include "loaders/gdkjpegprivate.h"
|
||||
|
||||
G_DEFINE_QUARK (gdk-texture-error-quark, gdk_texture_error)
|
||||
|
||||
/* HACK: So we don't need to include any (not-yet-created) GSK or GTK headers */
|
||||
void
|
||||
@@ -115,13 +120,35 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
#define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
|
||||
g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj))
|
||||
|
||||
static void
|
||||
gdk_texture_real_download (GdkTexture *self,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
static GdkTexture *
|
||||
gdk_texture_real_download_texture (GdkTexture *self)
|
||||
{
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
|
||||
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download_texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (texture);
|
||||
gdk_texture_download (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_real_download_float (GdkTexture *self,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkTexture *memory_texture;
|
||||
|
||||
memory_texture = gdk_texture_download_texture (self);
|
||||
gdk_texture_download_float (memory_texture, data, stride);
|
||||
g_object_unref (memory_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -187,7 +214,9 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->download_texture = gdk_texture_real_download_texture;
|
||||
klass->download = gdk_texture_real_download;
|
||||
klass->download_float = gdk_texture_real_download_float;
|
||||
|
||||
gobject_class->set_property = gdk_texture_set_property;
|
||||
gobject_class->get_property = gdk_texture_get_property;
|
||||
@@ -263,7 +292,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_CAIRO_FORMAT_ARGB32,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
@@ -359,28 +388,92 @@ GdkTexture *
|
||||
gdk_texture_new_from_file (GFile *file,
|
||||
GError **error)
|
||||
{
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkPixbuf *pixbuf;
|
||||
GInputStream *stream;
|
||||
|
||||
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
||||
if (stream == NULL)
|
||||
bytes = g_file_load_bytes (file, NULL, NULL, error);
|
||||
if (bytes == NULL)
|
||||
return NULL;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
|
||||
g_object_unref (stream);
|
||||
if (pixbuf == NULL)
|
||||
return NULL;
|
||||
texture = gdk_texture_new_from_bytes (bytes, error);
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gdk_texture_new_from_bytes:
|
||||
* @bytes: a `GBytes` containing the data to load
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from memory,
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
* Return value: A newly-created `GdkTexture`
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
GError **error)
|
||||
{
|
||||
const char *data;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
data = g_bytes_get_data (bytes, &size);
|
||||
|
||||
if (size > strlen (PNG_SIGNATURE) &&
|
||||
memcmp (data, PNG_SIGNATURE, strlen (PNG_SIGNATURE)) == 0)
|
||||
{
|
||||
return gdk_load_png (bytes, error);
|
||||
}
|
||||
else if ((size > strlen (TIFF_SIGNATURE1) &&
|
||||
memcmp (data, TIFF_SIGNATURE1, strlen (TIFF_SIGNATURE1)) == 0) ||
|
||||
(size > strlen (TIFF_SIGNATURE2) &&
|
||||
memcmp (data, TIFF_SIGNATURE2, strlen (TIFF_SIGNATURE2)) == 0))
|
||||
{
|
||||
return gdk_load_tiff (bytes, error);
|
||||
}
|
||||
else if (size > strlen (JPEG_SIGNATURE) &&
|
||||
memcmp (data, JPEG_SIGNATURE, strlen (JPEG_SIGNATURE)) == 0)
|
||||
{
|
||||
return gdk_load_jpeg (bytes, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
GInputStream *stream;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
stream = g_memory_input_stream_new_from_bytes (bytes);
|
||||
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
|
||||
g_object_unref (stream);
|
||||
|
||||
if (pixbuf)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_width: (attributes org.gtk.Method.get_property=width)
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -435,20 +528,6 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_download_area (GdkTexture *texture,
|
||||
const GdkRectangle *area,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_assert (area->x >= 0);
|
||||
g_assert (area->y >= 0);
|
||||
g_assert (area->x + area->width <= texture->width);
|
||||
g_assert (area->y + area->height <= texture->height);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, area, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download:
|
||||
* @texture: a `GdkTexture`
|
||||
@@ -485,10 +564,62 @@ gdk_texture_download (GdkTexture *texture,
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
gdk_texture_download_area (texture,
|
||||
&(GdkRectangle) { 0, 0, texture->width, texture->height },
|
||||
data,
|
||||
stride);
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_download_float:
|
||||
* @texture: a `GdkTexture`
|
||||
* @data: (array): pointer to enough memory to be filled with the
|
||||
* downloaded data of @texture
|
||||
* @stride: rowstride in elements, will usually be equal to
|
||||
* gdk_texture_get_width() * 4
|
||||
*
|
||||
* Downloads the @texture into local memory in a high dynamic range format.
|
||||
*
|
||||
* This may be an expensive operation, as the actual texture data
|
||||
* may reside on a GPU or on a remote display server and because the data
|
||||
* may need to be upsampled if it was not already available in this
|
||||
* format.
|
||||
*
|
||||
* You may want to use [method@Gdk.Texture.download] instead if you don't
|
||||
* need high dynamic range support.
|
||||
*
|
||||
* The data format of the downloaded data is equivalent to
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, so every downloaded
|
||||
* pixel requires 16 bytes of memory.
|
||||
*
|
||||
* Note that the caller is responsible to provide sufficiently
|
||||
* aligned memory to access the resulting data directly as floats.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
void
|
||||
gdk_texture_download_float (GdkTexture *texture,
|
||||
float *data,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
||||
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
|
||||
}
|
||||
|
||||
GdkTexture *
|
||||
gdk_texture_download_texture (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
g_object_ref (texture);
|
||||
while (!GDK_IS_MEMORY_TEXTURE (texture))
|
||||
{
|
||||
GdkTexture *downloaded = GDK_TEXTURE_GET_CLASS (texture)->download_texture (texture);
|
||||
g_object_unref (texture);
|
||||
texture = downloaded;
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -533,14 +664,15 @@ gdk_texture_get_render_data (GdkTexture *self,
|
||||
/**
|
||||
* gdk_texture_save_to_png:
|
||||
* @texture: a `GdkTexture`
|
||||
* @filename: the filename to store to
|
||||
* @filename: (type filename): the filename to store to
|
||||
*
|
||||
* Store the given @texture to the @filename as a PNG file.
|
||||
*
|
||||
* This is a utility function intended for debugging and testing.
|
||||
* If you want more control over formats, proper error handling or
|
||||
* want to store to a `GFile` or other location, you might want to
|
||||
* look into using the gdk-pixbuf library.
|
||||
* use gdk_texture_save_to_png_bytes() or look into the
|
||||
* gdk-pixbuf library.
|
||||
*
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*/
|
||||
@@ -548,30 +680,109 @@ gboolean
|
||||
gdk_texture_save_to_png (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
GBytes *bytes;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
status = cairo_surface_write_to_png (surface, filename);
|
||||
|
||||
if (status != CAIRO_STATUS_SUCCESS ||
|
||||
cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
|
||||
result = FALSE;
|
||||
else
|
||||
result = TRUE;
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
bytes = gdk_save_png (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_png_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a PNG file.
|
||||
* Use gdk_texture_new_from_bytes() to read it back.
|
||||
*
|
||||
* If you want to serialize a texture, this is a convenient and
|
||||
* portable way to do that.
|
||||
*
|
||||
* If you need more control over the generated image, such as
|
||||
* attaching metadata, you should look into an image handling
|
||||
* library such as the gdk-pixbuf library.
|
||||
*
|
||||
* If you are dealing with high dynamic range float data, you
|
||||
* might also want to consider gdk_texture_save_to_tiff_bytes()
|
||||
* instead.
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing PNG data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_png_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_png (texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff:
|
||||
* @texture: a `GdkTexture`
|
||||
* @filename: (type filename): the filename to store to
|
||||
*
|
||||
* Store the given @texture to the @filename as a TIFF file.
|
||||
*
|
||||
* GTK will attempt to store data without loss.
|
||||
* Returns: %TRUE if saving succeeded, %FALSE on failure.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
gboolean
|
||||
gdk_texture_save_to_tiff (GdkTexture *texture,
|
||||
const char *filename)
|
||||
{
|
||||
GBytes *bytes;
|
||||
gboolean result;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
|
||||
bytes = gdk_save_tiff (texture);
|
||||
result = g_file_set_contents (filename,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes),
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_save_to_tiff_bytes:
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Store the given @texture in memory as a TIFF file.
|
||||
* Use gdk_texture_new_from_bytes() to read it back.
|
||||
*
|
||||
* This function is intended to store a representation of the
|
||||
* texture's data that is as accurate as possible. This is
|
||||
* particularly relevant when working with high dynamic range
|
||||
* images and floating-point texture data.
|
||||
*
|
||||
* If that is not your concern and you are interested in a
|
||||
* smaller size and a more portable format, you might want to
|
||||
* use gdk_texture_save_to_png_bytes().
|
||||
*
|
||||
* Returns: a newly allocated `GBytes` containing TIFF data
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GBytes *
|
||||
gdk_texture_save_to_tiff_bytes (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return gdk_save_tiff (texture);
|
||||
}
|
||||
|
||||
|
||||