Compare commits
430 Commits
4.9.2
...
gl-sync-wo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
406a32d825 | ||
|
|
beabe8c33b | ||
|
|
90500519d6 | ||
|
|
06921674a9 | ||
|
|
a91fa9a680 | ||
|
|
ead40dc834 | ||
|
|
2be928b569 | ||
|
|
621ba6d67c | ||
|
|
af929a8787 | ||
|
|
ef986f4256 | ||
|
|
ab36c275cf | ||
|
|
720327bc00 | ||
|
|
679d510059 | ||
|
|
0c2b437643 | ||
|
|
0764cf0c9c | ||
|
|
557a1ed879 | ||
|
|
c28b6a3ee6 | ||
|
|
dd22e2aea9 | ||
|
|
7f3ea15d80 | ||
|
|
d3dfdd214f | ||
|
|
b6c3cf4eee | ||
|
|
157ef1d395 | ||
|
|
d0263f563a | ||
|
|
83b48bb25f | ||
|
|
81e9eca256 | ||
|
|
44c2d585b8 | ||
|
|
348803af7d | ||
|
|
c8bfea7aa1 | ||
|
|
8f47e885f0 | ||
|
|
a9f50f1f7a | ||
|
|
0d58e5365d | ||
|
|
d00d4c4475 | ||
|
|
a6e7c38236 | ||
|
|
eee7e59265 | ||
|
|
c2cb1ffe9e | ||
|
|
d918a77d34 | ||
|
|
2285ef3824 | ||
|
|
b2a2bf819d | ||
|
|
dd9433b50e | ||
|
|
67c53e46f9 | ||
|
|
238e7ec351 | ||
|
|
d916659781 | ||
|
|
82c02574f1 | ||
|
|
26e6d2106b | ||
|
|
625ffa2d96 | ||
|
|
dd3eedd510 | ||
|
|
dc3a72cf38 | ||
|
|
b937c19dd4 | ||
|
|
04c3af537c | ||
|
|
cc43f5dcde | ||
|
|
c74d7afce5 | ||
|
|
52e18eb7fb | ||
|
|
c0b5b4b8c1 | ||
|
|
d497e721c9 | ||
|
|
a7fb9a6865 | ||
|
|
2365d9be18 | ||
|
|
41b60bbd6c | ||
|
|
f0d3d011ea | ||
|
|
48e141a42c | ||
|
|
6215b38e64 | ||
|
|
41490f9624 | ||
|
|
45e6e9a7d1 | ||
|
|
9991d6834d | ||
|
|
ddf8c4dd1a | ||
|
|
970072ef65 | ||
|
|
f8321029fc | ||
|
|
f83cab01ec | ||
|
|
8a74770ec1 | ||
|
|
39c503c108 | ||
|
|
fc32b8242b | ||
|
|
7c2b4eb0e7 | ||
|
|
d8b0aea6b7 | ||
|
|
190d8ef8ff | ||
|
|
15e9194b59 | ||
|
|
0257da6cc0 | ||
|
|
907f878c9f | ||
|
|
b2071cdeb5 | ||
|
|
1a292bf8ab | ||
|
|
7e07d63a6c | ||
|
|
824e983372 | ||
|
|
9e5417c6c7 | ||
|
|
e94dae8536 | ||
|
|
0dd163254d | ||
|
|
341ecab41a | ||
|
|
9eac7ed8b9 | ||
|
|
4005eb8fe8 | ||
|
|
1d4ceac2c5 | ||
|
|
a5246a6856 | ||
|
|
11d235d165 | ||
|
|
af00beb772 | ||
|
|
e5cd9354d5 | ||
|
|
6426ab7466 | ||
|
|
b710df6f45 | ||
|
|
50998b0ee9 | ||
|
|
92c2c68c7b | ||
|
|
c2f5b64b5d | ||
|
|
460bf6d8b9 | ||
|
|
a0dff87c86 | ||
|
|
3015b9f120 | ||
|
|
01549e3c91 | ||
|
|
bc48bfc2b6 | ||
|
|
6100258ba2 | ||
|
|
e083bd7920 | ||
|
|
e915546b44 | ||
|
|
b6cfe35940 | ||
|
|
4cd9fd9b15 | ||
|
|
6f8cab0e9d | ||
|
|
6eb9161906 | ||
|
|
d13695f586 | ||
|
|
749919c551 | ||
|
|
58980e0b4a | ||
|
|
5813a5cace | ||
|
|
f88b777fe5 | ||
|
|
a80af681b8 | ||
|
|
94695bb276 | ||
|
|
be36113826 | ||
|
|
5dfbaa53fc | ||
|
|
a13ddcb67b | ||
|
|
d228bae365 | ||
|
|
463f12a3bb | ||
|
|
3f87b130ba | ||
|
|
c17049c6d1 | ||
|
|
f000baf0d6 | ||
|
|
aef4c50155 | ||
|
|
2a1e4b8621 | ||
|
|
cabd18fba0 | ||
|
|
1da4782262 | ||
|
|
8911ed5d9b | ||
|
|
294b659dc1 | ||
|
|
7ad74ad6c3 | ||
|
|
bb777507ce | ||
|
|
1e1d79d4f7 | ||
|
|
a254a4529f | ||
|
|
e7bd691532 | ||
|
|
4e62350232 | ||
|
|
2c883a70e2 | ||
|
|
3dfeb2fd37 | ||
|
|
3ba3e8286f | ||
|
|
fbf4817ef5 | ||
|
|
db43e0669f | ||
|
|
386c77b13d | ||
|
|
e6998dffe8 | ||
|
|
12057c8a30 | ||
|
|
b7c422cb98 | ||
|
|
1c76f6586b | ||
|
|
d43968f7b6 | ||
|
|
26650787e1 | ||
|
|
b4ef072188 | ||
|
|
3858c5282c | ||
|
|
1ff8dad8ec | ||
|
|
d8cb11ec4a | ||
|
|
8796950651 | ||
|
|
c6cef6db52 | ||
|
|
fdea27c04d | ||
|
|
a52f9d6def | ||
|
|
ee272646c9 | ||
|
|
6655177a0b | ||
|
|
cb78f0d10a | ||
|
|
1cb621633c | ||
|
|
ce25efeee7 | ||
|
|
375b554924 | ||
|
|
69eed999bb | ||
|
|
cab5f2bd8d | ||
|
|
35e3c22832 | ||
|
|
92612c2265 | ||
|
|
4e1b46a7ec | ||
|
|
55f7f7d0ee | ||
|
|
442cd4a369 | ||
|
|
53af41e2fa | ||
|
|
c43e1f3d0a | ||
|
|
32e855ad61 | ||
|
|
034a8a5501 | ||
|
|
1e9dbf2df0 | ||
|
|
dce21f06dd | ||
|
|
56c1c4152f | ||
|
|
a9d2fa296e | ||
|
|
5bccb106c2 | ||
|
|
45086487f1 | ||
|
|
65f03121a4 | ||
|
|
09769193d7 | ||
|
|
7f8acf960b | ||
|
|
ee0e026237 | ||
|
|
6bfd581a72 | ||
|
|
7b6f254e64 | ||
|
|
47955cfe62 | ||
|
|
e62ca17f88 | ||
|
|
c24ba58acb | ||
|
|
30987168fb | ||
|
|
93a875bf20 | ||
|
|
aac3bf581a | ||
|
|
869f07521c | ||
|
|
7e392a1186 | ||
|
|
53d87e42a5 | ||
|
|
6757a1b409 | ||
|
|
115738dd2f | ||
|
|
5caa66ffb7 | ||
|
|
7df73c4fd2 | ||
|
|
1ea5a08c8f | ||
|
|
9c669cbe90 | ||
|
|
1a5184bc85 | ||
|
|
8f2ad8f154 | ||
|
|
d6ef39b9a2 | ||
|
|
52f6acd398 | ||
|
|
2f894bb4ef | ||
|
|
2509fe0d17 | ||
|
|
83a5611ce8 | ||
|
|
136c1ccd2c | ||
|
|
16e23b3f9e | ||
|
|
af088d5e11 | ||
|
|
a6e1c5c96a | ||
|
|
3c8c54ed15 | ||
|
|
628aeda7ee | ||
|
|
2669dc269b | ||
|
|
c4d3d72c57 | ||
|
|
cd79159420 | ||
|
|
1bc63eeadb | ||
|
|
071c6c60c0 | ||
|
|
fc24f401b7 | ||
|
|
6c96e51b07 | ||
|
|
e703163bc4 | ||
|
|
ad549cbded | ||
|
|
673beef210 | ||
|
|
55baa1f2e1 | ||
|
|
1d8a23e97b | ||
|
|
422b4b6561 | ||
|
|
27ee8b23fd | ||
|
|
b9847795a7 | ||
|
|
b13f05537b | ||
|
|
757d1916ae | ||
|
|
0834dac6ee | ||
|
|
3c31f72219 | ||
|
|
a0f63160d6 | ||
|
|
c99d85954a | ||
|
|
33f31d06f9 | ||
|
|
bf4b40f17e | ||
|
|
7aba9e3295 | ||
|
|
3080cb7acd | ||
|
|
4b404f0dea | ||
|
|
0c1c0524c7 | ||
|
|
b58ef290dc | ||
|
|
1387fba7f8 | ||
|
|
34b9ec5be2 | ||
|
|
cefdfbd894 | ||
|
|
3676ddbdff | ||
|
|
7c1a0e0c15 | ||
|
|
19bb043a85 | ||
|
|
fecc80b59c | ||
|
|
1648dc36f8 | ||
|
|
a27a2cbf40 | ||
|
|
e418656a04 | ||
|
|
d4ec1afe44 | ||
|
|
420be8fb0f | ||
|
|
9c3629653f | ||
|
|
eb5cf831b1 | ||
|
|
374d97008b | ||
|
|
fecc923c2c | ||
|
|
703ed608c0 | ||
|
|
99f07c7c0a | ||
|
|
51b4d70b8f | ||
|
|
746d12fc43 | ||
|
|
96ce9e10b8 | ||
|
|
3090795351 | ||
|
|
815b54f3df | ||
|
|
9ad27e4371 | ||
|
|
a6e1804474 | ||
|
|
7ae549e253 | ||
|
|
434d8ef0ea | ||
|
|
31a6d73635 | ||
|
|
958ecf2855 | ||
|
|
fb12ad807a | ||
|
|
965c52d369 | ||
|
|
474872563f | ||
|
|
b92e52bf0e | ||
|
|
d226dc3812 | ||
|
|
46e0fde606 | ||
|
|
1e7f525e0e | ||
|
|
d43e0fb9a7 | ||
|
|
6fb6f47fc8 | ||
|
|
0f7d8e04d8 | ||
|
|
c9fca559dc | ||
|
|
b9d1b5d6a3 | ||
|
|
5f75ba46a5 | ||
|
|
2507301983 | ||
|
|
41aeff331d | ||
|
|
3aab48ec16 | ||
|
|
ad0348b85e | ||
|
|
6a134551b9 | ||
|
|
0e1ae6ad11 | ||
|
|
5baf4b4b2e | ||
|
|
63560061e8 | ||
|
|
be721f5797 | ||
|
|
0073bb79a7 | ||
|
|
f59b506674 | ||
|
|
88b4404296 | ||
|
|
e20bc7723a | ||
|
|
7edf8841fb | ||
|
|
6b5b7eab04 | ||
|
|
c775262e9d | ||
|
|
553fde9761 | ||
|
|
f2593dec4b | ||
|
|
ab5a6ed0f1 | ||
|
|
dd3cdc52f5 | ||
|
|
5a3156a8b7 | ||
|
|
a4c2f19155 | ||
|
|
be8fb1e9b8 | ||
|
|
52c97dbf67 | ||
|
|
57ebf26f15 | ||
|
|
32247bc50e | ||
|
|
ad940bc892 | ||
|
|
7d34e7e0f7 | ||
|
|
b2f43076bd | ||
|
|
202e889577 | ||
|
|
a8690c84ab | ||
|
|
35244f4b59 | ||
|
|
503c3ec04d | ||
|
|
4a5a466975 | ||
|
|
e694511da3 | ||
|
|
0a94827b9c | ||
|
|
735cf301a4 | ||
|
|
e8a29f90d1 | ||
|
|
182cc74834 | ||
|
|
7801dd8944 | ||
|
|
38e090f5c1 | ||
|
|
998c382037 | ||
|
|
ac81e71f78 | ||
|
|
de271c9a30 | ||
|
|
bf3cf8bb29 | ||
|
|
63fa5b7f52 | ||
|
|
96add330f5 | ||
|
|
44aa6a891a | ||
|
|
7a30a21405 | ||
|
|
2b3eadcfa4 | ||
|
|
352443d5a5 | ||
|
|
3574fde770 | ||
|
|
793689789c | ||
|
|
120396fa40 | ||
|
|
d61ec38974 | ||
|
|
2a463baed0 | ||
|
|
348acde6bd | ||
|
|
5ba793842b | ||
|
|
149b608bfc | ||
|
|
3348ea81f2 | ||
|
|
63e69131bd | ||
|
|
d42a34b0b3 | ||
|
|
5ee10fc669 | ||
|
|
b0a4917ce4 | ||
|
|
47e22d6301 | ||
|
|
b970b60503 | ||
|
|
7406f8165d | ||
|
|
9435e689c3 | ||
|
|
66c947b86b | ||
|
|
ad1af87834 | ||
|
|
68700f8722 | ||
|
|
f76270167c | ||
|
|
2a442c4fbb | ||
|
|
9356dfc404 | ||
|
|
7eb8439047 | ||
|
|
0ccf9ad8fc | ||
|
|
c52978dfa4 | ||
|
|
52dfa54301 | ||
|
|
b6f9e00a9e | ||
|
|
8780aa02d7 | ||
|
|
8d5a39d765 | ||
|
|
446e6a8d62 | ||
|
|
9b1bee99b8 | ||
|
|
77cf0f1719 | ||
|
|
fc1f1366b4 | ||
|
|
6efd1a9dad | ||
|
|
8349ae2bc4 | ||
|
|
7c5c843b5b | ||
|
|
bc11bc4f8d | ||
|
|
be24e4a1f7 | ||
|
|
918ff1d0f4 | ||
|
|
20723613bc | ||
|
|
604aafe15d | ||
|
|
4041ca0f69 | ||
|
|
3526d8b299 | ||
|
|
e8adfa2a88 | ||
|
|
7fab1b85ad | ||
|
|
5aeabdb3d4 | ||
|
|
6f01f846dc | ||
|
|
3c4f6144a0 | ||
|
|
ae71d338d7 | ||
|
|
8b469a2727 | ||
|
|
53813f24f0 | ||
|
|
1fde83f12b | ||
|
|
1f7783224b | ||
|
|
0d04ceda76 | ||
|
|
9396ccf9ff | ||
|
|
5a68639788 | ||
|
|
85df554ec1 | ||
|
|
8776ebfe90 | ||
|
|
83eee03b0f | ||
|
|
d7bba4ebac | ||
|
|
40e2b5b153 | ||
|
|
f7a7313758 | ||
|
|
2d9ce0357f | ||
|
|
0ea05896df | ||
|
|
8c638df147 | ||
|
|
6605ded4c9 | ||
|
|
ba1a9530c8 | ||
|
|
a9fcea369e | ||
|
|
ca2787fbba | ||
|
|
6d2c897dfc | ||
|
|
01f81b2d77 | ||
|
|
8a3c5c63e8 | ||
|
|
b688f47776 | ||
|
|
e126110ae0 | ||
|
|
f98406b080 | ||
|
|
40a2910262 | ||
|
|
ec84077486 | ||
|
|
188f9269b7 | ||
|
|
7ad693f865 | ||
|
|
913e3680f3 | ||
|
|
f3ad6015c6 | ||
|
|
4e694c1824 | ||
|
|
0214cb5b1b | ||
|
|
089d0caa5e | ||
|
|
d0c4413033 | ||
|
|
410fa9871f | ||
|
|
9fd4b215ee | ||
|
|
19aaa8fee5 | ||
|
|
43c1a433aa | ||
|
|
ff8d88b097 | ||
|
|
30525835f3 | ||
|
|
818ca63d35 | ||
|
|
2290c2bb23 | ||
|
|
3fc7c97979 | ||
|
|
b9551a8952 | ||
|
|
e600fcbcc5 |
@@ -22,9 +22,9 @@ stages:
|
||||
|
||||
# Common variables
|
||||
variables:
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dglib:werror=false -Dpango:werror=false -Dgtk-doc:werror=false -Dwayland-protocols:werror=false -Dsysprof:werror=false -Dwayland:werror=false"
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Ddemos=false -Dbuild-examples=false -Dbuild-tests=false -Dbuild-testsuite=true"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v40"
|
||||
FLATPAK_IMAGE: "quay.io/gnome_infrastructure/gnome-runtime-images:gnome-master"
|
||||
@@ -113,7 +113,12 @@ release-build:
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS} _build
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
${BACKEND_FLAGS}
|
||||
${FEATURE_FLAGS}
|
||||
_build
|
||||
- meson compile -C _build
|
||||
- .gitlab-ci/run-tests.sh _build x11
|
||||
|
||||
@@ -201,7 +206,7 @@ macos:
|
||||
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
|
||||
- export MESON_FORCE_BACKTRACE=1
|
||||
script:
|
||||
- meson setup
|
||||
- meson setup ${COMMON_MESON_FLAGS}
|
||||
-Dx11-backend=false
|
||||
-Dbroadway-backend=true
|
||||
-Dmacos-backend=true
|
||||
@@ -210,6 +215,10 @@ macos:
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
-Dlibjpeg-turbo:simd=disabled
|
||||
-Ddemos=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-testsuite=false
|
||||
_build
|
||||
- meson compile -C _build
|
||||
artifacts:
|
||||
@@ -338,7 +347,10 @@ static-scan:
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} _scan_build
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
_scan_build
|
||||
- ninja -C _scan_build scan-build
|
||||
artifacts:
|
||||
paths:
|
||||
@@ -352,6 +364,7 @@ asan-build:
|
||||
tags: [ asan ]
|
||||
stage: analysis
|
||||
needs: []
|
||||
when: manual
|
||||
variables:
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
@@ -368,12 +381,22 @@ reference:
|
||||
image: $FEDORA_IMAGE
|
||||
stage: docs
|
||||
needs: []
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release --force-fallback-for=gdk-pixbuf,pango"
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson setup ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} -Dgtk_doc=true -Dgdk-pixbuf:gtk_doc=true -Dpango:gtk_doc=true _build
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
--buildtype=release
|
||||
--force-fallback-for=gdk-pixbuf,pango
|
||||
-Dintrospection=enabled
|
||||
-Dgtk_doc=true
|
||||
-Dgdk-pixbuf:gtk_doc=true
|
||||
-Dpango:gtk_doc=true
|
||||
-Ddemos=false
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-tests=false
|
||||
-Dbuild-testsuite=false
|
||||
_build
|
||||
- meson compile -C _build
|
||||
- mkdir -p _reference/
|
||||
- mv _build/docs/reference/gdk/gdk4/ _reference/gdk4/
|
||||
|
||||
@@ -21,7 +21,7 @@ many things that we value:
|
||||
Please, do not use the issue tracker for support questions. If you have
|
||||
questions on how to use GTK effectively, you can use:
|
||||
|
||||
- the `#gtk` IRC channel on irc.gnome.org
|
||||
- the `gtk` [room on matrix](https://matrix.to/#/#gtk:gnome.org)
|
||||
- the [gtk tag on the GNOME Discourse instance](https://discourse.gnome.org/tag/gtk)
|
||||
|
||||
You can also look at the GTK tag on [Stack
|
||||
@@ -44,6 +44,7 @@ If you're reporting a bug make sure to list:
|
||||
|
||||
0. which version of GTK are you using?
|
||||
0. which operating system are you using?
|
||||
0. what display and graphics driver are you using?
|
||||
0. the necessary steps to reproduce the issue
|
||||
0. the expected outcome
|
||||
0. a description of the behavior; screenshots are also welcome
|
||||
|
||||
98
NEWS
98
NEWS
@@ -1,3 +1,101 @@
|
||||
Overview of Changes in 4.9.4, xx-xx-xxxx
|
||||
========================================
|
||||
|
||||
* Printing:
|
||||
- Add a CPDB print backend
|
||||
|
||||
* GtkFileDialog:
|
||||
- Robustness fixes
|
||||
|
||||
* GtkScaleButton:
|
||||
- Add an 'active' property
|
||||
|
||||
* Fix conflicting type names between gtk and gio
|
||||
|
||||
* Gsk:
|
||||
- Settable filtering for scaled textures
|
||||
- Add mask nodes
|
||||
|
||||
* Wayland:
|
||||
- Handle dispatch failing in more places
|
||||
|
||||
* Translation updates:
|
||||
Belarusian
|
||||
Chinese (Taiwan)
|
||||
Georgian
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.9.3, 04-02-2023
|
||||
========================================
|
||||
|
||||
* Add GtkUriLauncher, as replacement for gtk_show_uri
|
||||
|
||||
* Add GdkMonitor::description
|
||||
|
||||
* Fix problems with tooltip sizing
|
||||
|
||||
* Deprecations:
|
||||
- GtkStatusbar
|
||||
- GtkAssistant
|
||||
- GtkLockButton
|
||||
- gtk_gesture_set_sequence_state
|
||||
|
||||
* GtkColumnView:
|
||||
- Only create widgets for visible columns
|
||||
|
||||
* GtkFileDialog:
|
||||
- Drop shortcut folders API
|
||||
|
||||
* GtkCalendar:
|
||||
- Make marked days work again
|
||||
|
||||
* GtkSwitch:
|
||||
- Make state and active independently settable
|
||||
|
||||
* GtkFileChooser:
|
||||
- Fix a crash with DND
|
||||
- Fix excessively wide sidebar
|
||||
- Make context menus work again
|
||||
|
||||
* Accessibility:
|
||||
- Make GtkAccessible public, so it can be implemented outside GTK
|
||||
- Support accessible implementation for editables
|
||||
|
||||
* CSS:
|
||||
- Fix randomly stopping CSS animations
|
||||
|
||||
* GL:
|
||||
- Fix synchronization with GStreamer
|
||||
- Fix problems with 3rd party GL in the same thread
|
||||
|
||||
* Wayland:
|
||||
- Fix startup notification with xdg_activation
|
||||
|
||||
* Broadway:
|
||||
- Implement modal windows
|
||||
|
||||
* macOS:
|
||||
- Make DND work
|
||||
|
||||
* Build:
|
||||
- Require graphene 1.10
|
||||
- Require gobject-introspection 1.72
|
||||
|
||||
* Translation updates
|
||||
Catalan
|
||||
Galician
|
||||
German
|
||||
Hebrew
|
||||
Indonesian
|
||||
Portuguese
|
||||
Russian
|
||||
Spanish
|
||||
Swedish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.9.2, 26-12-2022
|
||||
========================================
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
typedef GtkApplication DemoApplication;
|
||||
typedef GtkApplicationClass DemoApplicationClass;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static GtkWidget *progress_bar = NULL;
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -37,6 +37,8 @@ remove_timeout (gpointer data)
|
||||
g_source_remove (id);
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static gboolean
|
||||
pop_status (gpointer data)
|
||||
{
|
||||
@@ -57,6 +59,8 @@ status_message (GtkStatusbar *status,
|
||||
g_object_set_data_full (G_OBJECT (status), "timeout", GUINT_TO_POINTER (id), remove_timeout);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
static void
|
||||
help_activate (GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
|
||||
@@ -215,6 +215,12 @@
|
||||
<file>demo3widget.h</file>
|
||||
<file>demo3widget.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/mask">
|
||||
<file>demo4widget.c</file>
|
||||
<file>demo4widget.h</file>
|
||||
<file>hsla.h</file>
|
||||
<file>hsla.c</file>
|
||||
</gresource>
|
||||
<gresource prefix="/paintable_svg">
|
||||
<file>svgpaintable.h</file>
|
||||
<file>svgpaintable.c</file>
|
||||
@@ -311,6 +317,7 @@
|
||||
<file>list_store.c</file>
|
||||
<file>main.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>mask.c</file>
|
||||
<file>menu.c</file>
|
||||
<file>overlay.c</file>
|
||||
<file>overlay_decorative.c</file>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_PAINTABLE = 1,
|
||||
PROP_TEXTURE = 1,
|
||||
PROP_FILTER,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
@@ -11,8 +12,9 @@ struct _Demo3Widget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GdkPaintable *paintable;
|
||||
GdkTexture *texture;
|
||||
float scale;
|
||||
GskScalingFilter filter;
|
||||
|
||||
GtkWidget *menu;
|
||||
};
|
||||
@@ -28,6 +30,7 @@ static void
|
||||
demo3_widget_init (Demo3Widget *self)
|
||||
{
|
||||
self->scale = 1.f;
|
||||
self->filter = GSK_SCALING_FILTER_LINEAR;
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
@@ -36,7 +39,7 @@ demo3_widget_dispose (GObject *object)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (object);
|
||||
|
||||
g_clear_object (&self->paintable);
|
||||
g_clear_object (&self->texture);
|
||||
|
||||
gtk_widget_dispose_template (GTK_WIDGET (self), DEMO3_TYPE_WIDGET);
|
||||
|
||||
@@ -50,12 +53,13 @@ demo3_widget_snapshot (GtkWidget *widget,
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int x, y, width, height;
|
||||
double w, h;
|
||||
GskRenderNode *node;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
w = self->scale * gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
h = self->scale * gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
w = self->scale * gdk_texture_get_width (self->texture);
|
||||
h = self->scale * gdk_texture_get_height (self->texture);
|
||||
|
||||
x = MAX (0, (width - ceil (w)) / 2);
|
||||
y = MAX (0, (height - ceil (h)) / 2);
|
||||
@@ -63,7 +67,11 @@ demo3_widget_snapshot (GtkWidget *widget,
|
||||
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gdk_paintable_snapshot (self->paintable, snapshot, w, h);
|
||||
node = gsk_texture_scale_node_new (self->texture,
|
||||
&GRAPHENE_RECT_INIT (0, 0, w, h),
|
||||
self->filter);
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
@@ -81,9 +89,9 @@ demo3_widget_measure (GtkWidget *widget,
|
||||
int size;
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
size = gdk_paintable_get_intrinsic_width (self->paintable);
|
||||
size = gdk_texture_get_width (self->texture);
|
||||
else
|
||||
size = gdk_paintable_get_intrinsic_height (self->paintable);
|
||||
size = gdk_texture_get_height (self->texture);
|
||||
|
||||
*minimum = *natural = self->scale * size;
|
||||
}
|
||||
@@ -113,9 +121,9 @@ demo3_widget_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_clear_object (&self->paintable);
|
||||
self->paintable = g_value_dup_object (value);
|
||||
case PROP_TEXTURE:
|
||||
g_clear_object (&self->texture);
|
||||
self->texture = g_value_dup_object (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
@@ -124,6 +132,11 @@ demo3_widget_set_property (GObject *object,
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
case PROP_FILTER:
|
||||
self->filter = g_value_get_enum (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -140,14 +153,18 @@ demo3_widget_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PAINTABLE:
|
||||
g_value_set_object (value, self->paintable);
|
||||
case PROP_TEXTURE:
|
||||
g_value_set_object (value, self->texture);
|
||||
break;
|
||||
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, self->scale);
|
||||
break;
|
||||
|
||||
case PROP_FILTER:
|
||||
g_value_set_enum (value, self->filter);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -205,16 +222,21 @@ demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
widget_class->measure = demo3_widget_measure;
|
||||
widget_class->size_allocate = demo3_widget_size_allocate;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_PAINTABLE,
|
||||
g_param_spec_object ("paintable", "Paintable", "Paintable",
|
||||
GDK_TYPE_PAINTABLE,
|
||||
g_object_class_install_property (object_class, PROP_TEXTURE,
|
||||
g_param_spec_object ("texture", NULL, NULL,
|
||||
GDK_TYPE_TEXTURE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE,
|
||||
g_param_spec_float ("scale", "Scale", "Scale",
|
||||
g_param_spec_float ("scale", NULL, NULL,
|
||||
0.0, 10.0, 1.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FILTER,
|
||||
g_param_spec_enum ("filter", NULL, NULL,
|
||||
GSK_TYPE_SCALING_FILTER, GSK_SCALING_FILTER_LINEAR,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
/* These are the actions that we are using in the menu */
|
||||
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
|
||||
@@ -229,16 +251,13 @@ GtkWidget *
|
||||
demo3_widget_new (const char *resource)
|
||||
{
|
||||
Demo3Widget *self;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPaintable *paintable;
|
||||
GdkTexture *texture;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_resource (resource, NULL);
|
||||
paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
|
||||
texture = gdk_texture_new_from_resource (resource);
|
||||
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "paintable", paintable, NULL);
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "texture", texture, NULL);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
g_object_unref (paintable);
|
||||
g_object_unref (texture);
|
||||
|
||||
return GTK_WIDGET (self);
|
||||
}
|
||||
|
||||
123
demos/gtk-demo/demo4widget.c
Normal file
123
demos/gtk-demo/demo4widget.c
Normal file
@@ -0,0 +1,123 @@
|
||||
#include <math.h>
|
||||
#include "demo4widget.h"
|
||||
#include "hsla.h"
|
||||
|
||||
struct _Demo4Widget
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
PangoLayout *layout;
|
||||
GskColorStop stops[8];
|
||||
gsize n_stops;
|
||||
|
||||
guint tick;
|
||||
};
|
||||
|
||||
struct _Demo4WidgetClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (Demo4Widget, demo4_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
rotate_color (GdkRGBA *rgba)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
_gdk_hsla_init_from_rgba (&hsla, rgba);
|
||||
hsla.hue -= 1;
|
||||
_gdk_rgba_init_from_hsla (rgba, &hsla);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rotate_colors (GtkWidget *widget,
|
||||
GdkFrameClock *clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (widget);
|
||||
|
||||
for (unsigned int i = 0; i < self->n_stops; i++)
|
||||
rotate_color (&self->stops[i].color);
|
||||
|
||||
gtk_widget_queue_draw (widget);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_init (Demo4Widget *self)
|
||||
{
|
||||
PangoFontDescription *desc;
|
||||
|
||||
self->n_stops = 8;
|
||||
self->stops[0].offset = 0;
|
||||
self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
|
||||
|
||||
for (unsigned int i = 1; i < self->n_stops; i++)
|
||||
{
|
||||
GdkHSLA hsla;
|
||||
|
||||
self->stops[i].offset = i / (double)(self->n_stops - 1);
|
||||
_gdk_hsla_init_from_rgba (&hsla, &self->stops[i - 1].color);
|
||||
hsla.hue += 360.0 / (double)(self->n_stops - 1);
|
||||
_gdk_rgba_init_from_hsla (&self->stops[i].color, &hsla);
|
||||
}
|
||||
|
||||
self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "123");
|
||||
desc = pango_font_description_from_string ("Cantarell Bold 210");
|
||||
pango_layout_set_font_description (self->layout, desc);
|
||||
pango_font_description_free (desc);
|
||||
|
||||
self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), rotate_colors, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_dispose (GObject *object)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (object);
|
||||
|
||||
g_clear_object (&self->layout);
|
||||
gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick);
|
||||
|
||||
G_OBJECT_CLASS (demo4_widget_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
Demo4Widget *self = DEMO4_WIDGET (widget);
|
||||
int width, height;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
gtk_snapshot_push_mask (snapshot);
|
||||
gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
|
||||
gtk_snapshot_pop (snapshot);
|
||||
|
||||
gtk_snapshot_append_linear_gradient (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height),
|
||||
&GRAPHENE_POINT_INIT (0, 0),
|
||||
&GRAPHENE_POINT_INIT (width, height),
|
||||
self->stops,
|
||||
self->n_stops);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
demo4_widget_class_init (Demo4WidgetClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
object_class->dispose = demo4_widget_dispose;
|
||||
|
||||
widget_class->snapshot = demo4_widget_snapshot;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
demo4_widget_new (void)
|
||||
{
|
||||
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
|
||||
}
|
||||
8
demos/gtk-demo/demo4widget.h
Normal file
8
demos/gtk-demo/demo4widget.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define DEMO4_TYPE_WIDGET (demo4_widget_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (Demo4Widget, demo4_widget, DEMO4, WIDGET, GtkWidget)
|
||||
|
||||
GtkWidget * demo4_widget_new (void);
|
||||
@@ -362,7 +362,7 @@ do_drawingarea (GtkWidget *do_widget)
|
||||
G_CALLBACK (scribble_resize), NULL);
|
||||
|
||||
drag = gtk_gesture_drag_new ();
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), GDK_BUTTON_PRIMARY);
|
||||
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (drag), 0);
|
||||
gtk_widget_add_controller (da, GTK_EVENT_CONTROLLER (drag));
|
||||
|
||||
g_signal_connect (drag, "drag-begin", G_CALLBACK (drag_begin), da);
|
||||
|
||||
146
demos/gtk-demo/hsla.c
Normal file
146
demos/gtk-demo/hsla.c
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include "hsla.h"
|
||||
|
||||
void
|
||||
_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
float min;
|
||||
float max;
|
||||
float red;
|
||||
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
|
||||
min = blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (green > blue)
|
||||
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;
|
||||
else if (green == max)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
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)
|
||||
{
|
||||
rgba->red = lightness;
|
||||
rgba->green = lightness;
|
||||
rgba->blue = lightness;
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = hsla->hue + 120;
|
||||
while (hue > 360)
|
||||
hue -= 360;
|
||||
while (hue < 0)
|
||||
hue += 360;
|
||||
|
||||
if (hue < 60)
|
||||
rgba->red = m1 + (m2 - m1) * hue / 60;
|
||||
else if (hue < 180)
|
||||
rgba->red = m2;
|
||||
else if (hue < 240)
|
||||
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)
|
||||
rgba->green = m2;
|
||||
else if (hue < 240)
|
||||
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)
|
||||
rgba->blue = m2;
|
||||
else if (hue < 240)
|
||||
rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
|
||||
else
|
||||
rgba->blue = m1;
|
||||
}
|
||||
}
|
||||
15
demos/gtk-demo/hsla.h
Normal file
15
demos/gtk-demo/hsla.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct _GdkHSLA GdkHSLA;
|
||||
|
||||
struct _GdkHSLA {
|
||||
float hue;
|
||||
float saturation;
|
||||
float lightness;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
|
||||
const GdkRGBA *rgba);
|
||||
void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
|
||||
const GdkHSLA *hsla);
|
||||
46
demos/gtk-demo/mask.c
Normal file
46
demos/gtk-demo/mask.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Masking
|
||||
*
|
||||
* Demonstrates mask nodes.
|
||||
*
|
||||
* This demo uses a text node as mask for
|
||||
* an animated linear gradient.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo4widget.h"
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_mask (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *widget;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Mask Nodes");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
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);
|
||||
|
||||
widget = demo4_widget_new ();
|
||||
gtk_widget_set_hexpand (widget, TRUE);
|
||||
gtk_widget_set_vexpand (widget, TRUE);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), widget);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
@@ -22,9 +22,11 @@ do_menu (GtkWidget *do_widget)
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *dropdown;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
@@ -43,10 +45,19 @@ do_menu (GtkWidget *do_widget)
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), box2);
|
||||
|
||||
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);
|
||||
gtk_widget_set_hexpand (scale, TRUE);
|
||||
gtk_box_append (GTK_BOX (box2), scale);
|
||||
|
||||
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
|
||||
gtk_box_append (GTK_BOX (box2), dropdown);
|
||||
|
||||
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
|
||||
|
||||
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
@@ -46,6 +46,7 @@ demos = files([
|
||||
'links.c',
|
||||
'listbox.c',
|
||||
'listbox_controls.c',
|
||||
'mask.c',
|
||||
'menu.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
@@ -114,6 +115,7 @@ extra_demo_sources = files([
|
||||
'gtkshadertoy.c',
|
||||
'gtkshaderstack.c',
|
||||
'gskshaderpaintable.c',
|
||||
'hsla.c',
|
||||
'puzzlepiece.c',
|
||||
'bluroverlay.c',
|
||||
'demoimage.c',
|
||||
@@ -126,6 +128,7 @@ extra_demo_sources = files([
|
||||
'four_point_transform.c',
|
||||
'demo2widget.c',
|
||||
'demo3widget.c',
|
||||
'demo4widget.c',
|
||||
'pixbufpaintable.c',
|
||||
'script-names.c',
|
||||
'unicode-names.c',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* Pickers
|
||||
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog
|
||||
/* Pickers and Launchers
|
||||
* #Keywords: GtkColorDialog, GtkFontDialog, GtkFileDialog, GtkFileLauncher, GtkUriLauncher
|
||||
*
|
||||
* These widgets are mainly intended for use in preference dialogs.
|
||||
* The dialogs are mainly intended for use in preference dialogs.
|
||||
* They allow to select colors, fonts and applications.
|
||||
*
|
||||
* This demo shows both the default appearance for these dialogs,
|
||||
* as well as some of the customizations that are possible.
|
||||
* The launchers let you open files or URIs in applications that
|
||||
* can handle them.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -73,9 +73,9 @@ open_file (GtkButton *picker,
|
||||
}
|
||||
|
||||
static void
|
||||
launch_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
open_app_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileLauncher *launcher = GTK_FILE_LAUNCHER (source);
|
||||
GError *error = NULL;
|
||||
@@ -97,7 +97,35 @@ open_app (GtkButton *picker)
|
||||
file = G_FILE (g_object_get_data (G_OBJECT (picker), "file"));
|
||||
launcher = gtk_file_launcher_new (file);
|
||||
|
||||
gtk_file_launcher_launch (launcher, parent, NULL, launch_done, NULL);
|
||||
gtk_file_launcher_launch (launcher, parent, NULL, open_app_done, NULL);
|
||||
|
||||
g_object_unref (launcher);
|
||||
}
|
||||
|
||||
static void
|
||||
open_uri_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkUriLauncher *launcher = GTK_URI_LAUNCHER (source);
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gtk_uri_launcher_launch_finish (launcher, result, &error))
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
launch_uri (GtkButton *picker)
|
||||
{
|
||||
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (picker)));
|
||||
GtkUriLauncher *launcher;
|
||||
|
||||
launcher = gtk_uri_launcher_new ("http://www.gtk.org");
|
||||
|
||||
gtk_uri_launcher_launch (launcher, parent, NULL, open_uri_done, NULL);
|
||||
|
||||
g_object_unref (launcher);
|
||||
}
|
||||
@@ -113,7 +141,7 @@ do_pickers (GtkWidget *do_widget)
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Pickers");
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Pickers and Launchers");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
table = gtk_grid_new ();
|
||||
@@ -121,8 +149,8 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_widget_set_margin_end (table, 20);
|
||||
gtk_widget_set_margin_top (table, 20);
|
||||
gtk_widget_set_margin_bottom (table, 20);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (table), 3);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (table), 10);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (table), 6);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (table), 6);
|
||||
gtk_window_set_child (GTK_WINDOW (window), table);
|
||||
|
||||
label = gtk_label_new ("Color:");
|
||||
@@ -149,7 +177,7 @@ do_pickers (GtkWidget *do_widget)
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 2, 1, 1);
|
||||
|
||||
picker = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
picker = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
button = gtk_button_new_from_icon_name ("document-open-symbolic");
|
||||
label = gtk_label_new ("None");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.);
|
||||
@@ -158,19 +186,23 @@ do_pickers (GtkWidget *do_widget)
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_file), label);
|
||||
gtk_box_append (GTK_BOX (picker), label);
|
||||
gtk_box_append (GTK_BOX (picker), button);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("Application:");
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 4, 1, 1);
|
||||
|
||||
app_picker = gtk_button_new_from_icon_name ("emblem-system-symbolic");
|
||||
gtk_widget_set_halign (app_picker, GTK_ALIGN_END);
|
||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||
g_signal_connect (app_picker, "clicked", G_CALLBACK (open_app), NULL);
|
||||
gtk_grid_attach (GTK_GRID (table), app_picker, 1, 4, 1, 1);
|
||||
gtk_box_append (GTK_BOX (picker), app_picker);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 2, 1, 1);
|
||||
|
||||
|
||||
label = gtk_label_new ("URI:");
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_CENTER);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (table), label, 0, 3, 1, 1);
|
||||
|
||||
picker = gtk_button_new_with_label ("www.gtk.org");
|
||||
g_signal_connect (picker, "clicked", G_CALLBACK (launch_uri), NULL);
|
||||
gtk_grid_attach (GTK_GRID (table), picker, 1, 3, 1, 1);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -297,6 +297,21 @@ The default texture is a 10x10 checkerboard with the top left and bottom right
|
||||
representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
|
||||
`.
|
||||
|
||||
### texture-scale
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| texture | `<url>` | *see below* | always |
|
||||
| filter | `filter` | *see below* | non-default |
|
||||
|
||||
Creates a node like `gsk_texture_scale_node_new()` with the given properties.
|
||||
|
||||
The default texture is a 10x10 checkerboard, just like for texture.
|
||||
|
||||
The possible filter values are `linear`, `nearest` and `trilinear`, with
|
||||
`linear` being the default.
|
||||
|
||||
### transform
|
||||
|
||||
| property | syntax | default | printed |
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include "demo_conf.h"
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
static GtkWidget *main_window;
|
||||
static GFile *filename = NULL;
|
||||
static GtkPageSetup *page_setup = NULL;
|
||||
|
||||
@@ -2056,6 +2056,67 @@ hide_widget (GtkWidget *widget)
|
||||
gtk_widget_set_visible (widget, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
load_texture_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const char *resource_path = (const char *) task_data;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
bytes = g_resources_lookup_data (resource_path, 0, &error);
|
||||
if (!bytes)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_from_bytes (bytes, &error);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
if (!texture)
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_pointer (task, texture, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
load_texture_done (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *picture = GTK_WIDGET (source);
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
texture = g_task_propagate_pointer (G_TASK (result), &error);
|
||||
if (!texture)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
load_texture_in_thread (GtkWidget *picture,
|
||||
const char *resource_path)
|
||||
{
|
||||
GTask *task = g_task_new (picture, NULL, load_texture_done, NULL);
|
||||
g_task_set_task_data (task, (gpointer)resource_path, NULL);
|
||||
g_task_run_in_thread (task, load_texture_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
activate (GApplication *app)
|
||||
{
|
||||
@@ -2155,6 +2216,13 @@ activate (GApplication *app)
|
||||
|
||||
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
|
||||
|
||||
load_texture_in_thread ((GtkWidget *)gtk_builder_get_object (builder, "notebook_sunset"),
|
||||
"/org/gtk/WidgetFactory4/sunset.jpg");
|
||||
load_texture_in_thread ((GtkWidget *)gtk_builder_get_object (builder, "notebook_nyc"),
|
||||
"/org/gtk/WidgetFactory4/nyc.jpg");
|
||||
load_texture_in_thread ((GtkWidget *)gtk_builder_get_object (builder, "notebook_beach"),
|
||||
"/org/gtk/WidgetFactory4/beach.jpg");
|
||||
|
||||
if (g_strcmp0 (PROFILE, "devel") == 0)
|
||||
gtk_widget_add_css_class (GTK_WIDGET (window), "devel");
|
||||
|
||||
@@ -2184,11 +2252,13 @@ activate (GApplication *app)
|
||||
for (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_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "statusbar");
|
||||
gtk_statusbar_push (GTK_STATUSBAR (widget), 0, "All systems are operating normally.");
|
||||
action = G_ACTION (g_property_action_new ("statusbar", widget, "visible"));
|
||||
g_action_map_add_action (G_ACTION_MAP (window), action);
|
||||
g_object_unref (G_OBJECT (action));
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "toolbar");
|
||||
action = G_ACTION (g_property_action_new ("toolbar", widget, "visible"));
|
||||
@@ -2362,6 +2432,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "record_button");
|
||||
g_object_set_data (G_OBJECT (window), "record_button", widget);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "lockbox");
|
||||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "lockbutton");
|
||||
g_object_set_data (G_OBJECT (window), "lockbutton", widget2);
|
||||
@@ -2379,6 +2450,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
G_BINDING_SYNC_CREATE);
|
||||
gtk_lock_button_set_permission (GTK_LOCK_BUTTON (widget2), permission);
|
||||
g_object_unref (permission);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
widget = (GtkWidget *)gtk_builder_get_object (builder, "iconview1");
|
||||
widget2 = (GtkWidget *)gtk_builder_get_object (builder, "increase_button");
|
||||
|
||||
@@ -1263,8 +1263,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/sunset.jpg</property>
|
||||
<object class="GtkPicture" id="notebook_sunset">
|
||||
<property name="content-fit">cover</property>
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
@@ -1290,8 +1289,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/nyc.jpg</property>
|
||||
<object class="GtkPicture" id="notebook_nyc">
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
@@ -1316,8 +1314,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/beach.jpg</property>
|
||||
<object class="GtkPicture" id="notebook_beach">
|
||||
<child>
|
||||
<object class="GtkDragSource">
|
||||
<signal name="prepare" handler="on_picture_drag_prepare" swapped="no"/>
|
||||
|
||||
@@ -18,12 +18,12 @@ search_index = true
|
||||
docs_url = "https://docs.gtk.org/gobject/"
|
||||
|
||||
[dependencies."Gio-2.0"]
|
||||
name = "GIO"
|
||||
name = "Gio"
|
||||
description = "GObject Interfaces and Objects, Networking, IPC, and I/O"
|
||||
docs_url = "https://docs.gtk.org/gio/"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "Cairo"
|
||||
name = "cairo"
|
||||
description = "A 2D graphics library with support for multiple output devices"
|
||||
docs_url = "https://www.cairographics.org/manual/"
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ dependencies = ["Graphene-1.0", "Gdk-4.0"]
|
||||
docs_url = "https://ebassi.github.io/graphene/docs/"
|
||||
|
||||
[dependencies."Gdk-4.0"]
|
||||
name = "GDK"
|
||||
name = "Gdk"
|
||||
description = "The GTK windowing system abstraction"
|
||||
docs_url = "https://docs.gtk.org/gdk4/"
|
||||
|
||||
|
||||
@@ -236,23 +236,17 @@ By default, GTK will try to build with support for the Vulkan graphics
|
||||
API in addition to cairo and OpenGL. This option can be used to explicitly
|
||||
control whether Vulkan should be used.
|
||||
|
||||
### `xinerama`
|
||||
|
||||
By default, GTK will try to link against the Xinerama libraries
|
||||
if they are found. This option can be used to explicitly control
|
||||
whether Xinerama should be used.
|
||||
|
||||
### `media`
|
||||
### `media-gstreamer` and `media-ffmpeg`
|
||||
|
||||
By default, GTK will try to build the gstreamer backend for
|
||||
media playback support. This option can be used to explicitly
|
||||
media playback support. These option can be used to explicitly
|
||||
control which media backends should be built.
|
||||
|
||||
### `print`
|
||||
### `print-cups`
|
||||
|
||||
By default, GTK will try to build various print backends
|
||||
if their dependencies are found. This option can be used
|
||||
to explicitly control which print backends should be built.
|
||||
to explicitly control whether the cups print backend should be built.
|
||||
|
||||
### `cloudproviders`
|
||||
|
||||
@@ -274,18 +268,13 @@ support in the file chooser.
|
||||
This option controls whether GTK should use colord for color
|
||||
calibration support in the cups print backend.
|
||||
|
||||
### `gtk_doc` and `man-pages`
|
||||
### `gtk_doc`, `man-pages` and `update_screenshots`
|
||||
|
||||
The *gtk-doc* package is used to generate the reference documentation
|
||||
included with GTK. By default support for *gtk-doc* is disabled
|
||||
The *gi-docgen* package is used to generate the reference documentation
|
||||
included with GTK. By default support for *gi-docgen* is disabled
|
||||
because it requires various extra dependencies to be installed.
|
||||
If you have *gtk-doc* and *pandoc* installed and are modifying GTK,
|
||||
you may want to enable *gtk-doc* support by passing in `-Dgtk_doc=true`.
|
||||
|
||||
Additionally, some tools provided by GTK have their own
|
||||
manual pages generated using a similar set of dependencies;
|
||||
if you have *xsltproc* then you can generate manual pages by
|
||||
passing `-Dman-pages=true` when configuring the build.
|
||||
Introspection needs to be enabled, since the documentation is generated
|
||||
from introspection data.
|
||||
|
||||
### `introspection`
|
||||
|
||||
@@ -294,9 +283,14 @@ is mainly useful for shortening turnaround times on developer
|
||||
systems. Installed builds of GTK should always have introspection
|
||||
support.
|
||||
|
||||
### `build-tests`, `demos`
|
||||
### `build-testsuite`
|
||||
|
||||
By default, GTK will build quite a few tests and demos.
|
||||
If you want to run the testsuite to ensure that your GTK build
|
||||
works, you should enable it with this option.
|
||||
|
||||
### `build-tests`, `build-examples`, `demos`
|
||||
|
||||
By default, GTK will build quite a few tests, examples and demos.
|
||||
While these are useful on a developer system, they are not
|
||||
needed when GTK is built e.g. for a flatpak runtime. These
|
||||
options allow to disable building tests and demos.
|
||||
|
||||
@@ -377,7 +377,7 @@ demonstrates input event handling with event controllers.
|
||||
|
||||
### Drawing in response to input
|
||||
|
||||
Create a new file with the following content named `example-4.c`.
|
||||
Create a new file with the following content named `example-3.c`.
|
||||
|
||||
```c
|
||||
#include <gtk/gtk.h>
|
||||
@@ -572,7 +572,7 @@ main (int argc,
|
||||
You can compile the program above with GCC using:
|
||||
|
||||
```
|
||||
gcc $( pkg-config --cflags gtk4 ) -o example-4 example-4.c $( pkg-config --libs gtk4 )
|
||||
gcc $( pkg-config --cflags gtk4 ) -o example-3 example-3.c $( pkg-config --libs gtk4 )
|
||||
```
|
||||
|
||||
## Building user interfaces
|
||||
@@ -587,7 +587,7 @@ XML format that can be parsed by the [class@Gtk.Builder] class.
|
||||
|
||||
### Packing buttons with GtkBuilder
|
||||
|
||||
Create a new file with the following content named `example-3.c`.
|
||||
Create a new file with the following content named `example-4.c`.
|
||||
|
||||
```c
|
||||
#include <gtk/gtk.h>
|
||||
@@ -697,7 +697,7 @@ Create a new file with the following content named `builder.ui`.
|
||||
You can compile the program above with GCC using:
|
||||
|
||||
```
|
||||
gcc $( pkg-config --cflags gtk4 ) -o example-3 example-3.c $( pkg-config --libs gtk4 )
|
||||
gcc $( pkg-config --cflags gtk4 ) -o example-4 example-4.c $( pkg-config --libs gtk4 )
|
||||
```
|
||||
|
||||
Note that `GtkBuilder` can also be used to construct objects that are
|
||||
|
||||
@@ -14,12 +14,12 @@ search_index = true
|
||||
dependencies = ["Gdk-4.0", "Gsk-4.0"]
|
||||
|
||||
[dependencies."Gdk-4.0"]
|
||||
name = "GDK"
|
||||
name = "Gdk"
|
||||
description = "The GTK windowing system abstraction"
|
||||
docs_url = "https://docs.gtk.org/gdk4/"
|
||||
|
||||
[dependencies."Gsk-4.0"]
|
||||
name = "GSK"
|
||||
name = "Gsk"
|
||||
description = "The GTK rendering abstraction"
|
||||
docs_url = "https://docs.gtk.org/gsk4/"
|
||||
|
||||
|
||||
@@ -105,3 +105,17 @@ retire it. If you need such a widget, it is relatively trivial to create one
|
||||
using a [class@Gtk.Revealer] with labels and buttons.
|
||||
|
||||
Other libraries, such as libadwaita, may provide replacements as well.
|
||||
|
||||
## gtk_show_uri is being replaced
|
||||
|
||||
Instead of gtk_show_uri(), you should use GtkUriLauncher or GtkFileLauncher.
|
||||
|
||||
## GtkStatusbar is going away
|
||||
|
||||
This is an oldfashioned widget that does not do all that much anymore, since
|
||||
it no longer has a resize handle for the window.
|
||||
|
||||
## GtkLockButton and GtkVolumeButton are going away
|
||||
|
||||
These are very specialized widgets that should better live with the application
|
||||
where they are used.
|
||||
|
||||
@@ -37,7 +37,7 @@ main (int argc,
|
||||
GtkApplication *app;
|
||||
int status;
|
||||
|
||||
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
|
||||
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
|
||||
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
|
||||
status = g_application_run (G_APPLICATION (app), argc, argv);
|
||||
g_object_unref (app);
|
||||
|
||||
@@ -213,6 +213,7 @@ typedef enum {
|
||||
BROADWAY_REQUEST_RELEASE_TEXTURE,
|
||||
BROADWAY_REQUEST_SET_NODES,
|
||||
BROADWAY_REQUEST_ROUNDTRIP,
|
||||
BROADWAY_REQUEST_SET_MODAL_HINT,
|
||||
} BroadwayRequestType;
|
||||
|
||||
typedef struct {
|
||||
@@ -293,6 +294,12 @@ typedef struct {
|
||||
guint32 show_keyboard;
|
||||
} BroadwayRequestSetShowKeyboard;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
gboolean modal_hint;
|
||||
} BroadwayRequestSetModalHint;
|
||||
|
||||
typedef union {
|
||||
BroadwayRequestBase base;
|
||||
BroadwayRequestNewSurface new_surface;
|
||||
@@ -312,6 +319,7 @@ typedef union {
|
||||
BroadwayRequestUploadTexture upload_texture;
|
||||
BroadwayRequestReleaseTexture release_texture;
|
||||
BroadwayRequestSetNodes set_nodes;
|
||||
BroadwayRequestSetModalHint set_modal_hint;
|
||||
} BroadwayRequest;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -124,6 +124,7 @@ struct BroadwaySurface {
|
||||
gboolean visible;
|
||||
gint32 transient_for;
|
||||
guint32 texture;
|
||||
gboolean modal_hint;
|
||||
BroadwayNode *nodes;
|
||||
GHashTable *node_lookup;
|
||||
};
|
||||
@@ -421,6 +422,14 @@ update_event_state (BroadwayServer *server,
|
||||
{
|
||||
surface->x = message->configure_notify.x;
|
||||
surface->y = message->configure_notify.y;
|
||||
|
||||
if (server->focused_surface_id != message->configure_notify.id &&
|
||||
server->pointer_grab_surface_id == -1 && surface->modal_hint)
|
||||
{
|
||||
broadway_server_surface_raise (server, message->configure_notify.id);
|
||||
broadway_server_focus_surface (server, message->configure_notify.id);
|
||||
broadway_server_flush (server);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
|
||||
@@ -1568,6 +1577,7 @@ broadway_server_destroy_surface (BroadwayServer *server,
|
||||
int id)
|
||||
{
|
||||
BroadwaySurface *surface;
|
||||
gint32 transient_for = -1;
|
||||
|
||||
if (server->mouse_in_surface_id == id)
|
||||
{
|
||||
@@ -1585,11 +1595,24 @@ broadway_server_destroy_surface (BroadwayServer *server,
|
||||
surface = broadway_server_lookup_surface (server, id);
|
||||
if (surface != NULL)
|
||||
{
|
||||
if (server->focused_surface_id == id)
|
||||
transient_for = surface->transient_for;
|
||||
|
||||
server->surfaces = g_list_remove (server->surfaces, surface);
|
||||
g_hash_table_remove (server->surface_id_hash,
|
||||
GINT_TO_POINTER (id));
|
||||
broadway_surface_free (server, surface);
|
||||
}
|
||||
|
||||
if (transient_for != -1)
|
||||
{
|
||||
surface = broadway_server_lookup_surface (server, transient_for);
|
||||
if (surface != NULL)
|
||||
{
|
||||
broadway_server_focus_surface (server, transient_for);
|
||||
broadway_server_flush (server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1710,6 +1733,19 @@ broadway_server_surface_set_transient_for (BroadwayServer *server,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
broadway_server_surface_set_modal_hint (BroadwayServer *server,
|
||||
int id, gboolean modal_hint)
|
||||
{
|
||||
BroadwaySurface *surface;
|
||||
|
||||
surface = broadway_server_lookup_surface (server, id);
|
||||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
surface->modal_hint = modal_hint;
|
||||
}
|
||||
|
||||
gboolean
|
||||
broadway_server_has_client (BroadwayServer *server)
|
||||
{
|
||||
|
||||
@@ -130,6 +130,9 @@ gboolean broadway_server_surface_move_resize (BroadwayServer *
|
||||
int height);
|
||||
void broadway_server_focus_surface (BroadwayServer *server,
|
||||
int new_focused_surface);
|
||||
void broadway_server_surface_set_modal_hint (BroadwayServer *server,
|
||||
int id,
|
||||
gboolean modal_hint);
|
||||
|
||||
|
||||
#endif /* __BROADWAY_SERVER__ */
|
||||
|
||||
@@ -380,6 +380,11 @@ client_handle_request (BroadwayClient *client,
|
||||
case BROADWAY_REQUEST_SET_SHOW_KEYBOARD:
|
||||
broadway_server_set_show_keyboard (server, request->set_show_keyboard.show_keyboard);
|
||||
break;
|
||||
case BROADWAY_REQUEST_SET_MODAL_HINT:
|
||||
broadway_server_surface_set_modal_hint (server,
|
||||
request->set_modal_hint.id,
|
||||
request->set_modal_hint.modal_hint);
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown request of type %d", request->base.type);
|
||||
}
|
||||
|
||||
@@ -561,6 +561,18 @@ _gdk_broadway_server_surface_set_transient_for (GdkBroadwayServer *server,
|
||||
BROADWAY_REQUEST_SET_TRANSIENT_FOR);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server,
|
||||
int id, gboolean modal_hint)
|
||||
{
|
||||
BroadwayRequestSetModalHint msg;
|
||||
|
||||
msg.id = id;
|
||||
msg.modal_hint = modal_hint;
|
||||
gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_SET_MODAL_HINT);
|
||||
}
|
||||
|
||||
static int
|
||||
open_shared_memory (void)
|
||||
{
|
||||
|
||||
@@ -78,5 +78,8 @@ gboolean _gdk_broadway_server_surface_move_resize (GdkBroadwaySe
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
void _gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server,
|
||||
int id,
|
||||
gboolean modal_hint);
|
||||
|
||||
#endif /* __GDK_BROADWAY_SERVER__ */
|
||||
|
||||
@@ -82,6 +82,27 @@ gdk_event_source_check (GSource *source)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_focus_change (GdkEvent *event)
|
||||
{
|
||||
GdkEvent *focus_event;
|
||||
gboolean focus_in = (gdk_event_get_event_type (event) == GDK_ENTER_NOTIFY);
|
||||
|
||||
if (gdk_crossing_event_get_detail (event) == GDK_NOTIFY_INFERIOR)
|
||||
return;
|
||||
|
||||
if (!gdk_crossing_event_get_focus (event) )
|
||||
return;
|
||||
|
||||
focus_event = gdk_focus_event_new (gdk_event_get_surface (event),
|
||||
gdk_event_get_device (event),
|
||||
focus_in);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gdk_display_put_event (gdk_event_get_display (event), focus_event);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
gdk_event_unref (focus_event);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
BroadwayInputMsg *message)
|
||||
@@ -110,6 +131,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
_gdk_windowing_got_event (display, node, event, message->base.serial);
|
||||
|
||||
handle_focus_change (event);
|
||||
}
|
||||
break;
|
||||
case BROADWAY_EVENT_LEAVE:
|
||||
@@ -126,6 +149,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
message->crossing.mode,
|
||||
GDK_NOTIFY_ANCESTOR);
|
||||
|
||||
handle_focus_change (event);
|
||||
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
_gdk_windowing_got_event (display, node, event, message->base.serial);
|
||||
}
|
||||
|
||||
@@ -709,6 +709,21 @@ gdk_broadway_surface_set_transient_for (GdkSurface *surface,
|
||||
_gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_set_modal_hint (GdkSurface *surface,
|
||||
gboolean modal)
|
||||
{
|
||||
GdkBroadwayDisplay *display;
|
||||
GdkBroadwaySurface *impl;
|
||||
|
||||
impl = GDK_BROADWAY_SURFACE (surface);
|
||||
|
||||
impl->modal_hint = modal;
|
||||
|
||||
display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface));
|
||||
_gdk_broadway_server_surface_set_modal_hint (display->server, impl->id, impl->modal_hint);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_broadway_surface_get_geometry (GdkSurface *surface,
|
||||
int *x,
|
||||
@@ -1433,6 +1448,8 @@ gdk_broadway_toplevel_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
|
||||
gdk_broadway_surface_set_modal_hint (surface, g_value_get_boolean (value));
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
|
||||
@@ -1479,6 +1496,10 @@ gdk_broadway_toplevel_get_property (GObject *object,
|
||||
g_value_set_object (value, surface->transient_for);
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
|
||||
g_value_set_boolean (value, surface->modal_hint);
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
|
||||
g_value_set_pointer (value, NULL);
|
||||
break;
|
||||
|
||||
@@ -54,6 +54,7 @@ struct _GdkBroadwaySurface
|
||||
|
||||
gboolean dirty;
|
||||
gboolean last_synced;
|
||||
gboolean modal_hint;
|
||||
|
||||
GdkGeometry geometry_hints;
|
||||
GdkSurfaceHints geometry_hints_mask;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "gdkcontentformats.h"
|
||||
#include "gdkcontentserializer.h"
|
||||
#include "gdkcontentdeserializer.h"
|
||||
#include "gdkdebugprivate.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
@@ -213,6 +214,8 @@ file_transfer_portal_register_files (const char **files,
|
||||
afd->len = g_strv_length ((char **)files);
|
||||
afd->start = 0;
|
||||
|
||||
GDK_DEBUG (DND, "file transfer portal: registering %d files", afd->len);
|
||||
|
||||
g_variant_builder_init (&options, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&options, "{sv}", "writable", g_variant_new_boolean (writable));
|
||||
g_variant_builder_add (&options, "{sv}", "autostop", g_variant_new_boolean (TRUE));
|
||||
@@ -348,9 +351,8 @@ portal_ready (GObject *object,
|
||||
static void
|
||||
portal_file_serializer (GdkContentSerializer *serializer)
|
||||
{
|
||||
GFile *file;
|
||||
const GValue *value;
|
||||
GPtrArray *files;
|
||||
const GValue *value;
|
||||
|
||||
files = g_ptr_array_new_with_free_func (g_free);
|
||||
|
||||
@@ -358,9 +360,24 @@ portal_file_serializer (GdkContentSerializer *serializer)
|
||||
|
||||
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_value_get_object (gdk_content_serializer_get_value (serializer));
|
||||
if (file)
|
||||
g_ptr_array_add (files, g_file_get_path (file));
|
||||
|
||||
if (file && g_file_peek_path (file))
|
||||
{
|
||||
GDK_DEBUG (DND, "file transfer portal: Adding %s", g_file_peek_path (file));
|
||||
g_ptr_array_add (files, g_file_get_path (file));
|
||||
}
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
else if (GDK_DEBUG_CHECK (DND))
|
||||
{
|
||||
char *uri = g_file_get_uri (file);
|
||||
gdk_debug_message ("file transfer portal: %s has no path, dropping\n", uri);
|
||||
g_free (uri);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_ptr_array_add (files, NULL);
|
||||
}
|
||||
else if (G_VALUE_HOLDS (value, GDK_TYPE_FILE_LIST))
|
||||
@@ -368,7 +385,21 @@ portal_file_serializer (GdkContentSerializer *serializer)
|
||||
GSList *l;
|
||||
|
||||
for (l = g_value_get_boxed (value); l; l = l->next)
|
||||
g_ptr_array_add (files, g_file_get_path (l->data));
|
||||
{
|
||||
GFile *file = l->data;
|
||||
|
||||
if (file && g_file_peek_path (file))
|
||||
{
|
||||
GDK_DEBUG (DND, "file transfer portal: Adding %s", g_file_peek_path (file));
|
||||
g_ptr_array_add (files, g_file_get_path (file));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *uri = g_file_get_uri (file);
|
||||
gdk_debug_message ("file transfer portal: %s has no path, dropping", uri);
|
||||
g_free (uri);
|
||||
}
|
||||
}
|
||||
|
||||
g_ptr_array_add (files, NULL);
|
||||
}
|
||||
@@ -395,6 +426,15 @@ portal_finish (GObject *object,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GDK_DEBUG_CHECK (DND))
|
||||
{
|
||||
char *s = g_strjoinv (", ", files);
|
||||
gdk_debug_message ("file transfer portal: Receiving files: %s", s);
|
||||
g_free (s);
|
||||
}
|
||||
#endif
|
||||
|
||||
value = gdk_content_deserializer_get_value (deserializer);
|
||||
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
|
||||
{
|
||||
|
||||
@@ -471,8 +471,8 @@ gdk_display_get_event (GdkDisplay *display)
|
||||
* Appends the given event onto the front of the event
|
||||
* queue for @display.
|
||||
*
|
||||
* This function is only useful in very special situations
|
||||
* and should not be used by applications.
|
||||
* Deprecated: 4.10: This function is only useful in very
|
||||
* special situations and should not be used by applications.
|
||||
**/
|
||||
void
|
||||
gdk_display_put_event (GdkDisplay *display,
|
||||
@@ -1114,7 +1114,7 @@ gdk_display_get_app_launch_context (GdkDisplay *display)
|
||||
|
||||
/**
|
||||
* gdk_display_open:
|
||||
* @display_name: the name of the display to open
|
||||
* @display_name: (nullable): the name of the display to open
|
||||
*
|
||||
* Opens a display.
|
||||
*
|
||||
@@ -1148,6 +1148,8 @@ _gdk_display_get_next_serial (GdkDisplay *display)
|
||||
* with custom startup-notification identifier unless
|
||||
* [method@Gtk.Window.set_auto_startup_notification]
|
||||
* is called to disable that feature.
|
||||
*
|
||||
* Deprecated: 4.10: Using [method@Gdk.Toplevel.set_startup_id] is sufficient
|
||||
*/
|
||||
void
|
||||
gdk_display_notify_startup_complete (GdkDisplay *display,
|
||||
@@ -1166,6 +1168,8 @@ gdk_display_notify_startup_complete (GdkDisplay *display,
|
||||
* if no ID has been defined.
|
||||
*
|
||||
* Returns: (nullable): the startup notification ID for @display
|
||||
*
|
||||
* Deprecated: 4.10
|
||||
*/
|
||||
const char *
|
||||
gdk_display_get_startup_notification_id (GdkDisplay *display)
|
||||
@@ -1775,11 +1779,11 @@ gdk_display_init_egl (GdkDisplay *self,
|
||||
gpointer
|
||||
gdk_display_get_egl_display (GdkDisplay *self)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (self), NULL);
|
||||
|
||||
#ifdef HAVE_EGL
|
||||
if (!priv->egl_display &&
|
||||
!gdk_display_prepare_gl (self, NULL))
|
||||
return NULL;
|
||||
@@ -2013,10 +2017,7 @@ gdk_display_get_monitors (GdkDisplay *self)
|
||||
* Gets the monitor in which the largest area of @surface
|
||||
* resides.
|
||||
*
|
||||
* Returns a monitor close to @surface if it is outside
|
||||
* of all monitors.
|
||||
*
|
||||
* Returns: (transfer none): the monitor with the largest
|
||||
* Returns: (transfer none) (nullable): the monitor with the largest
|
||||
* overlap with @surface
|
||||
*/
|
||||
GdkMonitor *
|
||||
|
||||
@@ -83,10 +83,10 @@ GdkClipboard * gdk_display_get_clipboard (GdkDisplay
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkClipboard * gdk_display_get_primary_clipboard (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10_FOR(gdk_toplevel_set_startup_id)
|
||||
void gdk_display_notify_startup_complete (GdkDisplay *display,
|
||||
const char *startup_id);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10
|
||||
const char * gdk_display_get_startup_notification_id (GdkDisplay *display);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -104,7 +104,7 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkMonitor * gdk_display_get_monitor_at_surface (GdkDisplay *display,
|
||||
GdkSurface *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10
|
||||
void gdk_display_put_event (GdkDisplay *display,
|
||||
GdkEvent *event);
|
||||
|
||||
|
||||
@@ -1511,7 +1511,6 @@ gdk_button_event_get_button (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkKeyEvent */
|
||||
|
||||
/**
|
||||
@@ -1972,7 +1971,6 @@ gdk_key_event_get_match (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkTouchEvent */
|
||||
|
||||
/**
|
||||
@@ -2109,7 +2107,6 @@ gdk_touch_event_get_emulating_pointer (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkCrossingEvent */
|
||||
|
||||
/**
|
||||
@@ -2253,7 +2250,6 @@ gdk_crossing_event_get_detail (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkDeleteEvent */
|
||||
|
||||
/**
|
||||
@@ -2284,7 +2280,6 @@ gdk_delete_event_new (GdkSurface *surface)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkFocusEvent */
|
||||
|
||||
/**
|
||||
@@ -2341,7 +2336,6 @@ gdk_focus_event_get_in (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkScrollEvent */
|
||||
|
||||
/**
|
||||
@@ -2600,7 +2594,6 @@ gdk_scroll_event_get_unit (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkTouchpadEvent */
|
||||
|
||||
/**
|
||||
@@ -2859,7 +2852,6 @@ gdk_touchpad_event_get_pinch_scale (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkPadEvent */
|
||||
|
||||
/**
|
||||
@@ -3033,7 +3025,6 @@ gdk_pad_event_get_group_mode (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkMotionEvent */
|
||||
|
||||
/**
|
||||
@@ -3195,7 +3186,6 @@ gdk_event_get_history (GdkEvent *event,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkProximityEvent */
|
||||
|
||||
/**
|
||||
@@ -3258,7 +3248,6 @@ gdk_proximity_event_new (GdkEventType type,
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkDNDEvent */
|
||||
|
||||
/**
|
||||
@@ -3364,7 +3353,6 @@ gdk_dnd_event_get_drop (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ GdkGrabBrokenEvent */
|
||||
|
||||
/**
|
||||
@@ -3442,3 +3430,5 @@ gdk_grab_broken_event_get_implicit (GdkEvent *event)
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
||||
|
||||
@@ -621,8 +621,11 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
|
||||
}
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GDK_DEBUG_CHECK (FRAMES))
|
||||
timings->frame_end_time = g_get_monotonic_time ();
|
||||
if (GDK_DEBUG_CHECK (FRAMES))
|
||||
{
|
||||
if (timings)
|
||||
timings->frame_end_time = g_get_monotonic_time ();
|
||||
}
|
||||
#endif /* G_ENABLE_DEBUG */
|
||||
G_GNUC_FALLTHROUGH;
|
||||
|
||||
|
||||
@@ -501,11 +501,23 @@ gdk_gl_context_real_is_shared (GdkGLContext *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_real_is_current (GdkGLContext *self)
|
||||
{
|
||||
#ifdef HAVE_EGL
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
|
||||
|
||||
return priv->egl_context == eglGetCurrentContext ();
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_real_clear_current (GdkGLContext *context)
|
||||
{
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
#ifdef HAVE_EGL
|
||||
GdkDisplay *display = gdk_gl_context_get_display (context);
|
||||
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
|
||||
|
||||
if (priv->egl_context == NULL)
|
||||
@@ -670,6 +682,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
|
||||
klass->is_shared = gdk_gl_context_real_is_shared;
|
||||
klass->make_current = gdk_gl_context_real_make_current;
|
||||
klass->clear_current = gdk_gl_context_real_clear_current;
|
||||
klass->is_current = gdk_gl_context_real_is_current;
|
||||
klass->get_default_framebuffer = gdk_gl_context_real_get_default_framebuffer;
|
||||
|
||||
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
|
||||
@@ -1551,6 +1564,12 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
priv->extensions_checked = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_gl_context_check_is_current (GdkGLContext *context)
|
||||
{
|
||||
return GDK_GL_CONTEXT_GET_CLASS (context)->is_current (context);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_context_make_current:
|
||||
* @context: a `GdkGLContext`
|
||||
@@ -1569,7 +1588,7 @@ gdk_gl_context_make_current (GdkGLContext *context)
|
||||
masked_context = mask_context (context, surfaceless);
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
if (current == masked_context)
|
||||
if (current == masked_context && gdk_gl_context_check_is_current (context))
|
||||
return;
|
||||
|
||||
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
|
||||
@@ -1740,10 +1759,18 @@ GdkGLContext *
|
||||
gdk_gl_context_get_current (void)
|
||||
{
|
||||
MaskedContext *current;
|
||||
GdkGLContext *context;
|
||||
|
||||
current = g_private_get (&thread_current_context);
|
||||
context = unmask_context (current);
|
||||
|
||||
return unmask_context (current);
|
||||
if (context && !gdk_gl_context_check_is_current (context))
|
||||
{
|
||||
g_private_replace (&thread_current_context, NULL);
|
||||
context = NULL;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -83,6 +83,7 @@ struct _GdkGLContextClass
|
||||
gboolean (* make_current) (GdkGLContext *context,
|
||||
gboolean surfaceless);
|
||||
gboolean (* clear_current) (GdkGLContext *context);
|
||||
gboolean (* is_current) (GdkGLContext *context);
|
||||
cairo_region_t * (* get_damage) (GdkGLContext *context);
|
||||
|
||||
gboolean (* is_shared) (GdkGLContext *self,
|
||||
|
||||
@@ -39,6 +39,7 @@ struct _GdkGLTexture {
|
||||
|
||||
GdkGLContext *context;
|
||||
guint id;
|
||||
GLsync sync;
|
||||
|
||||
GdkTexture *saved;
|
||||
|
||||
@@ -53,10 +54,8 @@ struct _GdkGLTextureClass {
|
||||
G_DEFINE_TYPE (GdkGLTexture, gdk_gl_texture, GDK_TYPE_TEXTURE)
|
||||
|
||||
static void
|
||||
gdk_gl_texture_dispose (GObject *object)
|
||||
drop_gl_resources (GdkGLTexture *self)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (object);
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
self->destroy (self->data);
|
||||
@@ -66,17 +65,30 @@ gdk_gl_texture_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
self->sync = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_gl_texture_dispose (GObject *object)
|
||||
{
|
||||
GdkGLTexture *self = GDK_GL_TEXTURE (object);
|
||||
|
||||
drop_gl_resources (self);
|
||||
|
||||
g_clear_object (&self->saved);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
typedef void (* GLFunc) (GdkGLTexture *self,
|
||||
GdkGLContext *context,
|
||||
gpointer data);
|
||||
|
||||
typedef struct _InvokeData
|
||||
{
|
||||
GdkGLTexture *self;
|
||||
volatile int spinlock;
|
||||
GFunc func;
|
||||
GLFunc func;
|
||||
gpointer data;
|
||||
} InvokeData;
|
||||
|
||||
@@ -89,9 +101,13 @@ gdk_gl_texture_invoke_callback (gpointer data)
|
||||
context = gdk_display_get_gl_context (gdk_gl_context_get_display (invoke->self->context));
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
if (invoke->self->sync && context != invoke->self->context)
|
||||
glWaitSync (invoke->self->sync, 0, GL_TIMEOUT_IGNORED);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, invoke->self->id);
|
||||
|
||||
invoke->func (invoke->self, invoke->data);
|
||||
invoke->func (invoke->self, context, invoke->data);
|
||||
|
||||
g_atomic_int_set (&invoke->spinlock, 1);
|
||||
|
||||
@@ -100,7 +116,7 @@ gdk_gl_texture_invoke_callback (gpointer data)
|
||||
|
||||
static void
|
||||
gdk_gl_texture_run (GdkGLTexture *self,
|
||||
GFunc func,
|
||||
GLFunc func,
|
||||
gpointer data)
|
||||
{
|
||||
InvokeData invoke = { self, 0, func, data };
|
||||
@@ -145,19 +161,19 @@ gdk_gl_texture_find_format (gboolean use_es,
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_gl_texture_do_download (gpointer texture_,
|
||||
gpointer download_)
|
||||
gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
GdkGLContext *context,
|
||||
gpointer download_)
|
||||
{
|
||||
GdkTexture *texture = GDK_TEXTURE (self);
|
||||
gsize expected_stride;
|
||||
GdkGLTexture *self = texture_;
|
||||
GdkTexture *texture = texture_;
|
||||
Download *download = download_;
|
||||
GLenum gl_internal_format, gl_format, gl_type;
|
||||
|
||||
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
|
||||
|
||||
if (download->stride == expected_stride &&
|
||||
!gdk_gl_context_get_use_es (self->context) &&
|
||||
!gdk_gl_context_get_use_es (context) &&
|
||||
gdk_memory_format_gl_format (download->format, TRUE, &gl_internal_format, &gl_format, &gl_type))
|
||||
{
|
||||
glGetTexImage (GL_TEXTURE_2D,
|
||||
@@ -175,11 +191,11 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
glGenFramebuffers (1, &fbo);
|
||||
glBindFramebuffer (GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
|
||||
if (gdk_gl_context_check_version (self->context, 4, 3, 3, 1))
|
||||
if (gdk_gl_context_check_version (context, 4, 3, 3, 1))
|
||||
{
|
||||
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &gl_read_format);
|
||||
glGetFramebufferParameteriv (GL_FRAMEBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &gl_read_type);
|
||||
if (!gdk_gl_texture_find_format (gdk_gl_context_get_use_es (self->context), gl_read_format, gl_read_type, &actual_format))
|
||||
if (!gdk_gl_texture_find_format (gdk_gl_context_get_use_es (context), gl_read_format, gl_read_type, &actual_format))
|
||||
actual_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; /* pray */
|
||||
}
|
||||
else
|
||||
@@ -193,7 +209,7 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
(download->stride == expected_stride))
|
||||
{
|
||||
glReadPixels (0, 0,
|
||||
texture->width, texture->height,
|
||||
texture->width, texture->height,
|
||||
gl_read_format,
|
||||
gl_read_type,
|
||||
download->data);
|
||||
@@ -204,7 +220,7 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
guchar *pixels = g_malloc_n (texture->width * actual_bpp, texture->height);
|
||||
|
||||
glReadPixels (0, 0,
|
||||
texture->width, texture->height,
|
||||
texture->width, texture->height,
|
||||
gl_read_format,
|
||||
gl_read_type,
|
||||
pixels);
|
||||
@@ -297,15 +313,7 @@ gdk_gl_texture_release (GdkGLTexture *self)
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture)));
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
self->destroy (self->data);
|
||||
self->destroy = NULL;
|
||||
self->data = NULL;
|
||||
}
|
||||
|
||||
g_clear_object (&self->context);
|
||||
self->id = 0;
|
||||
drop_gl_resources (self);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -438,6 +446,46 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (id != 0, NULL);
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
|
||||
return gdk_gl_texture_new_with_sync (context, id, NULL, width, height, destroy, data);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_gl_texture_new_with_sync:
|
||||
* @context: a `GdkGLContext`
|
||||
* @id: the ID of a texture that was created with @context
|
||||
* @sync: (nullable): an optional GLsync object
|
||||
* @width: the nominal width of the texture
|
||||
* @height: the nominal height of the texture
|
||||
* @destroy: a destroy notify that will be called when the GL resources
|
||||
* are released
|
||||
* @data: data that gets passed to @destroy
|
||||
*
|
||||
* Creates a new texture for an existing GL texture.
|
||||
*
|
||||
* If @sync is given, consumers of the texture are required to wait on
|
||||
* it before attempting to use the GL texture.
|
||||
*
|
||||
* The GL texture and the sync object must stay alive unmodified until
|
||||
* @destroy is called, which will happen when the GdkTexture object is
|
||||
* finalized, or due to an explicit call of [method@Gdk.GLTexture.release].
|
||||
*
|
||||
* Return value: (transfer full) (type GdkGLTexture): A newly-created
|
||||
* `GdkTexture`
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_gl_texture_new_with_sync (GdkGLContext *context,
|
||||
guint id,
|
||||
gpointer sync,
|
||||
int width,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data)
|
||||
{
|
||||
GdkGLTexture *self;
|
||||
|
||||
@@ -453,6 +501,7 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
|
||||
self->context = g_object_ref (context);
|
||||
self->id = id;
|
||||
self->sync = sync;
|
||||
self->destroy = destroy;
|
||||
self->data = data;
|
||||
|
||||
@@ -461,3 +510,8 @@ gdk_gl_texture_new (GdkGLContext *context,
|
||||
return GDK_TEXTURE (self);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gdk_gl_texture_get_sync (GdkGLTexture *self)
|
||||
{
|
||||
return self->sync;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,16 @@ G_BEGIN_DECLS
|
||||
|
||||
GdkGLContext * gdk_gl_texture_get_context (GdkGLTexture *self);
|
||||
guint gdk_gl_texture_get_id (GdkGLTexture *self);
|
||||
gpointer gdk_gl_texture_get_sync (GdkGLTexture *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkTexture * gdk_gl_texture_new_with_sync (GdkGLContext *context,
|
||||
guint id,
|
||||
gpointer sync,
|
||||
int width,
|
||||
int height,
|
||||
GDestroyNotify destroy,
|
||||
gpointer data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_DISPLAY,
|
||||
PROP_MANUFACTURER,
|
||||
PROP_MODEL,
|
||||
@@ -81,6 +82,10 @@ gdk_monitor_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, monitor->description);
|
||||
break;
|
||||
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, monitor->display);
|
||||
break;
|
||||
@@ -154,6 +159,7 @@ gdk_monitor_finalize (GObject *object)
|
||||
{
|
||||
GdkMonitor *monitor = GDK_MONITOR (object);
|
||||
|
||||
g_free (monitor->description);
|
||||
g_free (monitor->connector);
|
||||
g_free (monitor->manufacturer);
|
||||
g_free (monitor->model);
|
||||
@@ -170,6 +176,18 @@ gdk_monitor_class_init (GdkMonitorClass *class)
|
||||
object_class->get_property = gdk_monitor_get_property;
|
||||
object_class->set_property = gdk_monitor_set_property;
|
||||
|
||||
/**
|
||||
* GdkMonitor:description: (attributes org.gtk.Property.get=gdk_monitor_get_description)
|
||||
*
|
||||
* A short description of the monitor, meant for display to the user.
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
props[PROP_DESCRIPTION] =
|
||||
g_param_spec_string ("description", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkMonitor:display: (attributes org.gtk.Property.get=gdk_monitor_get_display)
|
||||
*
|
||||
@@ -377,6 +395,10 @@ gdk_monitor_get_height_mm (GdkMonitor *monitor)
|
||||
*
|
||||
* Gets the name of the monitor's connector, if available.
|
||||
*
|
||||
* These are strings such as "eDP-1", or "HDMI-2". They depend
|
||||
* on software and hardware configuration, and should not be
|
||||
* relied on as stable identifiers of a specific monitor.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the name of the connector
|
||||
*/
|
||||
const char *
|
||||
@@ -619,3 +641,33 @@ gdk_monitor_is_valid (GdkMonitor *monitor)
|
||||
|
||||
return monitor->valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_monitor_get_description: (attributes org.gtk.Method.get_property=description)
|
||||
* @monitor: a `GdkMonitor`
|
||||
*
|
||||
* Gets a string describing the monitor, if available.
|
||||
*
|
||||
* This can be used to identify a monitor in the UI.
|
||||
*
|
||||
* Returns: (transfer none) (nullable): the monitor description
|
||||
*
|
||||
* Since: 4.10
|
||||
*/
|
||||
const char *
|
||||
gdk_monitor_get_description (GdkMonitor *monitor)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MONITOR (monitor), NULL);
|
||||
|
||||
return monitor->description;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_monitor_set_description (GdkMonitor *monitor,
|
||||
const char *description)
|
||||
{
|
||||
g_free (monitor->description);
|
||||
monitor->description = g_strdup (description);
|
||||
g_object_notify_by_pspec (G_OBJECT (monitor), props[PROP_DESCRIPTION]);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkSubpixelLayout gdk_monitor_get_subpixel_layout (GdkMonitor *monitor);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_monitor_is_valid (GdkMonitor *monitor);
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
const char * gdk_monitor_get_description (GdkMonitor *monitor);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMonitor, g_object_unref)
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ struct _GdkMonitor {
|
||||
char *manufacturer;
|
||||
char *model;
|
||||
char *connector;
|
||||
char *description;
|
||||
GdkRectangle geometry;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
@@ -70,6 +71,8 @@ void gdk_monitor_set_refresh_rate (GdkMonitor *monitor,
|
||||
void gdk_monitor_set_subpixel_layout (GdkMonitor *monitor,
|
||||
GdkSubpixelLayout subpixel);
|
||||
void gdk_monitor_invalidate (GdkMonitor *monitor);
|
||||
void gdk_monitor_set_description (GdkMonitor *monitor,
|
||||
const char *description);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -586,7 +586,7 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED))
|
||||
{
|
||||
const char *s = token->string.string;
|
||||
const char *s = gtk_css_token_get_string (token);
|
||||
|
||||
switch (strlen (s))
|
||||
{
|
||||
@@ -637,13 +637,13 @@ gdk_rgba_parser_parse (GtkCssParser *parser,
|
||||
{
|
||||
*rgba = (GdkRGBA) { 0, 0, 0, 0 };
|
||||
}
|
||||
else if (gdk_rgba_parse (rgba, token->string.string))
|
||||
else if (gdk_rgba_parse (rgba, gtk_css_token_get_string (token)))
|
||||
{
|
||||
/* everything's fine */
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "\"%s\" is not a valid color name.", token->string.string);
|
||||
gtk_css_parser_error_syntax (parser, "\"%s\" is not a valid color name.", gtk_css_token_get_string (token));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +463,7 @@ gdk_texture_new_from_resource (const char *resource_path)
|
||||
* Creates a new texture by loading an image from a file.
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
* are PNG, JPEG and TIFF, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
@@ -556,7 +556,7 @@ gdk_texture_new_from_bytes_pixbuf (GBytes *bytes,
|
||||
* 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.
|
||||
* are PNG, JPEG and TIFF, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
@@ -602,7 +602,7 @@ gdk_texture_new_from_bytes (GBytes *bytes,
|
||||
* Creates a new texture by loading an image from a file.
|
||||
*
|
||||
* The file format is detected automatically. The supported formats
|
||||
* are PNG and JPEG, though more formats might be available.
|
||||
* are PNG, JPEG and TIFF, though more formats might be available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
|
||||
@@ -27,10 +27,12 @@
|
||||
#import "GdkMacosView.h"
|
||||
#import "GdkMacosWindow.h"
|
||||
|
||||
#include "gdkmacosclipboard-private.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacosdrag-private.h"
|
||||
#include "gdkmacosdrop-private.h"
|
||||
#include "gdkmacoseventsource-private.h"
|
||||
#include "gdkmacosmonitor-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
#include "gdkmacospopupsurface-private.h"
|
||||
#include "gdkmacostoplevelsurface-private.h"
|
||||
@@ -144,7 +146,7 @@ typedef NSString *CALayerContentsGravity;
|
||||
*
|
||||
* TODO: Can we improve grab breaking to fix this?
|
||||
*/
|
||||
_gdk_macos_display_send_button_event ([self gdkDisplay], event);
|
||||
_gdk_macos_display_send_event ([self gdkDisplay], event);
|
||||
|
||||
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
|
||||
|
||||
@@ -246,7 +248,7 @@ typedef NSString *CALayerContentsGravity;
|
||||
[view release];
|
||||
|
||||
/* TODO: We might want to make this more extensible at some point */
|
||||
_gdk_macos_clipboard_register_drag_types (self);
|
||||
_gdk_macos_pasteboard_register_drag_types (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -576,6 +578,8 @@ typedef NSString *CALayerContentsGravity;
|
||||
initialResizeLocation = convert_nspoint_to_screen (self, [self mouseLocationOutsideOfEventStream]);
|
||||
}
|
||||
|
||||
// NSDraggingDestination protocol
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
NSPoint location = [sender draggingLocation];
|
||||
@@ -665,10 +669,64 @@ typedef NSString *CALayerContentsGravity;
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
|
||||
// NSDraggingSource protocol
|
||||
|
||||
- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
|
||||
{
|
||||
NSInteger sequence_number = [session draggingSequenceNumber];
|
||||
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
|
||||
GdkModifierType state = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display));
|
||||
|
||||
_gdk_macos_drag_set_actions (GDK_MACOS_DRAG (drag), state);
|
||||
|
||||
return _gdk_macos_drag_operation (GDK_MACOS_DRAG (drag));
|
||||
}
|
||||
|
||||
- (void)draggingSession:(NSDraggingSession *)session willBeginAtPoint:(NSPoint)screenPoint
|
||||
{
|
||||
NSInteger sequence_number = [session draggingSequenceNumber];
|
||||
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
|
||||
int x, y;
|
||||
|
||||
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display), screenPoint.x, screenPoint.y, &x, &y);
|
||||
_gdk_macos_drag_set_start_position (GDK_MACOS_DRAG (drag), x, y);
|
||||
_gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
|
||||
}
|
||||
|
||||
- (void)draggingSession:(NSDraggingSession *)session movedToPoint:(NSPoint)screenPoint
|
||||
{
|
||||
NSInteger sequence_number = [session draggingSequenceNumber];
|
||||
GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
|
||||
GdkDrag *drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), sequence_number);
|
||||
int x, y;
|
||||
|
||||
_gdk_macos_display_send_event (display, [NSApp currentEvent]);
|
||||
|
||||
_gdk_macos_display_from_display_coords (display, screenPoint.x, screenPoint.y, &x, &y);
|
||||
_gdk_macos_drag_surface_move (GDK_MACOS_DRAG (drag), x, y);
|
||||
}
|
||||
|
||||
- (void)draggingSession:(NSDraggingSession *)session endedAtPoint:(NSPoint)screenPoint operation:(NSDragOperation)operation
|
||||
{
|
||||
NSInteger sequence_number = [session draggingSequenceNumber];
|
||||
GdkMacosDisplay *display = GDK_MACOS_DISPLAY (gdk_surface_get_display (GDK_SURFACE (gdk_surface)));
|
||||
GdkDrag *drag = _gdk_macos_display_find_drag (display, sequence_number);
|
||||
|
||||
_gdk_macos_display_send_event (display, [NSApp currentEvent]);
|
||||
gdk_drag_set_selected_action (drag, _gdk_macos_drag_ns_operation_to_action (operation));
|
||||
|
||||
if (gdk_drag_get_selected_action (drag) != 0)
|
||||
g_signal_emit_by_name (drag, "drop-performed");
|
||||
else
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
|
||||
|
||||
_gdk_macos_display_set_drag (display, [session draggingSequenceNumber], NULL);
|
||||
}
|
||||
|
||||
// end
|
||||
|
||||
-(void)setStyleMask:(NSWindowStyleMask)styleMask
|
||||
{
|
||||
gboolean was_fullscreen;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
|
||||
|
||||
@interface GdkMacosWindow : NSWindow {
|
||||
@interface GdkMacosWindow : NSWindow <NSDraggingSource, NSDraggingDestination> {
|
||||
GdkMacosSurface *gdk_surface;
|
||||
|
||||
BOOL inMove;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -41,30 +42,6 @@ NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char
|
||||
NSPasteboardType *alternate);
|
||||
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
||||
void _gdk_macos_clipboard_register_drag_types (NSWindow *window);
|
||||
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
|
||||
void _gdk_macos_pasteboard_read_async (GObject *object,
|
||||
NSPasteboard *pasteboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||
GAsyncResult *result,
|
||||
const char **out_mime_type,
|
||||
GError **error);
|
||||
|
||||
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
GdkClipboard *clipboard;
|
||||
char **mimeTypes;
|
||||
}
|
||||
|
||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
||||
-(NSArray<NSPasteboardType> *)types;
|
||||
|
||||
@end
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gdkmacosclipboard-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
#include "gdkmacosutils-private.h"
|
||||
#include "gdkprivate.h"
|
||||
|
||||
@@ -32,163 +33,8 @@ struct _GdkMacosClipboard
|
||||
NSInteger last_change_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMemoryOutputStream *stream;
|
||||
NSPasteboardItem *item;
|
||||
NSPasteboardType type;
|
||||
GMainContext *main_context;
|
||||
guint done : 1;
|
||||
} WriteRequest;
|
||||
|
||||
enum {
|
||||
TYPE_STRING,
|
||||
TYPE_PBOARD,
|
||||
TYPE_URL,
|
||||
TYPE_FILE_URL,
|
||||
TYPE_COLOR,
|
||||
TYPE_TIFF,
|
||||
TYPE_PNG,
|
||||
TYPE_LAST
|
||||
};
|
||||
|
||||
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
|
||||
|
||||
static NSPasteboardType pasteboard_types[TYPE_LAST];
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
|
||||
|
||||
static NSPasteboardType
|
||||
get_pasteboard_type (int type)
|
||||
{
|
||||
static gsize initialized = FALSE;
|
||||
|
||||
g_assert (type >= 0);
|
||||
g_assert (type < TYPE_LAST);
|
||||
|
||||
if (g_once_init_enter (&initialized))
|
||||
{
|
||||
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
|
||||
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
|
||||
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
|
||||
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
||||
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
|
||||
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
|
||||
#else
|
||||
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
|
||||
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
|
||||
#endif
|
||||
|
||||
g_once_init_leave (&initialized, TRUE);
|
||||
}
|
||||
|
||||
return pasteboard_types[type];
|
||||
}
|
||||
|
||||
static void
|
||||
write_request_free (WriteRequest *wr)
|
||||
{
|
||||
g_clear_pointer (&wr->main_context, g_main_context_unref);
|
||||
g_clear_object (&wr->stream);
|
||||
[wr->item release];
|
||||
g_slice_free (WriteRequest, wr);
|
||||
}
|
||||
|
||||
const char *
|
||||
_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([type isEqualToString:PTYPE(STRING)] ||
|
||||
[type isEqualToString:PTYPE(PBOARD)])
|
||||
return g_intern_string ("text/plain;charset=utf-8");
|
||||
else if ([type isEqualToString:PTYPE(URL)] ||
|
||||
[type isEqualToString:PTYPE(FILE_URL)])
|
||||
return g_intern_string ("text/uri-list");
|
||||
else if ([type isEqualToString:PTYPE(COLOR)])
|
||||
return g_intern_string ("application/x-color");
|
||||
else if ([type isEqualToString:PTYPE(TIFF)])
|
||||
return g_intern_string ("image/tiff");
|
||||
else if ([type isEqualToString:PTYPE(PNG)])
|
||||
return g_intern_string ("image/png");
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSPasteboardType
|
||||
_gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = NULL;
|
||||
|
||||
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
return PTYPE(STRING);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = PTYPE(URL);
|
||||
return PTYPE(FILE_URL);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
return PTYPE(COLOR);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
return PTYPE(TIFF);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
||||
{
|
||||
return PTYPE(PNG);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_content_formats (GdkContentFormatsBuilder *builder,
|
||||
NSPasteboardType type)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
g_return_if_fail (builder != NULL);
|
||||
g_return_if_fail (type != NULL);
|
||||
|
||||
mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
||||
|
||||
if (mime_type != NULL)
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
}
|
||||
|
||||
static GdkContentFormats *
|
||||
load_offer_formats (NSPasteboard *pasteboard)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkContentFormatsBuilder *builder;
|
||||
GdkContentFormats *formats;
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
for (NSPasteboardType type in [pasteboard types])
|
||||
populate_content_formats (builder, type);
|
||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
return g_steal_pointer (&formats);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||
{
|
||||
@@ -199,22 +45,13 @@ _gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||
|
||||
change_count = [self->pasteboard changeCount];
|
||||
|
||||
formats = load_offer_formats (self->pasteboard);
|
||||
formats = _gdk_macos_pasteboard_load_formats (self->pasteboard);
|
||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
|
||||
self->last_change_count = change_count;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
create_stream_from_nsdata (NSData *data)
|
||||
{
|
||||
const guint8 *bytes = [data bytes];
|
||||
gsize len = [data length];
|
||||
|
||||
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
@@ -245,34 +82,26 @@ static void
|
||||
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
|
||||
GdkContentProvider *content)
|
||||
{
|
||||
GdkMacosPasteboardItem *item;
|
||||
NSArray<NSPasteboardItem *> *items;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
g_assert (GDK_IS_CONTENT_PROVIDER (content));
|
||||
|
||||
if (self->pasteboard == NULL)
|
||||
return;
|
||||
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkMacosClipboardDataProvider *dataProvider;
|
||||
GdkContentFormats *serializable;
|
||||
NSPasteboardItem *item;
|
||||
const char * const *mime_types;
|
||||
gsize n_mime_types;
|
||||
|
||||
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
|
||||
|
||||
serializable = gdk_content_provider_ref_storable_formats (content);
|
||||
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
|
||||
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
|
||||
|
||||
dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
|
||||
mimetypes:mime_types];
|
||||
item = [[NSPasteboardItem alloc] init];
|
||||
[item setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||
item = [[GdkMacosPasteboardItem alloc] initForClipboard:GDK_CLIPBOARD (self) withContentProvider:content];
|
||||
items = [NSArray arrayWithObject:item];
|
||||
|
||||
[self->pasteboard clearContents];
|
||||
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
|
||||
g_warning ("Failed to write object to pasteboard");
|
||||
if ([self->pasteboard writeObjects:items] == NO)
|
||||
g_warning ("Failed to send clipboard to pasteboard");
|
||||
|
||||
self->last_change_count = [self->pasteboard changeCount];
|
||||
|
||||
g_clear_pointer (&serializable, gdk_content_formats_unref);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
@@ -365,305 +194,3 @@ _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
|
||||
if ([self->pasteboard changeCount] != self->last_change_count)
|
||||
_gdk_macos_clipboard_load_contents (self);
|
||||
}
|
||||
|
||||
@implementation GdkMacosClipboardDataProvider
|
||||
|
||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
||||
{
|
||||
[super init];
|
||||
|
||||
self->mimeTypes = g_strdupv ((char **)mime_types);
|
||||
self->clipboard = g_object_ref (gdkClipboard);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
|
||||
g_clear_pointer (&self->mimeTypes, g_strfreev);
|
||||
g_clear_object (&self->clipboard);
|
||||
g_clear_object (&self->cancellable);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
|
||||
{
|
||||
g_clear_object (&self->clipboard);
|
||||
}
|
||||
|
||||
-(NSArray<NSPasteboardType> *)types
|
||||
{
|
||||
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
||||
|
||||
for (guint i = 0; self->mimeTypes[i]; i++)
|
||||
{
|
||||
const char *mime_type = self->mimeTypes[i];
|
||||
NSPasteboardType type;
|
||||
NSPasteboardType alternate = nil;
|
||||
|
||||
if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
|
||||
{
|
||||
[ret addObject:type];
|
||||
if (alternate)
|
||||
[ret addObject:alternate];
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&ret);
|
||||
}
|
||||
|
||||
static void
|
||||
on_data_ready_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkClipboard *clipboard = (GdkClipboard *)object;
|
||||
WriteRequest *wr = user_data;
|
||||
GError *error = NULL;
|
||||
NSData *data = nil;
|
||||
|
||||
g_assert (GDK_IS_CLIPBOARD (clipboard));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (wr != NULL);
|
||||
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
|
||||
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
|
||||
|
||||
if (gdk_clipboard_write_finish (clipboard, result, &error))
|
||||
{
|
||||
gsize size;
|
||||
gpointer bytes;
|
||||
|
||||
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
|
||||
|
||||
size = g_memory_output_stream_get_data_size (wr->stream);
|
||||
bytes = g_memory_output_stream_steal_data (wr->stream);
|
||||
data = [[NSData alloc] initWithBytesNoCopy:bytes
|
||||
length:size
|
||||
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Failed to serialize clipboard contents: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
[wr->item setData:data forType:wr->type];
|
||||
|
||||
wr->done = TRUE;
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
-(void) pasteboard:(NSPasteboard *)pasteboard
|
||||
item:(NSPasteboardItem *)item
|
||||
provideDataForType:(NSPasteboardType)type
|
||||
{
|
||||
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
||||
GMainContext *main_context = g_main_context_default ();
|
||||
WriteRequest *wr;
|
||||
|
||||
if (self->clipboard == NULL || mime_type == NULL)
|
||||
{
|
||||
[item setData:[NSData data] forType:type];
|
||||
return;
|
||||
}
|
||||
|
||||
wr = g_slice_new0 (WriteRequest);
|
||||
wr->item = [item retain];
|
||||
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
|
||||
wr->type = type;
|
||||
wr->main_context = g_main_context_ref (main_context);
|
||||
wr->done = FALSE;
|
||||
|
||||
gdk_clipboard_write_async (self->clipboard,
|
||||
mime_type,
|
||||
G_OUTPUT_STREAM (wr->stream),
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
on_data_ready_cb,
|
||||
wr);
|
||||
|
||||
/* We're forced to provide data synchronously via this API
|
||||
* so we must block on the main loop. Using another main loop
|
||||
* than the default tends to get us locked up here, so that is
|
||||
* what we'll do for now.
|
||||
*/
|
||||
while (!wr->done)
|
||||
g_main_context_iteration (wr->main_context, TRUE);
|
||||
|
||||
write_request_free (wr);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_clipboard_register_drag_types (NSWindow *window)
|
||||
{
|
||||
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
|
||||
PTYPE(PBOARD),
|
||||
PTYPE(URL),
|
||||
PTYPE(FILE_URL),
|
||||
PTYPE(COLOR),
|
||||
PTYPE(TIFF),
|
||||
PTYPE(PNG),
|
||||
nil]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
GdkContentFormats *
|
||||
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
|
||||
{
|
||||
return load_offer_formats (pasteboard);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_pasteboard_read_async (GObject *object,
|
||||
NSPasteboard *pasteboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkContentFormats *offer_formats = NULL;
|
||||
const char *mime_type;
|
||||
GInputStream *stream = NULL;
|
||||
GTask *task = NULL;
|
||||
|
||||
g_assert (G_IS_OBJECT (object));
|
||||
g_assert (pasteboard != NULL);
|
||||
g_assert (formats != NULL);
|
||||
|
||||
task = g_task_new (object, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
offer_formats = load_offer_formats (pasteboard);
|
||||
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
|
||||
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"%s",
|
||||
_("No compatible transfer format found"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
|
||||
|
||||
if (nsstr != NULL)
|
||||
{
|
||||
const char *str = [nsstr UTF8String];
|
||||
stream = g_memory_input_stream_new_from_data (g_strdup (str),
|
||||
strlen (str) + 1,
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
else if (strcmp (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
|
||||
{
|
||||
GString *str = g_string_new (NULL);
|
||||
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
|
||||
gsize n_files = [files count];
|
||||
char *data;
|
||||
guint len;
|
||||
|
||||
for (gsize i = 0; i < n_files; ++i)
|
||||
{
|
||||
NSString* uriString = [files objectAtIndex:i];
|
||||
uriString = [@"file://" stringByAppendingString:uriString];
|
||||
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
g_string_append_printf (str,
|
||||
"%s\r\n",
|
||||
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
|
||||
len = str->len;
|
||||
data = g_string_free (str, FALSE);
|
||||
stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
}
|
||||
else if (strcmp (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
NSColorSpace *colorspace;
|
||||
NSColor *nscolor;
|
||||
guint16 color[4];
|
||||
|
||||
colorspace = [NSColorSpace genericRGBColorSpace];
|
||||
nscolor = [[NSColor colorFromPasteboard:pasteboard]
|
||||
colorUsingColorSpace:colorspace];
|
||||
|
||||
color[0] = 0xffff * [nscolor redComponent];
|
||||
color[1] = 0xffff * [nscolor greenComponent];
|
||||
color[2] = 0xffff * [nscolor blueComponent];
|
||||
color[3] = 0xffff * [nscolor alphaComponent];
|
||||
|
||||
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
|
||||
sizeof color,
|
||||
g_free);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/png") == 0)
|
||||
{
|
||||
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
|
||||
if (stream != NULL)
|
||||
{
|
||||
g_task_set_task_data (task, g_strdup (mime_type), g_free);
|
||||
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Failed to decode contents with mime-type of '%s'"),
|
||||
mime_type);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_clear_object (&task);
|
||||
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
GInputStream *
|
||||
_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||
GAsyncResult *result,
|
||||
const char **out_mime_type,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task = (GTask *)result;
|
||||
|
||||
g_assert (G_IS_OBJECT (object));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (out_mime_type != NULL)
|
||||
*out_mime_type = g_strdup (g_task_get_task_data (task));
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
#include "gdkmacoscursor-private.h"
|
||||
|
||||
@interface NSCursor()
|
||||
-(long long)_coreCursorType;
|
||||
@end
|
||||
|
||||
/* OS X only exports a number of cursor types in its public NSCursor interface.
|
||||
* By overriding the private _coreCursorType method, we can tell OS X to load
|
||||
* one of its internal cursors instead (since cursor images are loaded on demand
|
||||
|
||||
@@ -155,12 +155,13 @@ void _gdk_macos_display_surface_became_key (GdkMacosDisp
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_clear_sorting (GdkMacosDisplay *self);
|
||||
const GList *_gdk_macos_display_get_surfaces (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
|
||||
void _gdk_macos_display_send_event (GdkMacosDisplay *self,
|
||||
NSEvent *nsevent);
|
||||
void _gdk_macos_display_warp_pointer (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y);
|
||||
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
|
||||
NSEvent *_gdk_macos_display_get_last_nsevent (void);
|
||||
GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
|
||||
NSInteger sequence_number);
|
||||
GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,
|
||||
|
||||
@@ -723,6 +723,85 @@ fill_scroll_event (GdkMacosDisplay *self,
|
||||
return g_steal_pointer (&ret);
|
||||
}
|
||||
|
||||
|
||||
static GdkEvent *
|
||||
fill_event (GdkMacosDisplay *self,
|
||||
GdkMacosWindow *window,
|
||||
NSEvent *nsevent,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
GdkMacosSurface *surface = [window gdkSurface];
|
||||
NSEventType event_type = [nsevent type];
|
||||
GdkEvent *ret = NULL;
|
||||
|
||||
switch ((int)event_type)
|
||||
{
|
||||
case NSEventTypeLeftMouseDown:
|
||||
case NSEventTypeRightMouseDown:
|
||||
case NSEventTypeOtherMouseDown:
|
||||
case NSEventTypeLeftMouseUp:
|
||||
case NSEventTypeRightMouseUp:
|
||||
case NSEventTypeOtherMouseUp:
|
||||
ret = fill_button_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
case NSEventTypeRightMouseDragged:
|
||||
case NSEventTypeOtherMouseDragged:
|
||||
case NSEventTypeMouseMoved:
|
||||
ret = fill_motion_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeMagnify:
|
||||
case NSEventTypeRotate:
|
||||
ret = fill_pinch_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeMouseExited:
|
||||
case NSEventTypeMouseEntered:
|
||||
{
|
||||
GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
|
||||
GdkDevice *pointer = gdk_seat_get_pointer (seat);
|
||||
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
|
||||
|
||||
if ([(GdkMacosWindow *)window isInManualResizeOrMove])
|
||||
{
|
||||
ret = GDK_MACOS_EVENT_DROP;
|
||||
}
|
||||
else if (grab == NULL || grab->owner_events)
|
||||
{
|
||||
if (event_type == NSEventTypeMouseExited)
|
||||
[[NSCursor arrowCursor] set];
|
||||
|
||||
ret = synthesize_crossing_event (self, surface, nsevent, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NSEventTypeKeyDown:
|
||||
case NSEventTypeKeyUp:
|
||||
case NSEventTypeFlagsChanged: {
|
||||
GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
|
||||
|
||||
if (type)
|
||||
ret = fill_key_event (self, surface, nsevent, type);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NSEventTypeScrollWheel:
|
||||
ret = fill_scroll_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_mouse_button_press_event (NSEventType type)
|
||||
{
|
||||
@@ -1025,16 +1104,12 @@ find_surface_for_ns_event (GdkMacosDisplay *self,
|
||||
GdkMacosBaseView *view;
|
||||
GdkSurface *surface;
|
||||
NSPoint point;
|
||||
int x_tmp;
|
||||
int y_tmp;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DISPLAY (self));
|
||||
g_assert (nsevent != NULL);
|
||||
g_assert (x != NULL);
|
||||
g_assert (y != NULL);
|
||||
|
||||
_gdk_macos_display_from_display_coords (self, point.x, point.y, &x_tmp, &y_tmp);
|
||||
|
||||
switch ((int)[nsevent type])
|
||||
{
|
||||
case NSEventTypeLeftMouseDown:
|
||||
@@ -1083,7 +1158,6 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
|
||||
GdkMacosWindow *window;
|
||||
NSEventType event_type;
|
||||
NSWindow *event_window;
|
||||
GdkEvent *ret = NULL;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
@@ -1191,79 +1265,15 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
|
||||
_gdk_macos_display_clear_sorting (self);
|
||||
}
|
||||
}
|
||||
|
||||
switch ((int)event_type)
|
||||
{
|
||||
case NSEventTypeLeftMouseDown:
|
||||
case NSEventTypeRightMouseDown:
|
||||
case NSEventTypeOtherMouseDown:
|
||||
case NSEventTypeLeftMouseUp:
|
||||
case NSEventTypeRightMouseUp:
|
||||
case NSEventTypeOtherMouseUp:
|
||||
ret = fill_button_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
case NSEventTypeRightMouseDragged:
|
||||
case NSEventTypeOtherMouseDragged:
|
||||
case NSEventTypeMouseMoved:
|
||||
ret = fill_motion_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeMagnify:
|
||||
case NSEventTypeRotate:
|
||||
ret = fill_pinch_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
case NSEventTypeMouseExited:
|
||||
case NSEventTypeMouseEntered:
|
||||
{
|
||||
GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
|
||||
GdkDevice *pointer = gdk_seat_get_pointer (seat);
|
||||
GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), pointer);
|
||||
|
||||
if ([(GdkMacosWindow *)window isInManualResizeOrMove])
|
||||
{
|
||||
ret = GDK_MACOS_EVENT_DROP;
|
||||
}
|
||||
else if (grab == NULL)
|
||||
{
|
||||
if (event_type == NSEventTypeMouseExited)
|
||||
[[NSCursor arrowCursor] set];
|
||||
|
||||
ret = synthesize_crossing_event (self, surface, nsevent, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NSEventTypeKeyDown:
|
||||
case NSEventTypeKeyUp:
|
||||
case NSEventTypeFlagsChanged: {
|
||||
GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
|
||||
|
||||
if (type)
|
||||
ret = fill_key_event (self, surface, nsevent, type);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NSEventTypeScrollWheel:
|
||||
ret = fill_scroll_event (self, surface, nsevent, x, y);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return fill_event (self, window, nsevent, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_display_send_button_event (GdkMacosDisplay *self,
|
||||
NSEvent *nsevent)
|
||||
_gdk_macos_display_send_event (GdkMacosDisplay *self,
|
||||
NSEvent *nsevent)
|
||||
{
|
||||
GdkMacosSurface *surface;
|
||||
GdkMacosWindow *window;
|
||||
GdkEvent *event;
|
||||
int x;
|
||||
int y;
|
||||
@@ -1272,7 +1282,8 @@ _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
|
||||
g_return_if_fail (nsevent != NULL);
|
||||
|
||||
if ((surface = find_surface_for_ns_event (self, nsevent, &x, &y)) &&
|
||||
(event = fill_button_event (self, surface, nsevent, x, y)))
|
||||
(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)) &&
|
||||
(event = fill_event (self, window, nsevent, x, y)))
|
||||
_gdk_windowing_got_event (GDK_DISPLAY (self),
|
||||
_gdk_event_queue_append (GDK_DISPLAY (self), event),
|
||||
event,
|
||||
|
||||
@@ -1024,6 +1024,16 @@ _gdk_macos_display_get_nsevent (GdkEvent *event)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSEvent *
|
||||
_gdk_macos_display_get_last_nsevent ()
|
||||
{
|
||||
const GdkToNSEventMap *map = g_queue_peek_tail (&event_map);
|
||||
if (map)
|
||||
return map->nsevent;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GdkDrag *
|
||||
_gdk_macos_display_find_drag (GdkMacosDisplay *self,
|
||||
NSInteger sequence_number)
|
||||
|
||||
@@ -41,7 +41,6 @@ struct _GdkMacosDrag
|
||||
GdkDrag parent_instance;
|
||||
|
||||
GdkMacosDragSurface *drag_surface;
|
||||
GdkSeat *drag_seat;
|
||||
GdkCursor *cursor;
|
||||
|
||||
int hot_x;
|
||||
@@ -62,8 +61,22 @@ struct _GdkMacosDragClass
|
||||
GdkDragClass parent_class;
|
||||
};
|
||||
|
||||
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
|
||||
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self);
|
||||
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
|
||||
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self,
|
||||
GdkContentProvider *content,
|
||||
GdkMacosWindow *window);
|
||||
NSDragOperation _gdk_macos_drag_operation (GdkMacosDrag *self);
|
||||
GdkDragAction _gdk_macos_drag_ns_operation_to_action
|
||||
(NSDragOperation operation);
|
||||
void _gdk_macos_drag_surface_move (GdkMacosDrag *self,
|
||||
int x_root,
|
||||
int y_root);
|
||||
void _gdk_macos_drag_set_start_position (GdkMacosDrag *self,
|
||||
int start_x,
|
||||
int start_y);
|
||||
void _gdk_macos_drag_set_actions (GdkMacosDrag *self,
|
||||
GdkModifierType mods);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "gdkmacoscursor-private.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacosdragsurface-private.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
|
||||
#include "gdk/gdkdeviceprivate.h"
|
||||
#include "gdk/gdkeventsprivate.h"
|
||||
@@ -187,41 +188,6 @@ gdk_macos_drag_set_cursor (GdkDrag *drag,
|
||||
[nscursor set];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
drag_grab (GdkMacosDrag *self)
|
||||
{
|
||||
GdkSeat *seat;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
seat = gdk_device_get_seat (gdk_drag_get_device (GDK_DRAG (self)));
|
||||
|
||||
if (gdk_seat_grab (seat,
|
||||
GDK_SURFACE (self->drag_surface),
|
||||
GDK_SEAT_CAPABILITY_ALL_POINTING,
|
||||
FALSE,
|
||||
self->cursor,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL) != GDK_GRAB_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
g_set_object (&self->drag_seat, seat);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
drag_ungrab (GdkMacosDrag *self)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
display = gdk_drag_get_display (GDK_DRAG (self));
|
||||
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), GDK_CURRENT_TIME);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_drag_cancel (GdkDrag *drag,
|
||||
GdkDragCancelReason reason)
|
||||
@@ -234,7 +200,6 @@ gdk_macos_drag_cancel (GdkDrag *drag,
|
||||
return;
|
||||
|
||||
self->cancelled = TRUE;
|
||||
drag_ungrab (self);
|
||||
gdk_drag_drop_done (drag, FALSE);
|
||||
}
|
||||
|
||||
@@ -247,7 +212,6 @@ gdk_macos_drag_drop_performed (GdkDrag *drag,
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
g_object_ref (self);
|
||||
drag_ungrab (self);
|
||||
g_signal_emit_by_name (drag, "dnd-finished");
|
||||
gdk_drag_drop_done (drag, TRUE);
|
||||
g_object_unref (self);
|
||||
@@ -310,225 +274,6 @@ gdk_drag_get_current_actions (GdkModifierType state,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_drag_update (GdkDrag *drag,
|
||||
double x_root,
|
||||
double y_root,
|
||||
GdkModifierType mods,
|
||||
guint32 evtime)
|
||||
{
|
||||
GdkMacosDrag *self = (GdkMacosDrag *)drag;
|
||||
GdkDragAction suggested_action;
|
||||
GdkDragAction possible_actions;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
self->last_x = x_root;
|
||||
self->last_y = y_root;
|
||||
|
||||
gdk_drag_get_current_actions (mods,
|
||||
GDK_BUTTON_PRIMARY,
|
||||
gdk_drag_get_actions (drag),
|
||||
&suggested_action,
|
||||
&possible_actions);
|
||||
|
||||
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
|
||||
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
|
||||
x_root - self->hot_x,
|
||||
y_root - self->hot_y);
|
||||
|
||||
if (!self->did_update)
|
||||
{
|
||||
self->start_x = self->last_x;
|
||||
self->start_y = self->last_y;
|
||||
self->did_update = TRUE;
|
||||
}
|
||||
|
||||
gdk_drag_set_actions (drag, possible_actions);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dnd_handle_motion_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
{
|
||||
double x, y;
|
||||
int x_root, y_root;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (drag));
|
||||
g_assert (event != NULL);
|
||||
|
||||
/* Ignore motion while doing zoomback */
|
||||
if (GDK_MACOS_DRAG (drag)->cancelled)
|
||||
return FALSE;
|
||||
|
||||
gdk_event_get_position (event, &x, &y);
|
||||
x_root = event->surface->x + x;
|
||||
y_root = event->surface->y + y;
|
||||
gdk_drag_update (drag, x_root, y_root,
|
||||
gdk_event_get_modifier_state (event),
|
||||
gdk_event_get_time (event));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
|
||||
gboolean is_implicit = gdk_grab_broken_event_get_implicit (event);
|
||||
GdkSurface *grab_surface = gdk_grab_broken_event_get_grab_surface (event);
|
||||
|
||||
/* Don't cancel if we break the implicit grab from the initial button_press. */
|
||||
if (is_implicit || grab_surface == (GdkSurface *)self->drag_surface)
|
||||
return FALSE;
|
||||
|
||||
if (gdk_event_get_device (event) != gdk_drag_get_device (drag))
|
||||
return FALSE;
|
||||
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dnd_handle_button_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
g_assert (event != NULL);
|
||||
|
||||
#if 0
|
||||
/* FIXME: Check the button matches */
|
||||
if (event->button != self->button)
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
if (gdk_drag_get_selected_action (drag) != 0)
|
||||
g_signal_emit_by_name (drag, "drop-performed");
|
||||
else
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_dnd_handle_key_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
{
|
||||
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
|
||||
GdkModifierType state;
|
||||
GdkDevice *pointer;
|
||||
GdkSeat *seat;
|
||||
int dx, dy;
|
||||
|
||||
dx = dy = 0;
|
||||
state = gdk_event_get_modifier_state (event);
|
||||
seat = gdk_event_get_seat (event);
|
||||
pointer = gdk_seat_get_pointer (seat);
|
||||
|
||||
if (event->event_type == GDK_KEY_PRESS)
|
||||
{
|
||||
guint keyval = gdk_key_event_get_keyval (event);
|
||||
|
||||
switch (keyval)
|
||||
{
|
||||
case GDK_KEY_Escape:
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
|
||||
return TRUE;
|
||||
|
||||
case GDK_KEY_space:
|
||||
case GDK_KEY_Return:
|
||||
case GDK_KEY_ISO_Enter:
|
||||
case GDK_KEY_KP_Enter:
|
||||
case GDK_KEY_KP_Space:
|
||||
if (gdk_drag_get_selected_action (drag) != 0)
|
||||
g_signal_emit_by_name (drag, "drop-performed");
|
||||
else
|
||||
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
|
||||
|
||||
return TRUE;
|
||||
|
||||
case GDK_KEY_Up:
|
||||
case GDK_KEY_KP_Up:
|
||||
dy = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
|
||||
break;
|
||||
|
||||
case GDK_KEY_Down:
|
||||
case GDK_KEY_KP_Down:
|
||||
dy = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
|
||||
break;
|
||||
|
||||
case GDK_KEY_Left:
|
||||
case GDK_KEY_KP_Left:
|
||||
dx = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
|
||||
break;
|
||||
|
||||
case GDK_KEY_Right:
|
||||
case GDK_KEY_KP_Right:
|
||||
dx = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* The state is not yet updated in the event, so we need
|
||||
* to query it here. We could use XGetModifierMapping, but
|
||||
* that would be overkill.
|
||||
*/
|
||||
gdk_macos_device_query_state (pointer, NULL, NULL, NULL, NULL, &state);
|
||||
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
GdkDisplay *display = gdk_event_get_display ((GdkEvent *)event);
|
||||
|
||||
self->last_x += dx;
|
||||
self->last_y += dy;
|
||||
|
||||
_gdk_macos_display_warp_pointer (GDK_MACOS_DISPLAY (display),
|
||||
self->last_x,
|
||||
self->last_y);
|
||||
}
|
||||
|
||||
gdk_drag_update (drag,
|
||||
self->last_x, self->last_y,
|
||||
state,
|
||||
gdk_event_get_time (event));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_drag_handle_event (GdkDrag *drag,
|
||||
GdkEvent *event)
|
||||
{
|
||||
g_assert (GDK_IS_MACOS_DRAG (drag));
|
||||
g_assert (event != NULL);
|
||||
|
||||
switch ((guint) event->event_type)
|
||||
{
|
||||
case GDK_MOTION_NOTIFY:
|
||||
return gdk_dnd_handle_motion_event (drag, event);
|
||||
|
||||
case GDK_BUTTON_RELEASE:
|
||||
return gdk_dnd_handle_button_event (drag, event);
|
||||
|
||||
case GDK_KEY_PRESS:
|
||||
case GDK_KEY_RELEASE:
|
||||
return gdk_dnd_handle_key_event (drag, event);
|
||||
|
||||
case GDK_GRAB_BROKEN:
|
||||
return gdk_dnd_handle_grab_broken_event (drag, event);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_drag_finalize (GObject *object)
|
||||
{
|
||||
@@ -536,7 +281,6 @@ gdk_macos_drag_finalize (GObject *object)
|
||||
GdkMacosDragSurface *drag_surface = g_steal_pointer (&self->drag_surface);
|
||||
|
||||
g_clear_object (&self->cursor);
|
||||
g_clear_object (&self->drag_seat);
|
||||
|
||||
G_OBJECT_CLASS (gdk_macos_drag_parent_class)->finalize (object);
|
||||
|
||||
@@ -598,7 +342,6 @@ gdk_macos_drag_class_init (GdkMacosDragClass *klass)
|
||||
drag_class->set_cursor = gdk_macos_drag_set_cursor;
|
||||
drag_class->cancel = gdk_macos_drag_cancel;
|
||||
drag_class->drop_performed = gdk_macos_drag_drop_performed;
|
||||
drag_class->handle_event = gdk_macos_drag_handle_event;
|
||||
|
||||
properties [PROP_DRAG_SURFACE] =
|
||||
g_param_spec_object ("drag-surface", NULL, NULL,
|
||||
@@ -614,11 +357,113 @@ gdk_macos_drag_init (GdkMacosDrag *self)
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_macos_drag_begin (GdkMacosDrag *self)
|
||||
_gdk_macos_drag_begin (GdkMacosDrag *self,
|
||||
GdkContentProvider *content,
|
||||
GdkMacosWindow *window)
|
||||
{
|
||||
NSArray<NSDraggingItem *> *items;
|
||||
NSDraggingSession *session;
|
||||
NSPasteboardItem *item;
|
||||
NSEvent *nsevent;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_MACOS_WINDOW (window), FALSE);
|
||||
|
||||
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
return drag_grab (self);
|
||||
item = [[GdkMacosPasteboardItem alloc] initForDrag:GDK_DRAG (self) withContentProvider:content];
|
||||
items = [NSArray arrayWithObject:item];
|
||||
nsevent = _gdk_macos_display_get_last_nsevent ();
|
||||
|
||||
session = [[window contentView] beginDraggingSessionWithItems:items
|
||||
event:nsevent
|
||||
source:window];
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
_gdk_macos_display_set_drag (GDK_MACOS_DISPLAY (gdk_drag_get_display (GDK_DRAG (self))),
|
||||
[session draggingSequenceNumber],
|
||||
GDK_DRAG (self));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NSDragOperation
|
||||
_gdk_macos_drag_operation (GdkMacosDrag *self)
|
||||
{
|
||||
NSDragOperation operation = NSDragOperationNone;
|
||||
GdkDragAction actions;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), NSDragOperationNone);
|
||||
|
||||
actions = gdk_drag_get_actions (GDK_DRAG (self));
|
||||
|
||||
if (actions & GDK_ACTION_LINK)
|
||||
operation |= NSDragOperationLink;
|
||||
|
||||
if (actions & GDK_ACTION_MOVE)
|
||||
operation |= NSDragOperationMove;
|
||||
|
||||
if (actions & GDK_ACTION_COPY)
|
||||
operation |= NSDragOperationCopy;
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
GdkDragAction
|
||||
_gdk_macos_drag_ns_operation_to_action (NSDragOperation operation)
|
||||
{
|
||||
if (operation & NSDragOperationCopy)
|
||||
return GDK_ACTION_COPY;
|
||||
if (operation & NSDragOperationMove)
|
||||
return GDK_ACTION_MOVE;
|
||||
if (operation & NSDragOperationLink)
|
||||
return GDK_ACTION_LINK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_drag_surface_move (GdkMacosDrag *self,
|
||||
int x_root,
|
||||
int y_root)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
self->last_x = x_root;
|
||||
self->last_y = y_root;
|
||||
|
||||
if (GDK_IS_MACOS_SURFACE (self->drag_surface))
|
||||
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
|
||||
x_root - self->hot_x,
|
||||
y_root - self->hot_y);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_drag_set_start_position (GdkMacosDrag *self,
|
||||
int start_x,
|
||||
int start_y)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
self->start_x = start_x;
|
||||
self->start_y = start_y;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_drag_set_actions (GdkMacosDrag *self,
|
||||
GdkModifierType mods)
|
||||
{
|
||||
GdkDragAction suggested_action;
|
||||
GdkDragAction possible_actions;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DRAG (self));
|
||||
|
||||
gdk_drag_get_current_actions (mods,
|
||||
GDK_BUTTON_PRIMARY,
|
||||
gdk_drag_get_actions (GDK_DRAG (self)),
|
||||
&suggested_action,
|
||||
&possible_actions);
|
||||
|
||||
gdk_drag_set_selected_action (GDK_DRAG (self), suggested_action);
|
||||
gdk_drag_set_actions (GDK_DRAG (self), possible_actions);
|
||||
}
|
||||
|
||||
@@ -37,11 +37,15 @@
|
||||
/*
|
||||
* This file implementations integration between the GLib main loop and
|
||||
* the native system of the Core Foundation run loop and Cocoa event
|
||||
* handling. There are basically two different cases that we need to
|
||||
* handle: either the GLib main loop is in control (the application
|
||||
* has called gtk_main(), or is otherwise iterating the main loop), or
|
||||
* CFRunLoop is in control (we are in a modal operation such as window
|
||||
* resizing or drag-and-drop.)
|
||||
* handling. There are basically three different cases that we need to
|
||||
* handle:
|
||||
*
|
||||
* - the GLib main loop is in control. The application has called
|
||||
* gtk_main(), or is otherwise iterating the main loop.
|
||||
* - CFRunLoop is in control. We are in a modal operation such as window
|
||||
* resizing.
|
||||
* - CFRunLoop is running a nested loop. This happens when a drag-and-drop
|
||||
* operation has been initiated.
|
||||
*
|
||||
* When the GLib main loop is in control we integrate in native event
|
||||
* handling in two ways: first we add a GSource that handles checking
|
||||
@@ -57,14 +61,23 @@
|
||||
* stages of the GLib main loop (prepare, check, dispatch), and make the
|
||||
* appropriate calls into GLib.
|
||||
*
|
||||
* Both cases share a single problem: the OS X API’s don’t allow us to
|
||||
* When initiating a drag operation, a nested CFRunLoop is executed.
|
||||
* The nested run loop is started when fetching a native event in our GLib
|
||||
* main loop. The application does not receive any events until the nested loop
|
||||
* is finished. We work around this by forwarding the
|
||||
* events that trigger the callbacks of the NSDraggingSource protocol.
|
||||
* The "run loop observer" is executing the GLib main loop stages as long as we're
|
||||
* in the nested run loop, as if CFRunLoop were in control.
|
||||
* See also GdkMacosWindow.
|
||||
*
|
||||
* All cases share a single problem: the macOS API’s don’t allow us to
|
||||
* wait simultaneously for file descriptors and for events. So when we
|
||||
* need to do a blocking wait that includes file descriptor activity, we
|
||||
* push the actual work of calling select() to a helper thread (the
|
||||
* "select thread") and wait for native events in the main thread.
|
||||
*
|
||||
* The main known limitation of this code is that if a callback is triggered
|
||||
* via the OS X run loop while we are "polling" (in either case described
|
||||
* via the macOS run loop while we are "polling" (in either case described
|
||||
* above), iteration of the GLib main loop is not possible from within
|
||||
* that callback. If the programmer tries to do so explicitly, then they
|
||||
* will get a warning from GLib "main loop already active in another thread".
|
||||
@@ -640,6 +653,23 @@ _gdk_macos_event_source_get_pending (void)
|
||||
return event;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_event_source_queue_event (NSEvent *event)
|
||||
{
|
||||
/* Just used to wake us up; if an event and a FD arrived at the same
|
||||
* time; could have come from a previous iteration in some cases,
|
||||
* but the spurious wake up is harmless if a little inefficient.
|
||||
*/
|
||||
if (!event ||
|
||||
([event type] == NSEventTypeApplicationDefined &&
|
||||
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP))
|
||||
return;
|
||||
|
||||
if (!current_events)
|
||||
current_events = g_queue_new ();
|
||||
g_queue_push_head (current_events, [event retain]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_event_source_prepare (GSource *source,
|
||||
int *timeout)
|
||||
@@ -782,23 +812,7 @@ poll_func (GPollFD *ufds,
|
||||
if (last_ufds == ufds && n_ready < 0)
|
||||
n_ready = select_thread_collect_poll (ufds, nfds);
|
||||
|
||||
if (event &&
|
||||
[event type] == NSEventTypeApplicationDefined &&
|
||||
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP)
|
||||
{
|
||||
/* Just used to wake us up; if an event and a FD arrived at the same
|
||||
* time; could have come from a previous iteration in some cases,
|
||||
* but the spurious wake up is harmless if a little inefficient.
|
||||
*/
|
||||
event = NULL;
|
||||
}
|
||||
|
||||
if (event)
|
||||
{
|
||||
if (!current_events)
|
||||
current_events = g_queue_new ();
|
||||
g_queue_push_head (current_events, [event retain]);
|
||||
}
|
||||
_gdk_macos_event_source_queue_event (event);
|
||||
|
||||
return n_ready;
|
||||
}
|
||||
@@ -1018,7 +1032,10 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
|
||||
break;
|
||||
}
|
||||
|
||||
if (getting_events > 0) /* Activity we triggered */
|
||||
/* DnD starts a nested runloop, or so it seems.
|
||||
If we have such a loop, we still want to run
|
||||
our idle handlers. */
|
||||
if (getting_events > 0 && current_loop_level < 2)
|
||||
return;
|
||||
|
||||
switch (activity)
|
||||
@@ -1042,7 +1059,6 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
|
||||
run_loop_exit ();
|
||||
break;
|
||||
case kCFRunLoopAllActivities:
|
||||
/* TODO: Do most of the above? */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -548,6 +548,14 @@ gdk_macos_gl_context_clear_current (GdkGLContext *context)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_gl_context_is_current (GdkGLContext *context)
|
||||
{
|
||||
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
|
||||
|
||||
return self->cgl_context == CGLGetCurrentContext ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_macos_gl_context_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
@@ -639,6 +647,7 @@ gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
|
||||
|
||||
gl_class->get_damage = gdk_macos_gl_context_get_damage;
|
||||
gl_class->clear_current = gdk_macos_gl_context_clear_current;
|
||||
gl_class->is_current = gdk_macos_gl_context_is_current;
|
||||
gl_class->make_current = gdk_macos_gl_context_make_current;
|
||||
gl_class->realize = gdk_macos_gl_context_real_realize;
|
||||
gl_class->get_default_framebuffer = gdk_macos_gl_context_get_default_framebuffer;
|
||||
|
||||
74
gdk/macos/gdkmacospasteboard-private.h
Normal file
74
gdk/macos/gdkmacospasteboard-private.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright © 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_PASTEBOARD_PRIVATE_H__
|
||||
#define __GDK_MACOS_PASTEBOARD_PRIVATE_H__
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@interface GdkMacosPasteboardItemDataProvider : NSObject <NSPasteboardItemDataProvider>
|
||||
{
|
||||
GdkContentProvider *_contentProvider;
|
||||
GdkClipboard *_clipboard;
|
||||
GdkDrag *_drag;
|
||||
}
|
||||
|
||||
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
|
||||
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
|
||||
|
||||
@end
|
||||
|
||||
@interface GdkMacosPasteboardItem : NSPasteboardItem
|
||||
{
|
||||
GdkContentProvider *_contentProvider;
|
||||
GdkClipboard *_clipboard;
|
||||
GdkDrag *_drag;
|
||||
NSRect _draggingFrame;
|
||||
}
|
||||
|
||||
-(id)initForClipboard:(GdkClipboard *)clipboard withContentProvider:(GdkContentProvider *)contentProvider;
|
||||
-(id)initForDrag:(GdkDrag *)drag withContentProvider:(GdkContentProvider *)contentProvider;
|
||||
|
||||
@end
|
||||
|
||||
NSPasteboardType _gdk_macos_pasteboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate);
|
||||
const char *_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type);
|
||||
GdkContentFormats *_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard);
|
||||
void _gdk_macos_pasteboard_register_drag_types (NSWindow *window);
|
||||
void _gdk_macos_pasteboard_read_async (GObject *object,
|
||||
NSPasteboard *pasteboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GInputStream *_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||
GAsyncResult *result,
|
||||
const char **out_mime_type,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_PASTEBOARD_PRIVATE_H__ */
|
||||
602
gdk/macos/gdkmacospasteboard.c
Normal file
602
gdk/macos/gdkmacospasteboard.c
Normal file
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
* Copyright © 2021 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gdkdragprivate.h"
|
||||
#include "gdkmacospasteboard-private.h"
|
||||
#include "gdkmacosutils-private.h"
|
||||
|
||||
enum {
|
||||
TYPE_STRING,
|
||||
TYPE_PBOARD,
|
||||
TYPE_URL,
|
||||
TYPE_FILE_URL,
|
||||
TYPE_COLOR,
|
||||
TYPE_TIFF,
|
||||
TYPE_PNG,
|
||||
TYPE_LAST
|
||||
};
|
||||
|
||||
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
|
||||
|
||||
static NSPasteboardType pasteboard_types[TYPE_LAST];
|
||||
|
||||
static NSPasteboardType
|
||||
get_pasteboard_type (int type)
|
||||
{
|
||||
static gsize initialized = FALSE;
|
||||
|
||||
g_assert (type >= 0);
|
||||
g_assert (type < TYPE_LAST);
|
||||
|
||||
if (g_once_init_enter (&initialized))
|
||||
{
|
||||
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
|
||||
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
|
||||
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
|
||||
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
||||
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
|
||||
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
|
||||
#else
|
||||
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
|
||||
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
|
||||
#endif
|
||||
|
||||
g_once_init_leave (&initialized, TRUE);
|
||||
}
|
||||
|
||||
return pasteboard_types[type];
|
||||
}
|
||||
|
||||
const char *
|
||||
_gdk_macos_pasteboard_from_ns_type (NSPasteboardType type)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([type isEqualToString:PTYPE(STRING)] ||
|
||||
[type isEqualToString:PTYPE(PBOARD)])
|
||||
return g_intern_string ("text/plain;charset=utf-8");
|
||||
else if ([type isEqualToString:PTYPE(URL)] ||
|
||||
[type isEqualToString:PTYPE(FILE_URL)])
|
||||
return g_intern_string ("text/uri-list");
|
||||
else if ([type isEqualToString:PTYPE(COLOR)])
|
||||
return g_intern_string ("application/x-color");
|
||||
else if ([type isEqualToString:PTYPE(TIFF)])
|
||||
return g_intern_string ("image/tiff");
|
||||
else if ([type isEqualToString:PTYPE(PNG)])
|
||||
return g_intern_string ("image/png");
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSPasteboardType
|
||||
_gdk_macos_pasteboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = NULL;
|
||||
|
||||
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
return PTYPE(STRING);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = PTYPE(URL);
|
||||
return PTYPE(FILE_URL);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
return PTYPE(COLOR);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
return PTYPE(TIFF);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
||||
{
|
||||
return PTYPE(PNG);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_content_formats (GdkContentFormatsBuilder *builder,
|
||||
NSPasteboardType type)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
g_assert (builder != NULL);
|
||||
g_assert (type != NULL);
|
||||
|
||||
if ((mime_type = _gdk_macos_pasteboard_from_ns_type (type)))
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
}
|
||||
|
||||
static GdkContentFormats *
|
||||
load_offer_formats (NSPasteboard *pasteboard)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkContentFormatsBuilder *builder;
|
||||
GdkContentFormats *formats;
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
for (NSPasteboardType type in [pasteboard types])
|
||||
populate_content_formats (builder, type);
|
||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
return g_steal_pointer (&formats);
|
||||
}
|
||||
|
||||
GdkContentFormats *
|
||||
_gdk_macos_pasteboard_load_formats (NSPasteboard *pasteboard)
|
||||
{
|
||||
return load_offer_formats (pasteboard);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
create_stream_from_nsdata (NSData *data)
|
||||
{
|
||||
const guint8 *bytes = [data bytes];
|
||||
gsize len = [data length];
|
||||
|
||||
return g_memory_input_stream_new_from_data (g_memdup2 (bytes, len), len, g_free);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_pasteboard_read_async (GObject *object,
|
||||
NSPasteboard *pasteboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkContentFormats *offer_formats = NULL;
|
||||
const char *mime_type;
|
||||
GInputStream *stream = NULL;
|
||||
GTask *task = NULL;
|
||||
|
||||
g_assert (G_IS_OBJECT (object));
|
||||
g_assert (pasteboard != NULL);
|
||||
g_assert (formats != NULL);
|
||||
|
||||
task = g_task_new (object, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, _gdk_macos_pasteboard_read_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
offer_formats = load_offer_formats (pasteboard);
|
||||
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
|
||||
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"%s",
|
||||
_("No compatible transfer format found"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
NSString *nsstr = [pasteboard stringForType:NSPasteboardTypeString];
|
||||
|
||||
if (nsstr != NULL)
|
||||
{
|
||||
const char *str = [nsstr UTF8String];
|
||||
stream = g_memory_input_stream_new_from_data (g_strdup (str),
|
||||
strlen (str) + 1,
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
else if (strcmp (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([[pasteboard types] containsObject:PTYPE(FILE_URL)])
|
||||
{
|
||||
GString *str = g_string_new (NULL);
|
||||
NSArray *files = [pasteboard propertyListForType:NSFilenamesPboardType];
|
||||
gsize n_files = [files count];
|
||||
char *data;
|
||||
guint len;
|
||||
|
||||
for (gsize i = 0; i < n_files; ++i)
|
||||
{
|
||||
NSString* uriString = [files objectAtIndex:i];
|
||||
uriString = [@"file://" stringByAppendingString:uriString];
|
||||
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
g_string_append_printf (str,
|
||||
"%s\r\n",
|
||||
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
|
||||
len = str->len;
|
||||
data = g_string_free (str, FALSE);
|
||||
stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
}
|
||||
else if (strcmp (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
NSColorSpace *colorspace;
|
||||
NSColor *nscolor;
|
||||
guint16 color[4];
|
||||
|
||||
colorspace = [NSColorSpace genericRGBColorSpace];
|
||||
nscolor = [[NSColor colorFromPasteboard:pasteboard]
|
||||
colorUsingColorSpace:colorspace];
|
||||
|
||||
color[0] = 0xffff * [nscolor redComponent];
|
||||
color[1] = 0xffff * [nscolor greenComponent];
|
||||
color[2] = 0xffff * [nscolor blueComponent];
|
||||
color[3] = 0xffff * [nscolor alphaComponent];
|
||||
|
||||
stream = g_memory_input_stream_new_from_data (g_memdup2 (&color, sizeof color),
|
||||
sizeof color,
|
||||
g_free);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
NSData *data = [pasteboard dataForType:PTYPE(TIFF)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/png") == 0)
|
||||
{
|
||||
NSData *data = [pasteboard dataForType:PTYPE(PNG)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
|
||||
if (stream != NULL)
|
||||
{
|
||||
g_task_set_task_data (task, g_strdup (mime_type), g_free);
|
||||
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Failed to decode contents with mime-type of '%s'"),
|
||||
mime_type);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_clear_object (&task);
|
||||
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
GInputStream *
|
||||
_gdk_macos_pasteboard_read_finish (GObject *object,
|
||||
GAsyncResult *result,
|
||||
const char **out_mime_type,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task = (GTask *)result;
|
||||
|
||||
g_assert (G_IS_OBJECT (object));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (out_mime_type != NULL)
|
||||
*out_mime_type = g_strdup (g_task_get_task_data (task));
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_pasteboard_register_drag_types (NSWindow *window)
|
||||
{
|
||||
[window registerForDraggedTypes:[NSArray arrayWithObjects:PTYPE(STRING),
|
||||
PTYPE(PBOARD),
|
||||
PTYPE(URL),
|
||||
PTYPE(FILE_URL),
|
||||
PTYPE(COLOR),
|
||||
PTYPE(TIFF),
|
||||
PTYPE(PNG),
|
||||
nil]];
|
||||
}
|
||||
|
||||
@implementation GdkMacosPasteboardItemDataProvider
|
||||
|
||||
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
|
||||
{
|
||||
[super init];
|
||||
g_set_object (&self->_clipboard, clipboard);
|
||||
g_set_object (&self->_contentProvider, contentProvider);
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
|
||||
{
|
||||
[super init];
|
||||
g_set_object (&self->_drag, drag);
|
||||
g_set_object (&self->_contentProvider, contentProvider);
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_clear_object (&self->_contentProvider);
|
||||
g_clear_object (&self->_clipboard);
|
||||
g_clear_object (&self->_drag);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(NSArray<NSPasteboardType> *)types
|
||||
{
|
||||
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
||||
GdkContentFormats *serializable;
|
||||
const char * const *mime_types;
|
||||
gsize n_mime_types;
|
||||
|
||||
serializable = gdk_content_provider_ref_storable_formats (self->_contentProvider);
|
||||
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
|
||||
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
|
||||
|
||||
for (gsize i = 0; i < n_mime_types; i++)
|
||||
{
|
||||
const char *mime_type = mime_types[i];
|
||||
NSPasteboardType type;
|
||||
NSPasteboardType alternate = nil;
|
||||
|
||||
if ((type = _gdk_macos_pasteboard_to_ns_type (mime_type, &alternate)))
|
||||
{
|
||||
[ret addObject:type];
|
||||
if (alternate)
|
||||
[ret addObject:alternate];
|
||||
}
|
||||
}
|
||||
|
||||
gdk_content_formats_unref (serializable);
|
||||
|
||||
/* Default to an url type (think gobject://internal)
|
||||
* to support internal, GType-based DnD.
|
||||
*/
|
||||
if (n_mime_types == 0)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
gsize n_gtypes;
|
||||
|
||||
formats = gdk_content_provider_ref_formats (self->_contentProvider);
|
||||
gdk_content_formats_get_gtypes (formats, &n_gtypes);
|
||||
|
||||
if (n_gtypes)
|
||||
[ret addObject:NSPasteboardTypeURL];
|
||||
|
||||
gdk_content_formats_unref (formats);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&ret);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMemoryOutputStream *stream;
|
||||
NSPasteboardItem *item;
|
||||
NSPasteboardType type;
|
||||
GMainContext *main_context;
|
||||
guint done : 1;
|
||||
} WriteRequest;
|
||||
|
||||
static void
|
||||
write_request_free (WriteRequest *wr)
|
||||
{
|
||||
g_clear_pointer (&wr->main_context, g_main_context_unref);
|
||||
g_clear_object (&wr->stream);
|
||||
[wr->item release];
|
||||
g_slice_free (WriteRequest, wr);
|
||||
}
|
||||
|
||||
static void
|
||||
on_data_ready_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
WriteRequest *wr = user_data;
|
||||
GError *error = NULL;
|
||||
NSData *data = nil;
|
||||
gboolean ret;
|
||||
|
||||
g_assert (G_IS_OBJECT (object));
|
||||
g_assert (GDK_IS_CLIPBOARD (object) || GDK_IS_DRAG (object));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (wr != NULL);
|
||||
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
|
||||
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
|
||||
|
||||
if (GDK_IS_CLIPBOARD (object))
|
||||
ret = gdk_clipboard_write_finish (GDK_CLIPBOARD (object), result, &error);
|
||||
else if (GDK_IS_DRAG (object))
|
||||
ret = gdk_drag_write_finish (GDK_DRAG (object), result, &error);
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
if (ret)
|
||||
{
|
||||
gsize size;
|
||||
gpointer bytes;
|
||||
|
||||
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
|
||||
|
||||
size = g_memory_output_stream_get_data_size (wr->stream);
|
||||
bytes = g_memory_output_stream_steal_data (wr->stream);
|
||||
data = [[NSData alloc] initWithBytesNoCopy:bytes
|
||||
length:size
|
||||
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Failed to serialize pasteboard contents: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
[wr->item setData:data forType:wr->type];
|
||||
|
||||
wr->done = TRUE;
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
-(void)pasteboard:(NSPasteboard *)pasteboard item:(NSPasteboardItem *)item provideDataForType:(NSPasteboardType)type
|
||||
{
|
||||
const char *mime_type = _gdk_macos_pasteboard_from_ns_type (type);
|
||||
GMainContext *main_context = g_main_context_default ();
|
||||
WriteRequest *wr;
|
||||
|
||||
if (self->_contentProvider == NULL || mime_type == NULL)
|
||||
{
|
||||
[item setData:[NSData data] forType:type];
|
||||
return;
|
||||
}
|
||||
|
||||
wr = g_slice_new0 (WriteRequest);
|
||||
wr->item = [item retain];
|
||||
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
|
||||
wr->type = type;
|
||||
wr->main_context = g_main_context_ref (main_context);
|
||||
wr->done = FALSE;
|
||||
|
||||
if (GDK_IS_CLIPBOARD (self->_clipboard))
|
||||
gdk_clipboard_write_async (self->_clipboard,
|
||||
mime_type,
|
||||
G_OUTPUT_STREAM (wr->stream),
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_data_ready_cb,
|
||||
wr);
|
||||
else if (GDK_IS_DRAG (self->_drag))
|
||||
gdk_drag_write_async (self->_drag,
|
||||
mime_type,
|
||||
G_OUTPUT_STREAM (wr->stream),
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
on_data_ready_cb,
|
||||
wr);
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
/* We're forced to provide data synchronously via this API
|
||||
* so we must block on the main loop. Using another main loop
|
||||
* than the default tends to get us locked up here, so that is
|
||||
* what we'll do for now.
|
||||
*/
|
||||
while (!wr->done)
|
||||
g_main_context_iteration (wr->main_context, TRUE);
|
||||
|
||||
write_request_free (wr);
|
||||
}
|
||||
|
||||
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
|
||||
{
|
||||
g_clear_object (&self->_clipboard);
|
||||
g_clear_object (&self->_drag);
|
||||
g_clear_object (&self->_contentProvider);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GdkMacosPasteboardItem
|
||||
|
||||
-(id)initForClipboard:(GdkClipboard*)clipboard withContentProvider:(GdkContentProvider*)contentProvider
|
||||
{
|
||||
GdkMacosPasteboardItemDataProvider *dataProvider;
|
||||
|
||||
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForClipboard:clipboard withContentProvider:contentProvider];
|
||||
|
||||
[super init];
|
||||
g_set_object (&self->_clipboard, clipboard);
|
||||
g_set_object (&self->_contentProvider, contentProvider);
|
||||
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||
|
||||
[dataProvider release];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(id)initForDrag:(GdkDrag*)drag withContentProvider:(GdkContentProvider*)contentProvider
|
||||
{
|
||||
GdkMacosPasteboardItemDataProvider *dataProvider;
|
||||
|
||||
dataProvider = [[GdkMacosPasteboardItemDataProvider alloc] initForDrag:drag withContentProvider:contentProvider];
|
||||
|
||||
[super init];
|
||||
g_set_object (&self->_drag, drag);
|
||||
g_set_object (&self->_contentProvider, contentProvider);
|
||||
[self setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||
|
||||
[dataProvider release];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_clear_object (&self->_contentProvider);
|
||||
g_clear_object (&self->_clipboard);
|
||||
g_clear_object (&self->_drag);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(NSRect)draggingFrame
|
||||
{
|
||||
return self->_draggingFrame;
|
||||
}
|
||||
|
||||
-(void)setDraggingFrame:(NSRect)draggingFrame;
|
||||
{
|
||||
self->_draggingFrame = draggingFrame;
|
||||
}
|
||||
|
||||
-(id)item
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
-(NSArray* (^) (void))imageComponentsProvider
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -431,7 +431,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
||||
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
|
||||
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
|
||||
GDK_SURFACE_DRAG,
|
||||
surface,
|
||||
NULL,
|
||||
sx, sy, 1, 1);
|
||||
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
|
||||
"drag-surface", drag_surface,
|
||||
@@ -446,7 +446,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
|
||||
gdk_drag_get_selected_action (GDK_DRAG (drag)));
|
||||
gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
|
||||
|
||||
if (!_gdk_macos_drag_begin (drag))
|
||||
if (!_gdk_macos_drag_begin (drag, content, self->window))
|
||||
{
|
||||
g_object_unref (drag);
|
||||
return NULL;
|
||||
|
||||
@@ -19,6 +19,7 @@ gdk_macos_sources = files([
|
||||
'gdkmacoseventsource.c',
|
||||
'gdkmacoskeymap.c',
|
||||
'gdkmacosmonitor.c',
|
||||
'gdkmacospasteboard.c',
|
||||
'gdkmacospopupsurface.c',
|
||||
'gdkmacosseat.c',
|
||||
'gdkmacossurface.c',
|
||||
|
||||
@@ -87,7 +87,7 @@ gdk_wayland_app_launch_context_get_startup_notify_id (GAppLaunchContext *context
|
||||
xdg_activation_token_v1_commit (token);
|
||||
|
||||
while (app_launch_data.token == NULL)
|
||||
wl_display_dispatch_queue (display->wl_display, event_queue);
|
||||
gdk_wayland_display_dispatch_queue (GDK_DISPLAY (display), event_queue);
|
||||
|
||||
xdg_activation_token_v1_destroy (token);
|
||||
id = app_launch_data.token;
|
||||
|
||||
@@ -2,6 +2,236 @@
|
||||
#define __GDK_DEVICE_WAYLAND_PRIVATE_H__
|
||||
|
||||
#include "gdkwaylanddevice.h"
|
||||
#include "gdkwaylandseat.h"
|
||||
|
||||
#include <gdk/gdkdeviceprivate.h>
|
||||
#include <gdk/gdkkeysprivate.h>
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
struct _GdkWaylandDevice
|
||||
{
|
||||
GdkDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDeviceClass
|
||||
{
|
||||
GdkDeviceClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct _GdkWaylandTouchData GdkWaylandTouchData;
|
||||
typedef struct _GdkWaylandPointerFrameData GdkWaylandPointerFrameData;
|
||||
typedef struct _GdkWaylandPointerData GdkWaylandPointerData;
|
||||
typedef struct _GdkWaylandTabletPadGroupData GdkWaylandTabletPadGroupData;
|
||||
typedef struct _GdkWaylandTabletPadData GdkWaylandTabletPadData;
|
||||
typedef struct _GdkWaylandTabletData GdkWaylandTabletData;
|
||||
typedef struct _GdkWaylandTabletToolData GdkWaylandTabletToolData;
|
||||
|
||||
struct _GdkWaylandTouchData
|
||||
{
|
||||
uint32_t id;
|
||||
double x;
|
||||
double y;
|
||||
GdkSurface *surface;
|
||||
uint32_t touch_down_serial;
|
||||
guint initial_touch : 1;
|
||||
};
|
||||
|
||||
struct _GdkWaylandPointerFrameData
|
||||
{
|
||||
GdkEvent *event;
|
||||
|
||||
/* Specific to the scroll event */
|
||||
double delta_x, delta_y;
|
||||
int32_t value120_x, value120_y;
|
||||
gint8 is_scroll_stop;
|
||||
enum wl_pointer_axis_source source;
|
||||
};
|
||||
|
||||
struct _GdkWaylandPointerData {
|
||||
GdkSurface *focus;
|
||||
|
||||
double surface_x, surface_y;
|
||||
|
||||
GdkModifierType button_modifiers;
|
||||
|
||||
uint32_t time;
|
||||
uint32_t enter_serial;
|
||||
uint32_t press_serial;
|
||||
|
||||
GdkSurface *grab_surface;
|
||||
uint32_t grab_time;
|
||||
|
||||
struct wl_surface *pointer_surface;
|
||||
guint cursor_is_default: 1;
|
||||
GdkCursor *cursor;
|
||||
guint cursor_timeout_id;
|
||||
guint cursor_image_index;
|
||||
guint cursor_image_delay;
|
||||
guint touchpad_event_sequence;
|
||||
|
||||
guint current_output_scale;
|
||||
GSList *pointer_surface_outputs;
|
||||
|
||||
/* Accumulated event data for a pointer frame */
|
||||
GdkWaylandPointerFrameData frame;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletPadGroupData
|
||||
{
|
||||
GdkWaylandTabletPadData *pad;
|
||||
struct zwp_tablet_pad_group_v2 *wp_tablet_pad_group;
|
||||
GList *rings;
|
||||
GList *strips;
|
||||
GList *buttons;
|
||||
|
||||
guint mode_switch_serial;
|
||||
guint n_modes;
|
||||
guint current_mode;
|
||||
|
||||
struct {
|
||||
guint source;
|
||||
gboolean is_stop;
|
||||
double value;
|
||||
} axis_tmp_info;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletPadData
|
||||
{
|
||||
GdkSeat *seat;
|
||||
struct zwp_tablet_pad_v2 *wp_tablet_pad;
|
||||
GdkDevice *device;
|
||||
|
||||
GdkWaylandTabletData *current_tablet;
|
||||
|
||||
guint enter_serial;
|
||||
uint32_t n_buttons;
|
||||
char *path;
|
||||
|
||||
GList *rings;
|
||||
GList *strips;
|
||||
GList *mode_groups;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletToolData
|
||||
{
|
||||
GdkSeat *seat;
|
||||
struct zwp_tablet_tool_v2 *wp_tablet_tool;
|
||||
GdkAxisFlags axes;
|
||||
GdkDeviceToolType type;
|
||||
guint64 hardware_serial;
|
||||
guint64 hardware_id_wacom;
|
||||
|
||||
GdkDeviceTool *tool;
|
||||
GdkWaylandTabletData *current_tablet;
|
||||
};
|
||||
|
||||
struct _GdkWaylandTabletData
|
||||
{
|
||||
struct zwp_tablet_v2 *wp_tablet;
|
||||
char *name;
|
||||
char *path;
|
||||
uint32_t vid;
|
||||
uint32_t pid;
|
||||
|
||||
GdkDevice *logical_device;
|
||||
GdkDevice *stylus_device;
|
||||
GdkSeat *seat;
|
||||
GdkWaylandPointerData pointer_info;
|
||||
|
||||
GList *pads;
|
||||
|
||||
GdkWaylandTabletToolData *current_tool;
|
||||
|
||||
int axis_indices[GDK_AXIS_LAST];
|
||||
double axes[GDK_AXIS_LAST];
|
||||
};
|
||||
|
||||
struct _GdkWaylandSeat
|
||||
{
|
||||
GdkSeat parent_instance;
|
||||
|
||||
guint32 id;
|
||||
struct wl_seat *wl_seat;
|
||||
struct wl_pointer *wl_pointer;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
struct wl_touch *wl_touch;
|
||||
struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe;
|
||||
struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch;
|
||||
struct zwp_pointer_gesture_hold_v1 *wp_pointer_gesture_hold;
|
||||
struct zwp_tablet_seat_v2 *wp_tablet_seat;
|
||||
|
||||
GdkDisplay *display;
|
||||
|
||||
GdkDevice *logical_pointer;
|
||||
GdkDevice *logical_keyboard;
|
||||
GdkDevice *pointer;
|
||||
GdkDevice *wheel_scrolling;
|
||||
GdkDevice *finger_scrolling;
|
||||
GdkDevice *continuous_scrolling;
|
||||
GdkDevice *keyboard;
|
||||
GdkDevice *logical_touch;
|
||||
GdkDevice *touch;
|
||||
GdkCursor *cursor;
|
||||
GdkKeymap *keymap;
|
||||
|
||||
GHashTable *touches;
|
||||
GList *tablets;
|
||||
GList *tablet_tools;
|
||||
GList *tablet_pads;
|
||||
|
||||
GdkWaylandPointerData pointer_info;
|
||||
GdkWaylandPointerData touch_info;
|
||||
|
||||
GdkModifierType key_modifiers;
|
||||
GdkSurface *keyboard_focus;
|
||||
GdkSurface *grab_surface;
|
||||
uint32_t grab_time;
|
||||
gboolean have_server_repeat;
|
||||
uint32_t server_repeat_rate;
|
||||
uint32_t server_repeat_delay;
|
||||
|
||||
struct wl_data_offer *pending_offer;
|
||||
GdkContentFormatsBuilder *pending_builder;
|
||||
GdkDragAction pending_source_actions;
|
||||
GdkDragAction pending_action;
|
||||
|
||||
struct wl_callback *repeat_callback;
|
||||
guint32 repeat_timer;
|
||||
guint32 repeat_key;
|
||||
guint32 repeat_count;
|
||||
gint64 repeat_deadline;
|
||||
uint32_t keyboard_time;
|
||||
uint32_t keyboard_key_serial;
|
||||
|
||||
GdkClipboard *clipboard;
|
||||
GdkClipboard *primary_clipboard;
|
||||
struct wl_data_device *data_device;
|
||||
GdkDrag *drag;
|
||||
GdkDrop *drop;
|
||||
|
||||
/* Some tracking on gesture events */
|
||||
guint gesture_n_fingers;
|
||||
double gesture_scale;
|
||||
|
||||
GdkCursor *grab_cursor;
|
||||
};
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DEVICE_PAD (gdk_wayland_device_pad_get_type ())
|
||||
GType gdk_wayland_device_pad_get_type (void);
|
||||
|
||||
void gdk_wayland_seat_stop_cursor_animation (GdkWaylandSeat *seat,
|
||||
GdkWaylandPointerData *pointer);
|
||||
|
||||
GdkWaylandPointerData * gdk_wayland_device_get_pointer (GdkWaylandDevice *wayland_device);
|
||||
|
||||
void gdk_wayland_device_set_pointer (GdkWaylandDevice *wayland_device,
|
||||
GdkWaylandPointerData *pointer);
|
||||
|
||||
GdkWaylandTouchData * gdk_wayland_device_get_emulating_touch (GdkWaylandDevice *wayland_device);
|
||||
|
||||
void gdk_wayland_device_set_emulating_touch (GdkWaylandDevice *wayland_device,
|
||||
GdkWaylandTouchData *touch);
|
||||
|
||||
void gdk_wayland_device_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
@@ -14,4 +244,24 @@ void gdk_wayland_device_pad_set_feedback (GdkDevice *device,
|
||||
guint feature_idx,
|
||||
const char *label);
|
||||
|
||||
GdkWaylandTabletPadData * gdk_wayland_seat_find_pad (GdkWaylandSeat *seat,
|
||||
GdkDevice *device);
|
||||
|
||||
GdkWaylandTabletData * gdk_wayland_seat_find_tablet (GdkWaylandSeat *seat,
|
||||
GdkDevice *device);
|
||||
|
||||
GdkWaylandTouchData * gdk_wayland_seat_get_touch (GdkWaylandSeat *seat,
|
||||
uint32_t id);
|
||||
|
||||
void gdk_wayland_device_maybe_emit_grab_crossing (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
guint32 time);
|
||||
|
||||
GdkSurface * gdk_wayland_device_maybe_emit_ungrab_crossing (GdkDevice *device,
|
||||
guint32 time_);
|
||||
|
||||
gboolean gdk_wayland_device_update_surface_cursor (GdkDevice *device);
|
||||
|
||||
GdkModifierType gdk_wayland_device_get_modifiers (GdkDevice *device);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
266
gdk/wayland/gdkdevicepad-wayland.c
Normal file
266
gdk/wayland/gdkdevicepad-wayland.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkwaylanddevice.h"
|
||||
#include "gdkdevice-wayland-private.h"
|
||||
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
|
||||
#include <gdk/gdkdevicepadprivate.h>
|
||||
|
||||
typedef struct _GdkWaylandDevicePad GdkWaylandDevicePad;
|
||||
typedef struct _GdkWaylandDevicePadClass GdkWaylandDevicePadClass;
|
||||
|
||||
struct _GdkWaylandDevicePad
|
||||
{
|
||||
GdkWaylandDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkWaylandDevicePadClass
|
||||
{
|
||||
GdkWaylandDeviceClass parent_class;
|
||||
};
|
||||
|
||||
static void gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GdkWaylandDevicePad, gdk_wayland_device_pad,
|
||||
GDK_TYPE_WAYLAND_DEVICE,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_DEVICE_PAD,
|
||||
gdk_wayland_device_pad_iface_init))
|
||||
|
||||
static int
|
||||
gdk_wayland_device_pad_get_n_groups (GdkDevicePad *pad)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
#ifdef G_DISABLE_ASSERT
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
#else
|
||||
g_assert (data != NULL);
|
||||
#endif
|
||||
|
||||
return g_list_length (data->mode_groups);
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_wayland_device_pad_get_group_n_modes (GdkDevicePad *pad,
|
||||
int n_group)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
#ifdef G_DISABLE_ASSERT
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
#else
|
||||
g_assert (data != NULL);
|
||||
#endif
|
||||
|
||||
group = g_list_nth_data (data->mode_groups, n_group);
|
||||
if (!group)
|
||||
return -1;
|
||||
|
||||
return group->n_modes;
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_wayland_device_pad_get_n_features (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadData *data;
|
||||
|
||||
data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
g_assert (data != NULL);
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case GDK_DEVICE_PAD_FEATURE_BUTTON:
|
||||
return data->n_buttons;
|
||||
case GDK_DEVICE_PAD_FEATURE_RING:
|
||||
return g_list_length (data->rings);
|
||||
case GDK_DEVICE_PAD_FEATURE_STRIP:
|
||||
return g_list_length (data->strips);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_wayland_device_pad_get_feature_group (GdkDevicePad *pad,
|
||||
GdkDevicePadFeature feature,
|
||||
int idx)
|
||||
{
|
||||
GdkSeat *seat = gdk_device_get_seat (GDK_DEVICE (pad));
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkWaylandTabletPadData *data;
|
||||
GList *l;
|
||||
int i;
|
||||
|
||||
data = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat),
|
||||
GDK_DEVICE (pad));
|
||||
#ifdef G_DISABLE_ASSERT
|
||||
if (data == NULL)
|
||||
return -1;
|
||||
#else
|
||||
g_assert (data != NULL);
|
||||
#endif
|
||||
|
||||
for (l = data->mode_groups, i = 0; l; l = l->next, i++)
|
||||
{
|
||||
group = l->data;
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case GDK_DEVICE_PAD_FEATURE_BUTTON:
|
||||
if (g_list_find (group->buttons, GINT_TO_POINTER (idx)))
|
||||
return i;
|
||||
break;
|
||||
case GDK_DEVICE_PAD_FEATURE_RING:
|
||||
{
|
||||
gpointer ring;
|
||||
|
||||
ring = g_list_nth_data (data->rings, idx);
|
||||
if (ring && g_list_find (group->rings, ring))
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
case GDK_DEVICE_PAD_FEATURE_STRIP:
|
||||
{
|
||||
gpointer strip;
|
||||
strip = g_list_nth_data (data->strips, idx);
|
||||
if (strip && g_list_find (group->strips, strip))
|
||||
return i;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_iface_init (GdkDevicePadInterface *iface)
|
||||
{
|
||||
iface->get_n_groups = gdk_wayland_device_pad_get_n_groups;
|
||||
iface->get_group_n_modes = gdk_wayland_device_pad_get_group_n_modes;
|
||||
iface->get_n_features = gdk_wayland_device_pad_get_n_features;
|
||||
iface->get_feature_group = gdk_wayland_device_pad_get_feature_group;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_class_init (GdkWaylandDevicePadClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_device_pad_init (GdkWaylandDevicePad *pad)
|
||||
{
|
||||
}
|
||||
|
||||
static GdkWaylandTabletPadGroupData *
|
||||
tablet_pad_lookup_button_group (GdkWaylandTabletPadData *pad,
|
||||
uint32_t button)
|
||||
{
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GList *l;
|
||||
|
||||
for (l = pad->mode_groups; l; l = l->next)
|
||||
{
|
||||
group = l->data;
|
||||
|
||||
if (g_list_find (group->buttons, GUINT_TO_POINTER (button)))
|
||||
return group;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gdk_wayland_device_pad_set_feedback:
|
||||
* @device: (type GdkWaylandDevice): a %GDK_SOURCE_TABLET_PAD device
|
||||
* @feature: Feature to set the feedback label for
|
||||
* @feature_idx: 0-indexed index of the feature to set the feedback label for
|
||||
* @label: Feedback label
|
||||
*
|
||||
* Sets the feedback label for the given feature/index.
|
||||
*
|
||||
* This may be used by the compositor to provide user feedback
|
||||
* of the actions available/performed.
|
||||
*/
|
||||
void
|
||||
gdk_wayland_device_pad_set_feedback (GdkDevice *device,
|
||||
GdkDevicePadFeature feature,
|
||||
guint feature_idx,
|
||||
const char *label)
|
||||
{
|
||||
GdkWaylandTabletPadData *pad;
|
||||
GdkWaylandTabletPadGroupData *group;
|
||||
GdkSeat *seat;
|
||||
|
||||
seat = gdk_device_get_seat (device);
|
||||
pad = gdk_wayland_seat_find_pad (GDK_WAYLAND_SEAT (seat), device);
|
||||
if (!pad)
|
||||
return;
|
||||
|
||||
if (feature == GDK_DEVICE_PAD_FEATURE_BUTTON)
|
||||
{
|
||||
group = tablet_pad_lookup_button_group (pad, feature_idx);
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
zwp_tablet_pad_v2_set_feedback (pad->wp_tablet_pad, feature_idx, label,
|
||||
group->mode_switch_serial);
|
||||
}
|
||||
else if (feature == GDK_DEVICE_PAD_FEATURE_RING)
|
||||
{
|
||||
struct zwp_tablet_pad_ring_v2 *wp_pad_ring;
|
||||
|
||||
wp_pad_ring = g_list_nth_data (pad->rings, feature_idx);
|
||||
if (!wp_pad_ring)
|
||||
return;
|
||||
|
||||
group = zwp_tablet_pad_ring_v2_get_user_data (wp_pad_ring);
|
||||
zwp_tablet_pad_ring_v2_set_feedback (wp_pad_ring, label,
|
||||
group->mode_switch_serial);
|
||||
|
||||
}
|
||||
else if (feature == GDK_DEVICE_PAD_FEATURE_STRIP)
|
||||
{
|
||||
struct zwp_tablet_pad_strip_v2 *wp_pad_strip;
|
||||
|
||||
wp_pad_strip = g_list_nth_data (pad->strips, feature_idx);
|
||||
if (!wp_pad_strip)
|
||||
return;
|
||||
|
||||
group = zwp_tablet_pad_strip_v2_get_user_data (wp_pad_strip);
|
||||
zwp_tablet_pad_strip_v2_set_feedback (wp_pad_strip, label,
|
||||
group->mode_switch_serial);
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "gdkvulkancontext-wayland.h"
|
||||
#include "gdkwaylandmonitor.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktoplevel-wayland-private.h"
|
||||
#include <wayland/pointer-gestures-unstable-v1-client-protocol.h>
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||
@@ -831,6 +832,8 @@ gdk_wayland_display_get_next_serial (GdkDisplay *display)
|
||||
* if no ID has been defined.
|
||||
*
|
||||
* Returns: (nullable): the startup notification ID for @display
|
||||
*
|
||||
* Deprecated: 4.10.
|
||||
*/
|
||||
const char *
|
||||
gdk_wayland_display_get_startup_notification_id (GdkDisplay *display)
|
||||
@@ -852,6 +855,8 @@ gdk_wayland_display_get_startup_notification_id (GdkDisplay *display)
|
||||
* The startup ID is also what is used to signal that the startup is
|
||||
* complete (for example, when opening a window or when calling
|
||||
* [method@Gdk.Display.notify_startup_complete]).
|
||||
*
|
||||
* Deprecated: 4.10. Use [method@Gdk.Toplevel.set_startup_id]
|
||||
*/
|
||||
void
|
||||
gdk_wayland_display_set_startup_notification_id (GdkDisplay *display,
|
||||
@@ -980,7 +985,9 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass *class)
|
||||
display_class->queue_events = _gdk_wayland_display_queue_events;
|
||||
display_class->get_app_launch_context = _gdk_wayland_display_get_app_launch_context;
|
||||
display_class->get_next_serial = gdk_wayland_display_get_next_serial;
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
display_class->get_startup_notification_id = gdk_wayland_display_get_startup_notification_id;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
display_class->notify_startup_complete = gdk_wayland_display_notify_startup_complete;
|
||||
display_class->create_surface = _gdk_wayland_display_create_surface;
|
||||
display_class->get_keymap = _gdk_wayland_display_get_keymap;
|
||||
@@ -2325,6 +2332,7 @@ apply_monitor_change (GdkWaylandMonitor *monitor)
|
||||
monitor->x, monitor->y,
|
||||
monitor->width, monitor->height });
|
||||
gdk_monitor_set_connector (GDK_MONITOR (monitor), monitor->name);
|
||||
gdk_monitor_set_description (GDK_MONITOR (monitor), monitor->description);
|
||||
monitor->wl_output_done = FALSE;
|
||||
monitor->xdg_output_done = FALSE;
|
||||
|
||||
@@ -2381,7 +2389,7 @@ xdg_output_handle_name (void *data,
|
||||
{
|
||||
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
|
||||
|
||||
GDK_DEBUG (MISC, "handle name xdg-output %d", monitor->id);
|
||||
GDK_DEBUG (MISC, "handle name xdg-output %d: %s", monitor->id, name);
|
||||
|
||||
monitor->name = g_strdup (name);
|
||||
}
|
||||
@@ -2391,8 +2399,11 @@ xdg_output_handle_description (void *data,
|
||||
struct zxdg_output_v1 *xdg_output,
|
||||
const char *description)
|
||||
{
|
||||
GDK_DEBUG (MISC, "handle description xdg-output %d",
|
||||
((GdkWaylandMonitor *)data)->id);
|
||||
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *) data;
|
||||
|
||||
GDK_DEBUG (MISC, "handle description xdg-output %d: %s", monitor->id, description);
|
||||
|
||||
monitor->description = g_strdup (description);
|
||||
}
|
||||
|
||||
static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||
@@ -2683,3 +2694,17 @@ gdk_wayland_display_query_registry (GdkDisplay *display,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_display_dispatch_queue (GdkDisplay *display,
|
||||
struct wl_event_queue *event_queue)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
if (wl_display_dispatch_queue (display_wayland->wl_display, event_queue) == -1)
|
||||
{
|
||||
g_message ("Error %d (%s) dispatching to Wayland display.",
|
||||
errno, g_strerror (errno));
|
||||
_exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,9 @@ struct _GdkWaylandDisplayClass
|
||||
|
||||
gboolean gdk_wayland_display_prefers_ssd (GdkDisplay *display);
|
||||
|
||||
void gdk_wayland_display_dispatch_queue (GdkDisplay *display,
|
||||
struct wl_event_queue *event_queue);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WAYLAND_DISPLAY__ */
|
||||
|
||||
@@ -367,10 +367,10 @@ _gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
GdkWaylandDrag *drag_wayland;
|
||||
GdkDrag *drag;
|
||||
GdkSeat *seat;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
GdkDisplay *display;
|
||||
GdkCursor *cursor;
|
||||
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_device_get_display (device));
|
||||
display = gdk_device_get_display (device);
|
||||
seat = gdk_device_get_seat (device);
|
||||
|
||||
drag_wayland = g_object_new (GDK_TYPE_WAYLAND_DRAG,
|
||||
@@ -382,17 +382,13 @@ _gdk_wayland_surface_drag_begin (GdkSurface *surface,
|
||||
|
||||
drag = GDK_DRAG (drag_wayland);
|
||||
|
||||
drag_wayland->dnd_surface = create_dnd_surface (gdk_surface_get_display (surface));
|
||||
drag_wayland->dnd_surface = _gdk_wayland_display_create_surface (display, GDK_SURFACE_DRAG, NULL, 0, 0, 100, 100);
|
||||
drag_wayland->dnd_wl_surface = gdk_wayland_surface_get_wl_surface (drag_wayland->dnd_surface);
|
||||
|
||||
|
||||
gdk_wayland_drag_create_data_source (drag);
|
||||
|
||||
if (display_wayland->data_device_manager_version >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
{
|
||||
wl_data_source_set_actions (drag_wayland->data_source,
|
||||
gdk_to_wl_actions (actions));
|
||||
}
|
||||
if (GDK_WAYLAND_DISPLAY (display)->data_device_manager_version >= WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION)
|
||||
wl_data_source_set_actions (drag_wayland->data_source, gdk_to_wl_actions (actions));
|
||||
|
||||
gdk_wayland_seat_set_drag (seat, drag);
|
||||
|
||||
|
||||
136
gdk/wayland/gdkdragsurface-wayland.c
Normal file
136
gdk/wayland/gdkdragsurface-wayland.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright © 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdksurface-wayland.h"
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdisplay-wayland.h"
|
||||
#include "gdkdragsurfaceprivate.h"
|
||||
#include "gdkeventsprivate.h"
|
||||
#include "gdkframeclockidleprivate.h"
|
||||
#include "gdkglcontext-wayland.h"
|
||||
#include "gdkmonitor-wayland.h"
|
||||
#include "gdkpopupprivate.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkprivate-wayland.h"
|
||||
#include "gdkseat-wayland.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdktoplevelprivate.h"
|
||||
#include "gdkdevice-wayland-private.h"
|
||||
|
||||
#include <wayland/xdg-shell-unstable-v6-client-protocol.h>
|
||||
#include <wayland/xdg-foreign-unstable-v2-client-protocol.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gdksurface-wayland-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkWaylandSurface parent_instance;
|
||||
} GdkWaylandDragSurface;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkWaylandSurfaceClass parent_class;
|
||||
} GdkWaylandDragSurfaceClass;
|
||||
|
||||
static void gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface);
|
||||
|
||||
#define GDK_IS_WAYLAND_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DRAG_SURFACE))
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GdkWaylandDragSurface, gdk_wayland_drag_surface, GDK_TYPE_WAYLAND_SURFACE,
|
||||
G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE,
|
||||
gdk_wayland_drag_surface_iface_init))
|
||||
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_surface_init (GdkWaylandDragSurface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_drag_surface_compute_size (GdkSurface *surface)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (impl->next_layout.surface_geometry_dirty)
|
||||
{
|
||||
gdk_wayland_surface_update_size (surface,
|
||||
impl->next_layout.configured_width,
|
||||
impl->next_layout.configured_height,
|
||||
impl->scale);
|
||||
|
||||
impl->next_layout.surface_geometry_dirty = FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_surface_class_init (GdkWaylandDragSurfaceClass *class)
|
||||
{
|
||||
GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (class);
|
||||
|
||||
surface_class->compute_size = gdk_wayland_drag_surface_compute_size;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_notify_mapped (GdkSurface *surface)
|
||||
{
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
if (!GDK_SURFACE_IS_MAPPED (surface))
|
||||
gdk_surface_set_is_mapped (surface, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_wayland_drag_surface_present (GdkDragSurface *drag_surface,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (drag_surface);
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
|
||||
if (!impl->display_server.wl_surface)
|
||||
gdk_wayland_surface_create_wl_surface (surface);
|
||||
|
||||
impl->next_layout.configured_width = width;
|
||||
impl->next_layout.configured_height = height;
|
||||
impl->next_layout.surface_geometry_dirty = TRUE;
|
||||
gdk_surface_request_layout (surface);
|
||||
|
||||
maybe_notify_mapped (surface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_drag_surface_iface_init (GdkDragSurfaceInterface *iface)
|
||||
{
|
||||
iface->present = gdk_wayland_drag_surface_present;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ gdk_wayland_monitor_finalize (GObject *object)
|
||||
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)object;
|
||||
|
||||
g_free (monitor->name);
|
||||
g_free (monitor->description);
|
||||
|
||||
g_clear_pointer (&monitor->xdg_output, zxdg_output_v1_destroy);
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ struct _GdkWaylandMonitor {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
char *name;
|
||||
char *description;
|
||||
gboolean wl_output_done;
|
||||
gboolean xdg_output_done;
|
||||
};
|
||||
|
||||
1464
gdk/wayland/gdkpopup-wayland.c
Normal file
1464
gdk/wayland/gdkpopup-wayland.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -191,8 +191,6 @@ void gdk_wayland_surface_restore_shortcuts (GdkSurface *surface,
|
||||
|
||||
void gdk_wayland_surface_update_scale (GdkSurface *surface);
|
||||
|
||||
GdkSurface * create_dnd_surface (GdkDisplay *display);
|
||||
|
||||
GdkModifierType gdk_wayland_keymap_get_gdk_modifiers (GdkKeymap *keymap,
|
||||
guint32 mods);
|
||||
|
||||
|
||||
4423
gdk/wayland/gdkseat-wayland.c
Normal file
4423
gdk/wayland/gdkseat-wayland.c
Normal file
File diff suppressed because it is too large
Load Diff
121
gdk/wayland/gdksurface-wayland-private.h
Normal file
121
gdk/wayland/gdksurface-wayland-private.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright © 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum _PopupState
|
||||
{
|
||||
POPUP_STATE_IDLE,
|
||||
POPUP_STATE_WAITING_FOR_REPOSITIONED,
|
||||
POPUP_STATE_WAITING_FOR_CONFIGURE,
|
||||
POPUP_STATE_WAITING_FOR_FRAME,
|
||||
} PopupState;
|
||||
|
||||
struct _GdkWaylandSurface
|
||||
{
|
||||
GdkSurface parent_instance;
|
||||
|
||||
struct {
|
||||
GSList *outputs;
|
||||
struct wl_surface *wl_surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct zxdg_surface_v6 *zxdg_surface_v6;
|
||||
struct wl_egl_window *egl_window;
|
||||
} display_server;
|
||||
|
||||
struct wl_event_queue *event_queue;
|
||||
|
||||
unsigned int initial_configure_received : 1;
|
||||
unsigned int has_uncommitted_ack_configure : 1;
|
||||
unsigned int mapped : 1;
|
||||
unsigned int awaiting_frame : 1;
|
||||
unsigned int awaiting_frame_frozen : 1;
|
||||
|
||||
int pending_buffer_offset_x;
|
||||
int pending_buffer_offset_y;
|
||||
|
||||
gint64 pending_frame_counter;
|
||||
guint32 scale;
|
||||
|
||||
int shadow_left;
|
||||
int shadow_right;
|
||||
int shadow_top;
|
||||
int shadow_bottom;
|
||||
|
||||
cairo_region_t *opaque_region;
|
||||
gboolean opaque_region_dirty;
|
||||
|
||||
cairo_region_t *input_region;
|
||||
gboolean input_region_dirty;
|
||||
|
||||
GdkRectangle last_sent_window_geometry;
|
||||
|
||||
struct {
|
||||
gboolean is_initial_configure;
|
||||
uint32_t serial;
|
||||
gboolean is_dirty;
|
||||
} pending;
|
||||
|
||||
struct {
|
||||
int configured_width;
|
||||
int configured_height;
|
||||
gboolean surface_geometry_dirty;
|
||||
} next_layout;
|
||||
|
||||
uint32_t last_configure_serial;
|
||||
|
||||
int state_freeze_count;
|
||||
};
|
||||
|
||||
typedef struct _GdkWaylandSurfaceClass GdkWaylandSurfaceClass;
|
||||
struct _GdkWaylandSurfaceClass
|
||||
{
|
||||
GdkSurfaceClass parent_class;
|
||||
|
||||
void (* handle_configure) (GdkWaylandSurface *surface);
|
||||
|
||||
void (* handle_frame) (GdkWaylandSurface *surface);
|
||||
|
||||
void (* hide_surface) (GdkWaylandSurface *surface);
|
||||
};
|
||||
|
||||
#define GDK_WAYLAND_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
|
||||
|
||||
#define GDK_WAYLAND_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
|
||||
|
||||
void gdk_wayland_surface_create_wl_surface (GdkSurface *surface);
|
||||
void gdk_wayland_surface_update_size (GdkSurface *surface,
|
||||
int32_t width,
|
||||
int32_t height,
|
||||
int scale);
|
||||
void gdk_wayland_surface_create_xdg_surface_resources (GdkSurface *surface);
|
||||
void _gdk_wayland_surface_save_size (GdkSurface *surface);
|
||||
|
||||
void gdk_wayland_surface_hide_surface (GdkSurface *surface);
|
||||
void gdk_wayland_surface_move_resize (GdkSurface *surface,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
void gdk_wayland_surface_get_window_geometry (GdkSurface *surface,
|
||||
GdkRectangle *geometry);
|
||||
void gdk_wayland_surface_freeze_state (GdkSurface *surface);
|
||||
void gdk_wayland_surface_thaw_state (GdkSurface *surface);
|
||||
|
||||
|
||||
#define GDK_TYPE_WAYLAND_DRAG_SURFACE (gdk_wayland_drag_surface_get_type ())
|
||||
GType gdk_wayland_drag_surface_get_type (void) G_GNUC_CONST;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,26 +21,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkwaylandsurface.h"
|
||||
#include "gdkwaylandtoplevel.h"
|
||||
#include "gdkwaylandpopup.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
|
||||
const char *application_id,
|
||||
const char *app_menu_path,
|
||||
const char *menubar_path,
|
||||
const char *window_object_path,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name);
|
||||
|
||||
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
|
||||
|
||||
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
|
||||
|
||||
|
||||
struct gtk_surface1 * gdk_wayland_toplevel_get_gtk_surface (GdkWaylandToplevel *wayland_toplevel);
|
||||
|
||||
void gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
41
gdk/wayland/gdktoplevel-wayland-private.h
Normal file
41
gdk/wayland/gdktoplevel-wayland-private.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright © 2022 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
void gdk_wayland_toplevel_set_geometry_hints (GdkWaylandToplevel *toplevel,
|
||||
const GdkGeometry *geometry,
|
||||
GdkSurfaceHints geom_mask);
|
||||
|
||||
struct gtk_surface1 *
|
||||
gdk_wayland_toplevel_get_gtk_surface (GdkWaylandToplevel *wayland_toplevel);
|
||||
|
||||
void gdk_wayland_toplevel_set_dbus_properties (GdkToplevel *toplevel,
|
||||
const char *application_id,
|
||||
const char *app_menu_path,
|
||||
const char *menubar_path,
|
||||
const char *window_object_path,
|
||||
const char *application_object_path,
|
||||
const char *unique_bus_name);
|
||||
|
||||
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
|
||||
|
||||
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
|
||||
|
||||
2560
gdk/wayland/gdktoplevel-wayland.c
Normal file
2560
gdk/wayland/gdktoplevel-wayland.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -31,10 +31,12 @@
|
||||
|
||||
#include <gdk/wayland/gdkwaylanddevice.h>
|
||||
#include <gdk/wayland/gdkwaylanddisplay.h>
|
||||
#include <gdk/wayland/gdkwaylandglcontext.h>
|
||||
#include <gdk/wayland/gdkwaylandmonitor.h>
|
||||
#include <gdk/wayland/gdkwaylandpopup.h>
|
||||
#include <gdk/wayland/gdkwaylandseat.h>
|
||||
#include <gdk/wayland/gdkwaylandsurface.h>
|
||||
#include <gdk/wayland/gdkwaylandglcontext.h>
|
||||
#include <gdk/wayland/gdkwaylandtoplevel.h>
|
||||
|
||||
#undef __GDKWAYLAND_H_INSIDE__
|
||||
|
||||
|
||||
@@ -53,9 +53,9 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_display_set_cursor_theme (GdkDisplay *display,
|
||||
const char *name,
|
||||
int size);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10
|
||||
const char * gdk_wayland_display_get_startup_notification_id (GdkDisplay *display);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GDK_DEPRECATED_IN_4_10_FOR(gdk_toplevel_set_startup_id)
|
||||
void gdk_wayland_display_set_startup_notification_id (GdkDisplay *display,
|
||||
const char *startup_id);
|
||||
|
||||
|
||||
44
gdk/wayland/gdkwaylandpopup.h
Normal file
44
gdk/wayland/gdkwaylandpopup.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2013 Jan Arne Petersen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDKWAYLAND_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/wayland/gdkwayland.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/wayland/gdkwaylandsurface.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef GTK_COMPILATION
|
||||
typedef struct _GdkWaylandPopup GdkWaylandPopup;
|
||||
#else
|
||||
typedef GdkPopup GdkWaylandPopup;
|
||||
#endif
|
||||
|
||||
#define GDK_TYPE_WAYLAND_POPUP (gdk_wayland_popup_get_type())
|
||||
#define GDK_WAYLAND_POPUP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_POPUP, GdkWaylandPopup))
|
||||
#define GDK_IS_WAYLAND_POPUP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_POPUP))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_popup_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -30,59 +30,20 @@ G_BEGIN_DECLS
|
||||
|
||||
#ifdef GTK_COMPILATION
|
||||
typedef struct _GdkWaylandSurface GdkWaylandSurface;
|
||||
typedef struct _GdkWaylandToplevel GdkWaylandToplevel;
|
||||
typedef struct _GdkWaylandPopup GdkWaylandPopup;
|
||||
#else
|
||||
typedef GdkSurface GdkWaylandSurface;
|
||||
typedef GdkToplevel GdkWaylandToplevel;
|
||||
typedef GdkPopup GdkWaylandPopup;
|
||||
#endif
|
||||
|
||||
#define GDK_TYPE_WAYLAND_SURFACE (gdk_wayland_surface_get_type())
|
||||
#define GDK_WAYLAND_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurface))
|
||||
#define GDK_IS_WAYLAND_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SURFACE))
|
||||
|
||||
#define GDK_TYPE_WAYLAND_TOPLEVEL (gdk_wayland_toplevel_get_type())
|
||||
#define GDK_WAYLAND_TOPLEVEL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_TOPLEVEL, GdkWaylandToplevel))
|
||||
#define GDK_IS_WAYLAND_TOPLEVEL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_TOPLEVEL))
|
||||
|
||||
#define GDK_TYPE_WAYLAND_POPUP (gdk_wayland_popup_get_type())
|
||||
#define GDK_WAYLAND_POPUP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_POPUP, GdkWaylandPopup))
|
||||
#define GDK_IS_WAYLAND_POPUP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_POPUP))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_surface_get_type (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_toplevel_get_type (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_popup_get_type (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
struct wl_surface *gdk_wayland_surface_get_wl_surface (GdkSurface *surface);
|
||||
|
||||
typedef void (*GdkWaylandToplevelExported) (GdkToplevel *toplevel,
|
||||
const char *handle,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_wayland_toplevel_export_handle (GdkToplevel *toplevel,
|
||||
GdkWaylandToplevelExported callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy_func);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_toplevel_unexport_handle (GdkToplevel *toplevel);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
|
||||
const char *parent_handle_str);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
|
||||
const char *application_id);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_WAYLAND_SURFACE_H__ */
|
||||
|
||||
66
gdk/wayland/gdkwaylandtoplevel.h
Normal file
66
gdk/wayland/gdkwaylandtoplevel.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2013 Jan Arne Petersen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDKWAYLAND_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/wayland/gdkwayland.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/wayland/gdkwaylandsurface.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef GTK_COMPILATION
|
||||
typedef struct _GdkWaylandToplevel GdkWaylandToplevel;
|
||||
#else
|
||||
typedef GdkToplevel GdkWaylandToplevel;
|
||||
#endif
|
||||
|
||||
#define GDK_TYPE_WAYLAND_TOPLEVEL (gdk_wayland_toplevel_get_type())
|
||||
#define GDK_WAYLAND_TOPLEVEL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_TOPLEVEL, GdkWaylandToplevel))
|
||||
#define GDK_IS_WAYLAND_TOPLEVEL(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_TOPLEVEL))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_wayland_toplevel_get_type (void);
|
||||
|
||||
|
||||
typedef void (*GdkWaylandToplevelExported) (GdkToplevel *toplevel,
|
||||
const char *handle,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_wayland_toplevel_export_handle (GdkToplevel *toplevel,
|
||||
GdkWaylandToplevelExported callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy_func);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_toplevel_unexport_handle (GdkToplevel *toplevel);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
|
||||
const char *parent_handle_str);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_wayland_toplevel_set_application_id (GdkToplevel *toplevel,
|
||||
const char *application_id);
|
||||
|
||||
G_END_DECLS
|
||||
@@ -6,16 +6,21 @@ gdk_wayland_sources = files([
|
||||
'gdkclipboard-wayland.c',
|
||||
'gdkcursor-wayland.c',
|
||||
'gdkdevice-wayland.c',
|
||||
'gdkdevicepad-wayland.c',
|
||||
'gdkdisplay-wayland.c',
|
||||
'gdkdrag-wayland.c',
|
||||
'gdkdragsurface-wayland.c',
|
||||
'gdkdrop-wayland.c',
|
||||
'gdkeventsource.c',
|
||||
'gdkglcontext-wayland.c',
|
||||
'gdkkeys-wayland.c',
|
||||
'gdkkeymap-wayland.c',
|
||||
'gdkmonitor-wayland.c',
|
||||
'gdkprimary-wayland.c',
|
||||
'gdkvulkancontext-wayland.c',
|
||||
'gdkseat-wayland.c',
|
||||
'gdksurface-wayland.c',
|
||||
'gdktoplevel-wayland.c',
|
||||
'gdkpopup-wayland.c',
|
||||
'gdkvulkancontext-wayland.c',
|
||||
'wm-button-layout-translation.c',
|
||||
])
|
||||
|
||||
@@ -24,8 +29,10 @@ gdk_wayland_public_headers = files([
|
||||
'gdkwaylanddisplay.h',
|
||||
'gdkwaylandglcontext.h',
|
||||
'gdkwaylandmonitor.h',
|
||||
'gdkwaylandpopup.h',
|
||||
'gdkwaylandseat.h',
|
||||
'gdkwaylandsurface.h',
|
||||
'gdkwaylandtoplevel.h',
|
||||
])
|
||||
|
||||
install_headers(gdk_wayland_public_headers, 'gdkwayland.h', subdir: 'gtk-4.0/gdk/wayland/')
|
||||
|
||||
@@ -631,6 +631,14 @@ gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
|
||||
return wglMakeCurrent (NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_wgl_is_current (GdkGLContext *context)
|
||||
{
|
||||
GdkWin32GLContextWGL *self = GDK_WIN32_GL_CONTEXT_WGL (context);
|
||||
|
||||
return self->wgl_context == wglGetCurrentContext ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
@@ -682,6 +690,7 @@ gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
|
||||
context_class->realize = gdk_win32_gl_context_wgl_realize;
|
||||
context_class->make_current = gdk_win32_gl_context_wgl_make_current;
|
||||
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
|
||||
context_class->is_current = gdk_win32_gl_context_wgl_is_current;
|
||||
|
||||
draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
|
||||
draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;
|
||||
|
||||
@@ -740,7 +740,6 @@ GPtrArray *
|
||||
_gdk_win32_display_get_monitor_list (GdkWin32Display *win32_display)
|
||||
{
|
||||
EnumMonitorData data;
|
||||
int i;
|
||||
|
||||
data.display = win32_display;
|
||||
data.monitors = get_monitor_devices (win32_display);
|
||||
|
||||
@@ -283,6 +283,9 @@ gdk_x11_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
|
||||
GFileInfo *fileinfo;
|
||||
GdkAppLaunchContext *ctx;
|
||||
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
ctx = GDK_APP_LAUNCH_CONTEXT (context);
|
||||
|
||||
display = ctx->display;
|
||||
|
||||
@@ -1450,7 +1450,9 @@ _gdk_device_manager_xi2_handle_focus (GdkSurface *surface,
|
||||
GdkEvent *event;
|
||||
|
||||
event = gdk_focus_event_new (surface, device, focus_in);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gdk_display_put_event (gdk_surface_get_display (surface), event);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
gdk_event_unref (event);
|
||||
}
|
||||
}
|
||||
@@ -2064,19 +2066,10 @@ gdk_x11_device_manager_xi2_translate_event (GdkEventTranslator *translator,
|
||||
xev->detail != XINotifyInferior && xev->mode != XINotifyPassiveUngrab &&
|
||||
GDK_IS_TOPLEVEL (surface))
|
||||
{
|
||||
if (gdk_x11_device_xi2_get_device_type ((GdkX11DeviceXI2 *) device) != GDK_X11_DEVICE_TYPE_LOGICAL)
|
||||
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (source_device));
|
||||
else
|
||||
{
|
||||
GList *physical_devices, *l;
|
||||
GList *l;
|
||||
|
||||
physical_devices = gdk_device_list_physical_devices (source_device);
|
||||
|
||||
for (l = physical_devices; l; l = l->next)
|
||||
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
|
||||
|
||||
g_list_free (physical_devices);
|
||||
}
|
||||
for (l = device_manager->devices; l; l = l->next)
|
||||
_gdk_device_xi2_reset_scroll_valuators (GDK_X11_DEVICE_XI2 (l->data));
|
||||
}
|
||||
|
||||
event = gdk_crossing_event_new (ev->evtype == XI_Enter
|
||||
|
||||
@@ -2074,8 +2074,10 @@ gdk_x11_display_make_default (GdkDisplay *display)
|
||||
display_x11->startup_notification_id = NULL;
|
||||
|
||||
startup_id = gdk_get_startup_notification_id ();
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
if (startup_id)
|
||||
gdk_x11_display_set_startup_notification_id (display, startup_id);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2303,6 +2305,8 @@ gdk_x11_display_get_user_time (GdkDisplay *display)
|
||||
* Gets the startup notification ID for a display.
|
||||
*
|
||||
* Returns: the startup notification ID for @display
|
||||
*
|
||||
* Deprecated: 4.10
|
||||
*/
|
||||
const char *
|
||||
gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
|
||||
@@ -2329,7 +2333,9 @@ gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
|
||||
* The startup ID is also what is used to signal that the startup is
|
||||
* complete (for example, when opening a window or when calling
|
||||
* gdk_display_notify_startup_complete()).
|
||||
**/
|
||||
*
|
||||
* Deprecated: 4.10: Using [method@Gdk.Toplevel.set_startup_id] is sufficient
|
||||
*/
|
||||
void
|
||||
gdk_x11_display_set_startup_notification_id (GdkDisplay *display,
|
||||
const char *startup_id)
|
||||
@@ -3042,7 +3048,9 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
|
||||
display_class->get_app_launch_context = _gdk_x11_display_get_app_launch_context;
|
||||
|
||||
display_class->get_next_serial = gdk_x11_display_get_next_serial;
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
display_class->get_startup_notification_id = gdk_x11_display_get_startup_notification_id;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
display_class->notify_startup_complete = gdk_x11_display_notify_startup_complete;
|
||||
display_class->create_surface = _gdk_x11_display_create_surface;
|
||||
display_class->get_keymap = gdk_x11_display_get_keymap;
|
||||
|
||||
@@ -119,7 +119,9 @@ handle_focus_change (GdkEvent *event)
|
||||
focus_event = gdk_focus_event_new (gdk_event_get_surface (event),
|
||||
gdk_event_get_device (event),
|
||||
focus_in);
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gdk_display_put_event (gdk_event_get_display (event), focus_event);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
gdk_event_unref (focus_event);
|
||||
}
|
||||
}
|
||||
@@ -206,7 +208,9 @@ handle_touch_synthetic_crossing (GdkEvent *event)
|
||||
|
||||
if (crossing)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
gdk_display_put_event (gdk_seat_get_display (seat), crossing);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
gdk_event_unref (crossing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,6 +210,14 @@ gdk_x11_gl_context_glx_clear_current (GdkGLContext *context)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_gl_context_glx_is_current (GdkGLContext *context)
|
||||
{
|
||||
GdkX11GLContextGLX *self = GDK_X11_GL_CONTEXT_GLX (context);
|
||||
|
||||
return self->glx_context == glXGetCurrentContext ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
|
||||
gboolean surfaceless)
|
||||
@@ -685,6 +693,7 @@ gdk_x11_gl_context_glx_class_init (GdkX11GLContextGLXClass *klass)
|
||||
context_class->realize = gdk_x11_gl_context_glx_realize;
|
||||
context_class->make_current = gdk_x11_gl_context_glx_make_current;
|
||||
context_class->clear_current = gdk_x11_gl_context_glx_clear_current;
|
||||
context_class->is_current = gdk_x11_gl_context_glx_is_current;
|
||||
context_class->get_damage = gdk_x11_gl_context_glx_get_damage;
|
||||
|
||||
draw_context_class->end_frame = gdk_x11_gl_context_glx_end_frame;
|
||||
|
||||
@@ -982,7 +982,7 @@ gdk_x11_selection_output_streams_request (GdkDisplay *display,
|
||||
GOutputStream *stream;
|
||||
|
||||
if (special_targets[i].mime_type)
|
||||
mime_type = gdk_intern_mime_type (special_targets[i].mime_type);
|
||||
gdk_intern_mime_type (special_targets[i].mime_type);
|
||||
stream = gdk_x11_selection_output_stream_new (display,
|
||||
notify,
|
||||
requestor,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user