Compare commits
553 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 258233efa9 | |||
| 59bf76dce1 | |||
| 44a2a49f31 | |||
| 69bc42f444 | |||
| 269535c844 | |||
| c7f773f3e3 | |||
| c6da0c9a7a | |||
| d098cd5865 | |||
| 4dc8ab58a3 | |||
| 5680393f9d | |||
| aadcec3d1e | |||
| 5fd936beef | |||
| 563b80d434 | |||
| f4f0f0e6a0 | |||
| ba9b0c6f7d | |||
| 3ce3de98da | |||
| 1cd934e105 | |||
| dc1d3824a2 | |||
| 927e49ed86 | |||
| d55fc8b7b1 | |||
| e72d0a9118 | |||
| 8b14c8d0a8 | |||
| 913b4fcc49 | |||
| fb7d033953 | |||
| cfa440bbae | |||
| 7ac9fe3b60 | |||
| b0a8b7da63 | |||
| b2ff6e91cd | |||
| b4d906c464 | |||
| ae03caacc4 | |||
| ec22646210 | |||
| ba1644cba1 | |||
| d11bc68b27 | |||
| 5720e406b9 | |||
| b3f8f358b5 | |||
| e458ea2f3d | |||
| b6d8d3975e | |||
| 5e96129be1 | |||
| 0ef7d07880 | |||
| 545e95bb5c | |||
| ca76675a69 | |||
| 16d4ce4d03 | |||
| 58e273d056 | |||
| 1c14285dee | |||
| cd69570e78 | |||
| 52b9e4703b | |||
| d7193eaf8b | |||
| b52dea7a10 | |||
| 7bb5888272 | |||
| 4404afc9f3 | |||
| dadac6a9e1 | |||
| 210a06174d | |||
| f9a5a474f0 | |||
| c51f1fda28 | |||
| ea3d0c0f01 | |||
| 2c1198f6c2 | |||
| 9d3120cc1e | |||
| 66d3aa8101 | |||
| 0530637fef | |||
| 3d6bdb9af3 | |||
| 7e7c90961c | |||
| 3da9280a8a | |||
| ed17a8ddd7 | |||
| cd7e70680c | |||
| a80007ac12 | |||
| dc68d04c32 | |||
| bd95e16372 | |||
| c1e1e2da80 | |||
| ea8f1469c1 | |||
| 1d3aa9207c | |||
| b4f2a3416e | |||
| 3b46e2a558 | |||
| 480a04131c | |||
| 171a710a23 | |||
| 4f532a414c | |||
| 3f567781dd | |||
| 0397c8b628 | |||
| 3939824d11 | |||
| d7cafca118 | |||
| d10709c917 | |||
| e9d4823c57 | |||
| 06d764d046 | |||
| 325badc3eb | |||
| c665a1d5a5 | |||
| c7f1a275ac | |||
| a52989842e | |||
| 1df276f263 | |||
| 615f10f7c8 | |||
| 38cba6895a | |||
| e95e045898 | |||
| 1b730dcf31 | |||
| beb9ee6d4a | |||
| 8ce6d03c7b | |||
| 904202a636 | |||
| 7a0b6a3639 | |||
| b465e04ae2 | |||
| f67627875f | |||
| 8912dc226c | |||
| 12ac9f351e | |||
| c4b4e90f98 | |||
| fcf28ded42 | |||
| 1e69d248cb | |||
| c49b29fa53 | |||
| 024220aee8 | |||
| 1423265610 | |||
| 89c48a08a0 | |||
| c30968861f | |||
| a8ac6f833c | |||
| 271acaff53 | |||
| c35e0cba39 | |||
| 65240967e4 | |||
| a99bd2a422 | |||
| 3ec2d5fa38 | |||
| a0b5b39bbd | |||
| ab52862a5d | |||
| a350192ea2 | |||
| cb0d8d6d90 | |||
| 86ad3e8f2a | |||
| 8f29a0633b | |||
| 7601bca758 | |||
| 3bbfff9280 | |||
| 5b049364dc | |||
| 7997bdc5d7 | |||
| 04aebda1e9 | |||
| 77792b6475 | |||
| 5612e84551 | |||
| 462193ae26 | |||
| 80a90a084e | |||
| 2f29cb9e6f | |||
| 67fdfca3ba | |||
| 284d909347 | |||
| 43ef4d7b53 | |||
| 3ce45508e1 | |||
| 57efdcfbbe | |||
| df817bd118 | |||
| 82a1d4f280 | |||
| 80f2660838 | |||
| edd4d2918a | |||
| 320d272ec8 | |||
| 72d09d22e9 | |||
| a2a4603329 | |||
| 8de1ba2cc4 | |||
| 2644da106b | |||
| 4860410c4a | |||
| 4b3a94f382 | |||
| d67dacedba | |||
| e1feb1b712 | |||
| e8670c89ae | |||
| b4f918904c | |||
| aead150ce2 | |||
| fd47e57e4b | |||
| 1e129c1dd2 | |||
| e0a7d28339 | |||
| ad93806005 | |||
| 2b95a5daee | |||
| 0681c5d5bc | |||
| b19926c079 | |||
| 692ed4f994 | |||
| ad759307f8 | |||
| fb6adaaa62 | |||
| 58a4ae94e9 | |||
| 9df9087a13 | |||
| f8df527c68 | |||
| 71512cf9ad | |||
| 79cc8fb261 | |||
| 2831dbb110 | |||
| 933acb3682 | |||
| 574ebafa46 | |||
| 74dd05b45e | |||
| 3eb2cef421 | |||
| 94745241c2 | |||
| 538491efa1 | |||
| 6f8c4f873d | |||
| 7a4e9fa4d3 | |||
| f3c704b82e | |||
| a6a69dd567 | |||
| 8921c868a5 | |||
| 3f8598baa4 | |||
| b5fd7b3211 | |||
| e9fe9410e0 | |||
| 904fd5f1fc | |||
| f598836d6c | |||
| 5907ff694f | |||
| 7c020bfaaa | |||
| 2bd02d9185 | |||
| c0cf592336 | |||
| 12378f0afa | |||
| 5ea211bbb1 | |||
| c17c18f1ae | |||
| dbde7b68c0 | |||
| 95f06f6e75 | |||
| a26edd59d1 | |||
| dcd21e12cd | |||
| e5efc84eda | |||
| 8035969860 | |||
| e5f9bf2e9b | |||
| 0be4d31217 | |||
| eebb849760 | |||
| f92745aacf | |||
| 7aee30bfc2 | |||
| ef751bc809 | |||
| fe49f83982 | |||
| 059d9376da | |||
| 6466e53bfc | |||
| b7963a06ab | |||
| eeeefb40c7 | |||
| 97d8676b40 | |||
| 6e28d004ae | |||
| 8d7bf3ad0c | |||
| d76a0feef6 | |||
| 08a07d4ae5 | |||
| b42d99b37e | |||
| ea487b2233 | |||
| 40ae5c1319 | |||
| 8c9c3e4426 | |||
| d0f4fcb6fd | |||
| 4142d0a69a | |||
| b061821f24 | |||
| e0833e492c | |||
| 55faaf1aa1 | |||
| 7aa02b9e95 | |||
| c65c6ba11f | |||
| 359d874ddb | |||
| ade171a2ed | |||
| 1f1306a53b | |||
| ce3d5fcb0a | |||
| 28bd56454d | |||
| 75deff035b | |||
| 87ee7e31a4 | |||
| 5a3ecb9703 | |||
| e656f66720 | |||
| 0d47a6c970 | |||
| 39f8e1e137 | |||
| d7c2e5844b | |||
| edc4b2f7d0 | |||
| b3ba2961d2 | |||
| c2c1acc73e | |||
| c44728282c | |||
| 85a002bf9f | |||
| 6eba544ad4 | |||
| f610fbfc0e | |||
| 1e2d11cc62 | |||
| f1e24ca30a | |||
| 1787f04097 | |||
| 671f69c6ca | |||
| 7b51de6bbd | |||
| 45b909f2c5 | |||
| 0b4ee06f8e | |||
| 797739198f | |||
| 0c017ff109 | |||
| aad3686726 | |||
| fe7a2635d0 | |||
| 2834b38d2c | |||
| 29563a33ba | |||
| 5936d7f8f2 | |||
| 481a78eee7 | |||
| ac4134c298 | |||
| 145659af93 | |||
| 31b8e0f109 | |||
| 18199a3cef | |||
| 3194c39471 | |||
| 9d51a8f53a | |||
| c37c86a9bf | |||
| b4b30b4951 | |||
| 54830a2af3 | |||
| 9946dd2ab7 | |||
| 5028cb35bc | |||
| 48b569eae0 | |||
| 8099669466 | |||
| 1c465604d5 | |||
| 833442e1e2 | |||
| 1e39f999e3 | |||
| e31187e1cf | |||
| e457a7823c | |||
| 88c77eb7be | |||
| f57d337fac | |||
| 60b0f48fbc | |||
| 4c6d60ce2b | |||
| b4acf81609 | |||
| 62871400b1 | |||
| c4b3337569 | |||
| 45e6e0cd04 | |||
| 98dd53c2c3 | |||
| ad7eaf2bb8 | |||
| ef82f1799f | |||
| 1729da8a3e | |||
| a3ac3b61ef | |||
| 532a48aa92 | |||
| f3674688bf | |||
| dd6aa7b870 | |||
| 21d0e30903 | |||
| 3c73f70dae | |||
| 65fbd0af4e | |||
| 55b32c8a8f | |||
| bb0e964f56 | |||
| 0f4a6bfbf8 | |||
| 4e884b6056 | |||
| f252bbc02c | |||
| 9cbd3ac017 | |||
| 4bae7fb0fd | |||
| b98f5a0823 | |||
| 00c29e1fbe | |||
| de3e5be235 | |||
| ae3e6d1949 | |||
| 114efa83c6 | |||
| d15df65a9d | |||
| e0a1311e5b | |||
| 48e88c6ea4 | |||
| 50c63fc39a | |||
| 1ca5b41571 | |||
| cebf5ed46c | |||
| 1ca906008e | |||
| dd69c4e0f2 | |||
| cbb0d7ba69 | |||
| cbdb744c40 | |||
| 10fef2fbb4 | |||
| 8e2fb9c2be | |||
| f48ed12e78 | |||
| 66c0336ead | |||
| 0657a53940 | |||
| eecd5823d0 | |||
| 99b769706c | |||
| 39843ebb3f | |||
| 52bcf7fd46 | |||
| 43997fb550 | |||
| c59669d376 | |||
| ac97d2be0c | |||
| e9a67cc6d0 | |||
| 44655932c4 | |||
| 278f9a9eda | |||
| a28c7e8839 | |||
| 77c8d2df00 | |||
| aeca5858d8 | |||
| 89b96a864e | |||
| 26302cada5 | |||
| 42d064c62f | |||
| 273189fc1a | |||
| d51abaea2e | |||
| 248708c282 | |||
| 0e2748006a | |||
| e89bd7dfa2 | |||
| 2f6e998a27 | |||
| 7b7296410e | |||
| d90e2733ea | |||
| 19bf502fde | |||
| 2b8e30a8ed | |||
| 4ad8dcebd8 | |||
| a966b90e51 | |||
| 5b2a451e75 | |||
| 8105bde835 | |||
| 2329b62c14 | |||
| 1e1bed056f | |||
| a0d83bdfa7 | |||
| fa8190328d | |||
| d19cba429d | |||
| be2609a271 | |||
| 5bf009a203 | |||
| 93a89a371e | |||
| 60cb315be6 | |||
| 73728814b0 | |||
| d4098099dd | |||
| 57ef793e6d | |||
| 58cdd5139e | |||
| 2c84049769 | |||
| 29c700d1c7 | |||
| 0d7c987b1a | |||
| 03679d4342 | |||
| 1a4b60fb36 | |||
| 05b2ae0f31 | |||
| f211d71f74 | |||
| 691ab421fb | |||
| 9e3e9e83ef | |||
| a0056d5ca8 | |||
| f3e6d00db1 | |||
| e55df03fe2 | |||
| c8a13a2d8a | |||
| 6971e2923d | |||
| 231b76bdd1 | |||
| 57ba4048de | |||
| 545c5f18b2 | |||
| 5571217218 | |||
| b92c328425 | |||
| 8bdcff3320 | |||
| 9ffd88012d | |||
| 563fb97f90 | |||
| ee5708f543 | |||
| b7bf04fabd | |||
| b94b8ac38d | |||
| afd69db678 | |||
| f3834138f7 | |||
| 64b7c123cc | |||
| fcb780ee13 | |||
| 65b795b861 | |||
| 64d97b233b | |||
| db8474e5b1 | |||
| 5e8983883e | |||
| 59006e2e03 | |||
| b6acc31d44 | |||
| 6d0fe46cba | |||
| 05e752e096 | |||
| 2237009983 | |||
| 417ac4ab43 | |||
| 4495eaae84 | |||
| aba76fe8e9 | |||
| 867042f88f | |||
| 32ec7dec61 | |||
| d6161e09cd | |||
| 4b5fb5ec79 | |||
| 4f70f72349 | |||
| dd94129e27 | |||
| 63e5b827ed | |||
| 573c63973a | |||
| 1ce960c85b | |||
| d7a5dcba0b | |||
| a4b1c6b384 | |||
| 0edec9bcae | |||
| 7d12a843f2 | |||
| 867efe2e33 | |||
| a121bfa7ec | |||
| 02758cd48d | |||
| 005f932d13 | |||
| 4e8c06eb7a | |||
| ca9aa23619 | |||
| ae2c765ffd | |||
| ab9455ea1b | |||
| 89522e6923 | |||
| 506a4ddad5 | |||
| 272e4a0a9d | |||
| 16deffb48d | |||
| a60e951941 | |||
| 05306470b0 | |||
| 803a8cf333 | |||
| 3e5746356e | |||
| c9f1c56776 | |||
| fc026b95dd | |||
| 2bb97bc136 | |||
| d4d12171f4 | |||
| 21e484731a | |||
| b82a32676b | |||
| d7228ae025 | |||
| 04c02e9aec | |||
| d6945d81f0 | |||
| 6d6559f982 | |||
| b271db253f | |||
| eb9f95e9fa | |||
| d7a5723d66 | |||
| 72498b9e28 | |||
| b904fc6ee0 | |||
| 9622ba8a0d | |||
| 3b8d206143 | |||
| e027fc9272 | |||
| ba6c5ef201 | |||
| 6a8013735d | |||
| c3e72c4d7e | |||
| a6c47cb3ab | |||
| cc129e564a | |||
| 9fbcbc55d7 | |||
| 00a27c1e28 | |||
| f5f6597abc | |||
| fade0afbef | |||
| 0082675de8 | |||
| ed8e784879 | |||
| a4790b7eaa | |||
| ed434519d2 | |||
| 4ed4b4fd6a | |||
| 369cb702e4 | |||
| d246abd085 | |||
| 911627fa0b | |||
| ec576088bb | |||
| ab0b54db76 | |||
| fb51f8be9a | |||
| eb22c7c9c3 | |||
| 749ef4d71c | |||
| f6fae1dd09 | |||
| f21abba82f | |||
| bf222a9292 | |||
| 96e465b6d9 | |||
| 016de68ceb | |||
| d2178bcb94 | |||
| f40eb8a1fe | |||
| 9e0f43e8cb | |||
| 3e4d7250a0 | |||
| 4ebd14c045 | |||
| ca39b35e2f | |||
| a32fb5b849 | |||
| eed19c9269 | |||
| e2d691bdb1 | |||
| a73f961e65 | |||
| a7aed5af4b | |||
| 220a51e7cb | |||
| 6df28420d7 | |||
| 081b45399f | |||
| 0874a54708 | |||
| cd40ec2200 | |||
| 62b887e064 | |||
| ce9ce8a5bc | |||
| 2322f38bf9 | |||
| dcb6c9b4cf | |||
| afdeffd820 | |||
| 10439aaefe | |||
| d64467b334 | |||
| 099b967885 | |||
| d13cd9cb67 | |||
| 79b87cc543 | |||
| 3c2aceba63 | |||
| a01feae15b | |||
| b4d4f73d9f | |||
| c1de6219ed | |||
| b364827a5b | |||
| bbe362d015 | |||
| 08f32c6560 | |||
| b3c8c8e592 | |||
| ed36933232 | |||
| a90fc088f2 | |||
| ff6c4ed07e | |||
| 201f635559 | |||
| 59077e4843 | |||
| 3e6a473082 | |||
| 580d96620e | |||
| 61f50f2410 | |||
| 61b2f3c996 | |||
| ab30850aad | |||
| f5e04b59e9 | |||
| c67bcf09b9 | |||
| 5eba0bc932 | |||
| ff2ba52bc6 | |||
| a822d6fce9 | |||
| b749fe4270 | |||
| 933cb857cf | |||
| dde535bbdf | |||
| 71b36db88d | |||
| b5576397f7 | |||
| 4e86858405 | |||
| 14b21d78db | |||
| 35829a7272 | |||
| 0eb60fb03e | |||
| 94162197a1 | |||
| 877fffdd5e | |||
| 8669d31c30 | |||
| e76d17a786 | |||
| 5ab90f1a80 | |||
| 5b1fd111d1 | |||
| 5596feae9b | |||
| 8fb8303ba0 | |||
| 06e4c3c991 | |||
| f25f3b3c47 | |||
| 72ec8963d7 | |||
| 50d5666db0 | |||
| e06044530f | |||
| 7ce7e5503f | |||
| 0ba307995d | |||
| b7f9a5419f | |||
| 6cfa799ca1 |
@@ -0,0 +1 @@
|
||||
/subprojects/*/
|
||||
+2
-2
@@ -13,7 +13,7 @@ stages:
|
||||
- subprojects/pango/
|
||||
|
||||
fedora-x86_64:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v1
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v2
|
||||
stage: build
|
||||
script:
|
||||
- bash -x ./.gitlab-ci/test-docker.sh
|
||||
@@ -64,7 +64,7 @@ flatpak:widget-factory:
|
||||
<<: *flatpak-defaults
|
||||
|
||||
pages:
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v1
|
||||
image: registry.gitlab.gnome.org/gnome/gtk/master:v2
|
||||
stage: deploy
|
||||
script:
|
||||
- meson -Ddocumentation=true _build .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM fedora:28
|
||||
FROM fedora:29
|
||||
|
||||
RUN dnf -y install \
|
||||
hicolor-icon-theme \
|
||||
@@ -33,6 +33,7 @@ RUN dnf -y install \
|
||||
iso-codes \
|
||||
itstool \
|
||||
json-glib-devel \
|
||||
lcov \
|
||||
libattr-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
@@ -69,7 +70,7 @@ RUN dnf -y install \
|
||||
xorg-x11-server-Xvfb \
|
||||
&& dnf clean all
|
||||
|
||||
RUN pip3 install meson
|
||||
RUN pip3 install meson==0.49.0
|
||||
|
||||
ARG HOST_USER_ID=5555
|
||||
ENV HOST_USER_ID ${HOST_USER_ID}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v1"
|
||||
TAG="registry.gitlab.gnome.org/gnome/gtk/master:v2"
|
||||
|
||||
sudo docker build --build-arg HOST_USER_ID="$UID" --tag "${TAG}" \
|
||||
--file "Dockerfile" .
|
||||
|
||||
+223
-22
@@ -1,31 +1,144 @@
|
||||
If you want to hack on the GTK+ project, you'll need to have the development
|
||||
tools appropriate for your operating system, including:
|
||||
# Contribution guidelines
|
||||
|
||||
Thank you for considering contributing to the GTK project!
|
||||
|
||||
These guidelines are meant for new contributors, regardless of their level
|
||||
of proficiency; following them allows the maintainers of the GTK project to
|
||||
more effectively evaluate your contribution, and provide prompt feedback to
|
||||
you. Additionally, by following these guidelines you clearly communicate
|
||||
that you respect the time and effort that the people developing GTK put into
|
||||
managing the project.
|
||||
|
||||
GTK is a complex free software GUI toolkit, and it would not exist without
|
||||
contributions from the free and open source software community. There are
|
||||
many things that we value:
|
||||
|
||||
- bug reporting and fixing
|
||||
- documentation and examples
|
||||
- tests
|
||||
- new features
|
||||
|
||||
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](https://mail.gnome.org/mailman/listinfo/gtk-list) mailing list,
|
||||
for general questions on GTK
|
||||
- the [gtk-app-devel](https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list)
|
||||
mailing list, for questions on application development with GTK
|
||||
- the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
|
||||
mailing list, for questions on developing GTK itself
|
||||
|
||||
You can also look at the GTK tag on [Stack
|
||||
Overflow](https://stackoverflow.com/questions/tagged/gtk).
|
||||
|
||||
The issue tracker is meant to be used for actionable issues only.
|
||||
|
||||
## How to report bugs
|
||||
|
||||
### Security issues
|
||||
|
||||
You should not open a new issue for security related questions.
|
||||
|
||||
When in doubt, send an email to the [security](mailto:security@gnome.org)
|
||||
mailing list.
|
||||
|
||||
### Bug reports
|
||||
|
||||
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. the necessary steps to reproduce the issue
|
||||
0. the expected outcome
|
||||
0. a description of the behavior; screenshots are also welcome
|
||||
0. a small, self-contained example exhibiting the behavior; if this
|
||||
is not available, try reproducing the issue using the GTK examples
|
||||
or interactive tests
|
||||
|
||||
If the issue includes a crash, you should also include:
|
||||
|
||||
0. the eventual warnings printed on the terminal
|
||||
0. a backtrace, obtained with tools such as GDB or LLDB
|
||||
|
||||
For small issues, such as:
|
||||
|
||||
- spelling/grammar fixes in the documentation
|
||||
- typo correction
|
||||
- comment clean ups
|
||||
- changes to metadata files (CI, `.gitignore`)
|
||||
- build system changes
|
||||
- source tree clean ups and reorganizations
|
||||
|
||||
You should directly open a merge request instead of filing a new issue.
|
||||
|
||||
### Features and enhancements
|
||||
|
||||
Feature discussion can be open ended and require high bandwidth channels; if
|
||||
you are proposing a new feature on the issue tracker, make sure to make
|
||||
an actionable proposal, and list:
|
||||
|
||||
0. what you're trying to achieve
|
||||
0. prior art, in other toolkits or applications
|
||||
0. design and theming changes
|
||||
|
||||
If you're proposing the integration of new features it helps to have
|
||||
multiple applications using shared or similar code, especially if they have
|
||||
iterated over it various times.
|
||||
|
||||
Each feature should also come fully documented, and with tests.
|
||||
|
||||
## Your first contribution
|
||||
|
||||
### Prerequisites
|
||||
|
||||
If you want to contribute to the GTK project, you will need to have the
|
||||
development tools appropriate for your operating system, including:
|
||||
|
||||
- Python 3.x
|
||||
- Meson
|
||||
- Ninja
|
||||
- Gettext (19.7 or newer)
|
||||
- a C99 compatible compiler
|
||||
- a [C99 compatible compiler](https://wiki.gnome.org/Projects/GLib/CompilerRequirements)
|
||||
|
||||
Up-to-date instructions about developing GNOME applications and libraries
|
||||
can be found here:
|
||||
can be found on [the GNOME Developer Center](https://developer.gnome.org).
|
||||
|
||||
* https://developer.gnome.org
|
||||
The GTK project uses GitLab for code hosting and for tracking issues. More
|
||||
information about using GitLab can be found [on the GNOME
|
||||
wiki](https://wiki.gnome.org/GitLab).
|
||||
|
||||
Information about using GitLab with GNOME can be found here:
|
||||
### Dependencies
|
||||
|
||||
* https://wiki.gnome.org/GitLab
|
||||
In order to get GTK from Git installed on your system, you need to have the
|
||||
required versions of all the software dependencies required by GTK; typically,
|
||||
this means a recent version of GLib, Cairo, Pango, and ATK, as well as the
|
||||
platform-specific dependencies for the windowing system you are using (Wayland,
|
||||
X11, Windows, or macOS).
|
||||
|
||||
In order to get Git GTK+ installed on your system, you need to have the
|
||||
required versions of all the GTK+ dependencies; typically, this means a
|
||||
recent version of GLib, Cairo, Pango, and ATK, as well as the platform
|
||||
specific dependencies for the windowing system you are using (Wayland, X11,
|
||||
Windows, or macOS).
|
||||
The core dependencies for GTK are:
|
||||
|
||||
- [GLib, GObject, and GIO](https://gitlab.gnome.org/GNOME/glib)
|
||||
- [Cairo](http://cairographics.org)
|
||||
- [Pango](https://gitlab.gnome.org/GNOME/pango)
|
||||
- [GdkPixbuf](https://gitlab.gnome.org/GNOME/gdk-pixbuf)
|
||||
- [Epoxy](https://github.com/anholt/libepoxy)
|
||||
- [ATK](https://gitlab.gnome.org/GNOME/atk)
|
||||
- [Graphene](https://github.com/ebassi/graphene)
|
||||
|
||||
GTK will attempt to download and build some of these dependencies if it
|
||||
cannot find them on your system.
|
||||
|
||||
Additionally, you may want to look at projects that create a development
|
||||
environment for you, like [jhbuild](https://wiki.gnome.org/HowDoI/Jhbuild)
|
||||
and [gvsbuild](https://github.com/wingtk/gvsbuild).
|
||||
|
||||
### Getting started
|
||||
|
||||
You should start by forking the GTK repository from the GitLab web UI, and
|
||||
cloning from your fork:
|
||||
|
||||
```ssh
|
||||
```sh
|
||||
$ git clone https://gitlab.gnome.org/yourusername/gtk.git
|
||||
$ cd gtk
|
||||
```
|
||||
@@ -38,7 +151,7 @@ $ git clone git@gitlab.gnome.org:GNOME/gtk.git
|
||||
$ cd gtk
|
||||
```
|
||||
|
||||
To compile the Git version of GTK+ on your system, you will need to
|
||||
To compile the Git version of GTK on your system, you will need to
|
||||
configure your build using Meson:
|
||||
|
||||
```sh
|
||||
@@ -47,11 +160,6 @@ $ cd _builddir
|
||||
$ ninja
|
||||
```
|
||||
|
||||
**Note**: For information about submitting patches and pushing changes
|
||||
to Git, see the `README.md` and `README.commits` files. In particular,
|
||||
don't, under any circumstances, push anything to Git before reading and
|
||||
understanding `README.commmits`.
|
||||
|
||||
Typically, you should work on your own branch:
|
||||
|
||||
```sh
|
||||
@@ -60,6 +168,99 @@ $ git checkout -b your-branch
|
||||
|
||||
Once you've finished working on the bug fix or feature, push the branch
|
||||
to the Git repository and open a new merge request, to let the GTK
|
||||
maintainers review your contribution. The [CODE-OWNERS](./docs-CODE-OWNERS)
|
||||
document contains the list of core contributors to GTK and the areas for
|
||||
which they are responsible.
|
||||
maintainers review your contribution.
|
||||
|
||||
### Code reviews
|
||||
|
||||
Each contribution is reviewed by the core developers of the GTK project.
|
||||
|
||||
The [CODE-OWNERS](./docs/CODE-OWNERS) document contains the list of core
|
||||
contributors to GTK and the areas for which they are responsible; you
|
||||
should ensure to receive their review and signoff on your changes.
|
||||
|
||||
### Commit messages
|
||||
|
||||
The expected format for git commit messages is as follows:
|
||||
|
||||
```plain
|
||||
Short explanation of the commit
|
||||
|
||||
Longer explanation explaining exactly what's changed, whether any
|
||||
external or private interfaces changed, what bugs were fixed (with bug
|
||||
tracker reference if applicable) and so forth. Be concise but not too
|
||||
brief.
|
||||
|
||||
Closes #1234
|
||||
```
|
||||
|
||||
- Always add a brief description of the commit to the _first_ line of
|
||||
the commit and terminate by two newlines (it will work without the
|
||||
second newline, but that is not nice for the interfaces).
|
||||
|
||||
- First line (the brief description) must only be one sentence and
|
||||
should start with a capital letter unless it starts with a lowercase
|
||||
symbol or identifier. Don't use a trailing period either. Don't exceed
|
||||
72 characters.
|
||||
|
||||
- The main description (the body) is normal prose and should use normal
|
||||
punctuation and capital letters where appropriate. Consider the commit
|
||||
message as an email sent to the developers (or yourself, six months
|
||||
down the line) detailing **why** you changed something. There's no need
|
||||
to specify the **how**: the changes can be inlined.
|
||||
|
||||
- When committing code on behalf of others use the `--author` option, e.g.
|
||||
`git commit -a --author "Joe Coder <joe@coder.org>"` and `--signoff`.
|
||||
|
||||
- If your commit is addressing an issue, use the
|
||||
[GitLab syntax](https://docs.gitlab.com/ce/user/project/issues/automatic_issue_closing.html)
|
||||
to automatically close the issue when merging the commit with the upstream
|
||||
repository:
|
||||
|
||||
```plain
|
||||
Closes #1234
|
||||
Fixes #1234
|
||||
Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1234
|
||||
```
|
||||
|
||||
- If you have a merge request with multiple commits and none of them
|
||||
completely fixes an issue, you should add a reference to the issue in
|
||||
the commit message, e.g. `Bug: #1234`, and use the automatic issue
|
||||
closing syntax in the description of the merge request.
|
||||
|
||||
### Commit access to the GTK repository
|
||||
|
||||
GTK is part of the GNOME infrastructure. At the current time, any
|
||||
person with write access to the GNOME repository can merge changes to
|
||||
GTK. This is a good thing, in that it encourages many people to work
|
||||
on GTK, and progress can be made quickly. However, GTK is a fairly
|
||||
large and complicated project on which many other things depend, so to
|
||||
avoid unnecessary breakage, and to take advantage of the knowledge
|
||||
about GTK that has been built up over the years, we'd like to ask
|
||||
people committing to GTK to follow a few rules:
|
||||
|
||||
0. Ask first. If your changes are major, or could possibly break existing
|
||||
code, you should always ask. If your change is minor and you've been
|
||||
working on GTK for a while it probably isn't necessary to ask. But when
|
||||
in doubt, ask. Even if your change is correct, somebody may know a
|
||||
better way to do things. If you are making changes to GTK, you should
|
||||
be subscribed to the [gtk-devel](https://mail.gnome.org/mailman/listinfo/gtk-devel-list)
|
||||
mailing list; this is a good place to ask about intended changes.
|
||||
The `#gtk+` IRC channel on irc.gnome.org is also a good place to find GTK
|
||||
developers to discuss changes, but if you live outside of the EU/US time
|
||||
zones, an email to the gtk-devel mailing list is the most certain and
|
||||
preferred method.
|
||||
|
||||
0. Ask _first_.
|
||||
|
||||
0. Always write a meaningful commit message. Changes without a sufficient
|
||||
commit message will be reverted.
|
||||
|
||||
0. Never push to the `master` branch, or any stable branches, directly; you
|
||||
should always go through a merge request, to ensure that the code is
|
||||
tested on the CI infrastructure at the very least. A merge request is
|
||||
also the proper place to get a comprehensive code review from the core
|
||||
developers of GTK.
|
||||
|
||||
If you have been contributing to GTK for a while and you don't have commit
|
||||
access to the repository, you may ask to obtain it following the [GNOME account
|
||||
process](https://wiki.gnome.org/AccountsTeam/NewAccounts).
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
GTK+ is part of the GNOME git repository. At the current time, any
|
||||
person with write access to the GNOME repository, can make changes to
|
||||
GTK+. This is a good thing, in that it encourages many people to work
|
||||
on GTK+, and progress can be made quickly. However, GTK+ is a fairly
|
||||
large and complicated package that many other things depend on, so to
|
||||
avoid unnecessary breakage, and to take advantage of the knowledge
|
||||
about GTK+ that has been built up over the years, we'd like to ask
|
||||
people committing to GTK+ to follow a few rules:
|
||||
|
||||
0) Ask first. If your changes are major, or could possibly break existing
|
||||
code, you should always ask. If your change is minor and you've
|
||||
been working on GTK+ for a while it probably isn't necessary
|
||||
to ask. But when in doubt, ask. Even if your change is correct,
|
||||
somebody may know a better way to do things.
|
||||
|
||||
If you are making changes to GTK+, you should be subscribed
|
||||
to gtk-devel-list@gnome.org. (Subscription address:
|
||||
gtk-devel-list-request@gnome.org.) This is a good place to ask
|
||||
about intended changes.
|
||||
|
||||
#gtk+ on GIMPNet (irc.gimp.org, irc.us.gimp.org, irc.eu.gimp.org, ...)
|
||||
is also a good place to find GTK+ developers to discuss changes with,
|
||||
however, email to gtk-devel-list is the most certain and preferred
|
||||
method.
|
||||
|
||||
1) Ask _first_.
|
||||
|
||||
2) With git, we no longer maintain a ChangeLog file, but you are expected
|
||||
to produce a meaningful commit message. Changes without a sufficient
|
||||
commit message will be reverted. See below for the expected format
|
||||
of commit messages.
|
||||
|
||||
Notes:
|
||||
|
||||
* When developing larger features or complicated bug fixes, it is
|
||||
advisable to work in a branch in your own cloned GTK+ repository.
|
||||
You may even consider making your repository publically available
|
||||
so that others can easily test and review your changes.
|
||||
|
||||
* The expected format for git commit messages is as follows:
|
||||
|
||||
=== begin example commit ===
|
||||
Short explanation of the commit
|
||||
|
||||
Longer explanation explaining exactly what's changed, whether any
|
||||
external or private interfaces changed, what bugs were fixed (with bug
|
||||
tracker reference if applicable) and so forth. Be concise but not too brief.
|
||||
=== end example commit ===
|
||||
|
||||
- Always add a brief description of the commit to the _first_ line of
|
||||
the commit and terminate by two newlines (it will work without the
|
||||
second newline, but that is not nice for the interfaces).
|
||||
|
||||
- First line (the brief description) must only be one sentence and
|
||||
should start with a capital letter unless it starts with a lowercase
|
||||
symbol or identifier. Don't use a trailing period either. Don't exceed
|
||||
72 characters.
|
||||
|
||||
- The main description (the body) is normal prose and should use normal
|
||||
punctuation and capital letters where appropriate. Normally, for patches
|
||||
sent to a mailing list it's copied from there.
|
||||
|
||||
- When committing code on behalf of others use the --author option, e.g.
|
||||
git commit -a --author "Joe Coder <joe@coder.org>" and --signoff.
|
||||
|
||||
|
||||
Owen Taylor
|
||||
13 Aug 1998
|
||||
17 Apr 2001
|
||||
|
||||
Matthias Clasen
|
||||
31 Mar 2009
|
||||
@@ -31,6 +31,11 @@ Information about mailing lists can be found at
|
||||
|
||||
- http://www.gtk.org/mailing-lists.php
|
||||
|
||||
Nightly documentation can be found at
|
||||
- Gtk: https://gnome.pages.gitlab.gnome.org/gtk/gtk/
|
||||
- Gdk: https://gnome.pages.gitlab.gnome.org/gtk/gdk/
|
||||
- Gsk: https://gnome.pages.gitlab.gnome.org/gtk/gsk/
|
||||
|
||||
Building and installing
|
||||
-----------------------
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"command": "gtk4-demo",
|
||||
"tags": ["devel", "development", "nightly"],
|
||||
"rename-desktop-file": "gtk4-demo.desktop",
|
||||
"rename-icon": "gtk4-demo",
|
||||
"desktop-file-name-prefix": "(Development) ",
|
||||
"finish-args": [
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"command": "gtk4-widget-factory",
|
||||
"tags": ["devel", "development", "nightly"],
|
||||
"rename-desktop-file": "gtk4-widget-factory.desktop",
|
||||
"rename-icon": "gtk4-widget-factory",
|
||||
"desktop-file-name-prefix": "(Development) ",
|
||||
"finish-args": [
|
||||
|
||||
@@ -455,13 +455,16 @@ demo_application_window_constructed (GObject *object)
|
||||
}
|
||||
|
||||
static void
|
||||
demo_application_window_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline)
|
||||
demo_application_window_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
DemoApplicationWindow *window = (DemoApplicationWindow *)widget;
|
||||
|
||||
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget, allocation,
|
||||
GTK_WIDGET_CLASS (demo_application_window_parent_class)->size_allocate (widget,
|
||||
width,
|
||||
height,
|
||||
baseline);
|
||||
|
||||
if (!window->maximized && !window->fullscreen)
|
||||
|
||||
@@ -144,7 +144,7 @@ create_capital_store (void)
|
||||
{ NULL, "Jackson" },
|
||||
{ NULL, "Jefferson City" },
|
||||
{ NULL, "Juneau" },
|
||||
{ "K - O" },
|
||||
{ "K - O", NULL },
|
||||
{ NULL, "Lansing" },
|
||||
{ NULL, "Lincoln" },
|
||||
{ NULL, "Little Rock" },
|
||||
@@ -154,7 +154,7 @@ create_capital_store (void)
|
||||
{ NULL, "Nashville" },
|
||||
{ NULL, "Oklahoma City" },
|
||||
{ NULL, "Olympia" },
|
||||
{ NULL, "P - S" },
|
||||
{ "P - S", NULL },
|
||||
{ NULL, "Phoenix" },
|
||||
{ NULL, "Pierre" },
|
||||
{ NULL, "Providence" },
|
||||
|
||||
@@ -134,7 +134,9 @@ static GtkWidget *
|
||||
create_video (void)
|
||||
{
|
||||
GtkMediaStream *stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
|
||||
GtkWidget *w = gtk_image_new_from_paintable (GDK_PAINTABLE (stream));
|
||||
GtkWidget *w = gtk_picture_new_for_paintable (GDK_PAINTABLE (stream));
|
||||
|
||||
gtk_widget_set_size_request (w, 64, 64);
|
||||
gtk_media_stream_set_loop (stream, TRUE);
|
||||
gtk_media_stream_play (stream);
|
||||
g_object_unref (stream);
|
||||
|
||||
@@ -128,9 +128,10 @@ gtk_fishbowl_measure (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fishbowl_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline)
|
||||
gtk_fishbowl_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
|
||||
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
|
||||
@@ -147,8 +148,8 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
|
||||
continue;
|
||||
|
||||
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
|
||||
child_allocation.x = allocation->x + round (child->x * (allocation->width - child_requisition.width));
|
||||
child_allocation.y = allocation->y + round (child->y * (allocation->height - child_requisition.height));
|
||||
child_allocation.x = round (child->x * (width - child_requisition.width));
|
||||
child_allocation.y = round (child->y * (height - child_requisition.height));
|
||||
child_allocation.width = child_requisition.width;
|
||||
child_allocation.height = child_requisition.height;
|
||||
|
||||
|
||||
@@ -831,15 +831,14 @@ load_file (const gchar *demoname,
|
||||
/* Skipping blank lines */
|
||||
while (g_ascii_isspace (*p))
|
||||
p++;
|
||||
if (*p)
|
||||
{
|
||||
p = lines[i];
|
||||
state++;
|
||||
/* Fall through */
|
||||
}
|
||||
else
|
||||
|
||||
if (!*p)
|
||||
break;
|
||||
|
||||
p = lines[i];
|
||||
state++;
|
||||
/* Fall through */
|
||||
|
||||
case 3:
|
||||
/* Reading program body */
|
||||
gtk_text_buffer_insert (source_buffer, &start, p, -1);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkApplicationWindow" id="window">
|
||||
<style><class name="devel"/></style>
|
||||
<property name="default-width">800</property>
|
||||
<property name="default-height">600</property>
|
||||
<property name="title">GTK+ Demo</property>
|
||||
|
||||
@@ -129,7 +129,7 @@ foreach icon_size: [ '16x16', '22x22', '24x24', '32x32', '48x48', '256x256', ]
|
||||
endforeach
|
||||
|
||||
# desktop file
|
||||
install_data('gtk4-demo.desktop', install_dir: gtk_applicationsdir)
|
||||
install_data('org.gtk.Demo.desktop', install_dir: gtk_applicationsdir)
|
||||
|
||||
# GSettings
|
||||
install_data('org.gtk.Demo.gschema.xml', install_dir: gtk_schemasdir)
|
||||
|
||||
@@ -84,15 +84,16 @@ drawing_area_ensure_surface (DrawingArea *area,
|
||||
}
|
||||
|
||||
static void
|
||||
drawing_area_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline)
|
||||
drawing_area_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
DrawingArea *area = (DrawingArea *) widget;
|
||||
|
||||
drawing_area_ensure_surface (area, allocation->width, allocation->height);
|
||||
drawing_area_ensure_surface (area, width, height);
|
||||
|
||||
GTK_WIDGET_CLASS (drawing_area_parent_class)->size_allocate (widget, allocation, baseline);
|
||||
GTK_WIDGET_CLASS (drawing_area_parent_class)->size_allocate (widget, width, height, baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -55,10 +55,11 @@ create_complex_popover (GtkWidget *parent,
|
||||
}
|
||||
|
||||
static void
|
||||
entry_size_allocate_cb (GtkEntry *entry,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline,
|
||||
gpointer user_data)
|
||||
entry_size_allocate_cb (GtkEntry *entry,
|
||||
int width,
|
||||
int height,
|
||||
int baseline,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkEntryIconPosition popover_pos;
|
||||
GtkPopover *popover = user_data;
|
||||
|
||||
@@ -12,12 +12,10 @@ do_transparent (GtkWidget *do_widget)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *sw;
|
||||
GtkWidget *overlay;
|
||||
GtkWidget *button;
|
||||
GtkWidget *label;
|
||||
GtkWidget *box;
|
||||
GtkWidget *image;
|
||||
GtkWidget *picture;
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
@@ -54,17 +52,8 @@ do_transparent (GtkWidget *do_widget)
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), button);
|
||||
gtk_container_child_set (GTK_CONTAINER (overlay), button, "blur", 5.0, NULL);
|
||||
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
sw = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (overlay), sw);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_AUTOMATIC,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_container_add (GTK_CONTAINER (sw), box);
|
||||
image = gtk_image_new_from_resource ("/transparent/portland-rose.jpg");
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (box), image);
|
||||
picture = gtk_picture_new_for_resource ("/transparent/portland-rose.jpg");
|
||||
gtk_container_add (GTK_CONTAINER (overlay), picture);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -17,4 +17,4 @@ executable('gtk4-icon-browser',
|
||||
link_args: extra_demo_ldflags,
|
||||
install: true)
|
||||
|
||||
install_data('gtk4-icon-browser.desktop', install_dir: gtk_applicationsdir)
|
||||
install_data('org.gtk.IconBrowser.desktop', install_dir: gtk_applicationsdir)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="child-model">store</property>
|
||||
</object>
|
||||
<template class="IconBrowserWindow" parent="GtkApplicationWindow">
|
||||
<style><class name="devel"/></style>
|
||||
<property name="title" translatable="yes">Icon Browser</property>
|
||||
<property name="default-width">1024</property>
|
||||
<property name="default-height">768</property>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.0 -->
|
||||
<menu id="app-menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">About</attribute>
|
||||
<attribute name="action">app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Quit</attribute>
|
||||
<attribute name="action">app.quit</attribute>
|
||||
<attribute name="accel"><Primary>q</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
</interface>
|
||||
@@ -13,7 +13,7 @@ executable('gtk4-widget-factory',
|
||||
install: true)
|
||||
|
||||
# desktop file
|
||||
install_data('gtk4-widget-factory.desktop', install_dir: gtk_applicationsdir)
|
||||
install_data('org.gtk.WidgetFactory.desktop', install_dir: gtk_applicationsdir)
|
||||
|
||||
# icons
|
||||
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
<gresource prefix="/org/gtk/WidgetFactory">
|
||||
<file>widget-factory.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/WidgetFactory/gtk">
|
||||
<file preprocess="xml-stripblanks">menus.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/org/gtk/WidgetFactory/gtk">
|
||||
<file preprocess="xml-stripblanks">help-overlay.ui</file>
|
||||
</gresource>
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
<attribute name="action">win.transition</attribute>
|
||||
</item>
|
||||
</section>
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
|
||||
<attribute name="action">win.show-help-overlay</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_About Widget Factory</attribute>
|
||||
<attribute name="action">app.about</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<menu id="dinner_menu">
|
||||
<section>
|
||||
@@ -396,6 +406,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkApplicationWindow" id="window">
|
||||
<style><class name="devel"/></style>
|
||||
<property name="title">GTK+ Widget Factory</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar1">
|
||||
@@ -3583,4 +3594,4 @@ bad things might happen.</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
</interface>
|
||||
|
||||
+21
-21
@@ -44,7 +44,7 @@
|
||||
|
||||
<informalexample>
|
||||
<para>Create a new file with the following content named <filename>example-0.c.</filename></para>
|
||||
<programlisting><xi:include href="../../../../examples/window-default.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/window-default.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>
|
||||
@@ -153,7 +153,7 @@
|
||||
<example id="gtk-getting-started-hello-world">
|
||||
<title>Hello World in GTK+</title>
|
||||
<para>Create a new file with the following content named example-1.c.</para>
|
||||
<programlisting><xi:include href="../../../../examples/hello-world.c" parse="text">
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/hello-world.c" parse="text">
|
||||
<xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</example>
|
||||
|
||||
@@ -233,7 +233,7 @@
|
||||
<example id="gtk-getting-started-grid-packing">
|
||||
<title>Packing buttons</title>
|
||||
<para>Create a new file with the following content named example-2.c.</para>
|
||||
<programlisting><xi:include href="../../../../examples/grid-packing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/grid-packing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
You can compile the program above with GCC using:
|
||||
@@ -257,9 +257,9 @@
|
||||
<example>
|
||||
<title>Packing buttons with GtkBuilder</title>
|
||||
<para>Create a new file with the following content named example-3.c.</para>
|
||||
<programlisting><xi:include href="../../../../examples/builder.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/builder.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<para>Create a new file with the following content named builder.ui.</para>
|
||||
<programlisting><xi:include href="../../../../examples/builder.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/builder.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
You can compile the program above with GCC using:
|
||||
@@ -346,7 +346,7 @@
|
||||
of our application class.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application1/main.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application1/main.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>All the application logic is in the application class, which
|
||||
@@ -364,7 +364,7 @@
|
||||
GIO <ulink url="https://developer.gnome.org/gio/2.36/GApplication.html#GApplication.description">documentation</ulink>.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application1/exampleapp.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application1/exampleapp.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Another important class that is part of the application support
|
||||
@@ -373,7 +373,7 @@
|
||||
window.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application1/exampleappwin.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application1/exampleappwin.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>As part of the initial setup of our application, we also
|
||||
@@ -388,7 +388,7 @@
|
||||
</informalfigure>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application1/exampleapp.desktop" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application1/org.gtk.exampleapp.desktop" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Note that <replaceable>@<!-- -->bindir@</replaceable> needs to be replaced
|
||||
@@ -420,7 +420,7 @@
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application2/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application2/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>To make use of this file in our application, we revisit
|
||||
@@ -460,7 +460,7 @@ example_app_window_class_init (ExampleAppWindowClass *class)
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application2/exampleapp.gresource.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application2/exampleapp.gresource.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>This file has to be converted into a C source file that will be
|
||||
@@ -599,7 +599,7 @@ example_app_window_open (ExampleAppWindow *win,
|
||||
in a ui file, and add it as a resource to our binary.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application4/app-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application4/app-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>To associate the app menu with the application, we have to call
|
||||
@@ -698,7 +698,7 @@ example_app_class_init (ExampleAppClass *class)
|
||||
GSettings requires a schema that describes our settings:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application5/org.gtk.exampleapp.gschema.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application5/org.gtk.exampleapp.gschema.xml" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Before we can make use of this schema in our application,
|
||||
@@ -747,13 +747,13 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
<para>Lets start with the template.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application6/prefs.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application6/prefs.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Next comes the dialog subclass.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application6/exampleappprefs.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application6/exampleappprefs.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Now we revisit the <literal>preferences_activated(<!-- -->)</literal> function in our
|
||||
@@ -805,7 +805,7 @@ preferences_activated (GSimpleAction *action,
|
||||
to slide out the search bar below the header bar.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application7/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application7/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>Implementing the search needs quite a few code changes that
|
||||
@@ -882,7 +882,7 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
which demonstrates #GtkMenuButton, #GtkRevealer and #GtkListBox.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application8/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application8/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>The code to populate the sidebar with buttons for the words
|
||||
@@ -893,7 +893,7 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
ui file.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application8/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application8/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>To connect the menuitem to the show-words setting, we use
|
||||
@@ -952,7 +952,7 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
triggers the show-lines action:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application9/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application9/gears-menu.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>To make this menu item do something, we create a property
|
||||
@@ -1012,7 +1012,7 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
be a direct child of the window, and set its type to be titlebar.</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting><xi:include href="../../../../examples/application10/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/application10/window.ui" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>A small extra bonus of using a header bar is that we get
|
||||
@@ -1068,7 +1068,7 @@ example_app_window_init (ExampleAppWindow *win)
|
||||
<example id="gtk-getting-started-drawing">
|
||||
<title>Drawing in response to input</title>
|
||||
<para>Create a new file with the following content named example-4.c.</para>
|
||||
<programlisting><xi:include href="../../../../examples/drawing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
<programlisting><xi:include href="@SRC_DIR@/examples/drawing.c" parse="text"><xi:fallback>MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting>
|
||||
</example>
|
||||
<para>
|
||||
You can compile the program above with GCC using:
|
||||
@@ -41,6 +41,16 @@
|
||||
<xi:include href="visual_index.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="Lists">
|
||||
<title>GListModel support</title>
|
||||
<xi:include href="xml/gtkfilterlistmodel.xml" />
|
||||
<xi:include href="xml/gtkflattenlistmodel.xml" />
|
||||
<xi:include href="xml/gtkmaplistmodel.xml" />
|
||||
<xi:include href="xml/gtkslicelistmodel.xml" />
|
||||
<xi:include href="xml/gtksortlistmodel.xml" />
|
||||
<xi:include href="xml/gtktreelistmodel.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="Application">
|
||||
<title>Application support</title>
|
||||
<xi:include href="xml/gtkapplication.xml" />
|
||||
@@ -152,6 +162,7 @@
|
||||
<chapter id="TreeWidgetObjects">
|
||||
<title>Tree, List and Icon Grid Widgets</title>
|
||||
<xi:include href="xml/tree_widget.sgml" />
|
||||
<xi:include href="xml/treeview_tutorial.xml" />
|
||||
<xi:include href="xml/gtktreemodel.xml" />
|
||||
<xi:include href="xml/gtktreeselection.xml" />
|
||||
<xi:include href="xml/gtktreeviewcolumn.xml" />
|
||||
@@ -301,6 +312,7 @@
|
||||
<title>Gestures and event handling</title>
|
||||
<xi:include href="xml/gtkeventcontroller.xml" />
|
||||
<xi:include href="xml/gtkeventcontrollerkey.xml" />
|
||||
<xi:include href="xml/gtkeventcontrollerlegacy.xml" />
|
||||
<xi:include href="xml/gtkeventcontrollerscroll.xml" />
|
||||
<xi:include href="xml/gtkeventcontrollermotion.xml" />
|
||||
<xi:include href="xml/gtkgesture.xml" />
|
||||
|
||||
@@ -758,9 +758,6 @@ gtk_container_child_set_valist
|
||||
gtk_container_child_notify
|
||||
gtk_container_child_notify_by_pspec
|
||||
gtk_container_forall
|
||||
gtk_container_get_focus_chain
|
||||
gtk_container_set_focus_chain
|
||||
gtk_container_unset_focus_chain
|
||||
gtk_container_class_find_child_property
|
||||
gtk_container_class_install_child_property
|
||||
gtk_container_class_install_child_properties
|
||||
@@ -1242,6 +1239,26 @@ GTK_TYPE_FILE_FILTER
|
||||
gtk_file_filter_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkfilterlistmodel</FILE>
|
||||
<TITLE>GtkFilterListModel</TITLE>
|
||||
GtkFilterListModel
|
||||
gtk_filter_list_model_new
|
||||
gtk_filter_list_model_get_model
|
||||
gtk_filter_list_model_set_filter_func
|
||||
gtk_filter_list_model_has_filter
|
||||
gtk_filter_list_model_refilter
|
||||
<SUBSECTION Standard>
|
||||
GTK_FILTER_LIST_MODEL
|
||||
GTK_IS_FILTER_LIST_MODEL
|
||||
GTK_TYPE_FILTER_LIST_MODEL
|
||||
GTK_FILTER_LIST_MODEL_CLASS
|
||||
GTK_IS_FILTER_LIST_MODEL_CLASS
|
||||
GTK_FILTER_LIST_MODEL_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_filter_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkfixed</FILE>
|
||||
<TITLE>GtkFixed</TITLE>
|
||||
@@ -1262,6 +1279,24 @@ GtkFixedChild
|
||||
gtk_fixed_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkflattenlistmodel</FILE>
|
||||
<TITLE>GtkFlattenListModel</TITLE>
|
||||
GtkFlattenListModel
|
||||
gtk_flatten_list_model_new
|
||||
gtk_flatten_list_model_set_model
|
||||
gtk_flatten_list_model_get_model
|
||||
<SUBSECTION Standard>
|
||||
GTK_FLATTEN_LIST_MODEL
|
||||
GTK_IS_FLATTEN_LIST_MODEL
|
||||
GTK_TYPE_FLATTEN_LIST_MODEL
|
||||
GTK_FLATTEN_LIST_MODEL_CLASS
|
||||
GTK_IS_FLATTEN_LIST_MODEL_CLASS
|
||||
GTK_FLATTEN_LIST_MODEL_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_flatten_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkfontbutton</FILE>
|
||||
<TITLE>GtkFontButton</TITLE>
|
||||
@@ -1709,6 +1744,27 @@ GtkLinkButtonPrivate
|
||||
gtk_link_button_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkmaplistmodel</FILE>
|
||||
<TITLE>GtkMapListModel</TITLE>
|
||||
GtkMapListModel
|
||||
GtkMapListModelMapFunc
|
||||
gtk_map_list_model_new
|
||||
gtk_map_list_model_set_map_func
|
||||
gtk_map_list_model_set_model
|
||||
gtk_map_list_model_get_model
|
||||
gtk_map_list_model_has_map
|
||||
<SUBSECTION Standard>
|
||||
GTK_MAP_LIST_MODEL
|
||||
GTK_IS_MAP_LIST_MODEL
|
||||
GTK_TYPE_MAP_LIST_MODEL
|
||||
GTK_MAP_LIST_MODEL_CLASS
|
||||
GTK_IS_MAP_LIST_MODEL_CLASS
|
||||
GTK_MAP_LIST_MODEL_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_map_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkmenu</FILE>
|
||||
<TITLE>GtkMenu</TITLE>
|
||||
@@ -2537,6 +2593,51 @@ GtkSizeGroupPrivate
|
||||
gtk_size_group_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkslicelistmodel</FILE>
|
||||
<TITLE>GtkSliceListModel</TITLE>
|
||||
GtkSliceListModel
|
||||
gtk_slice_list_model_new
|
||||
gtk_slice_list_model_new_for_type
|
||||
gtk_slice_list_model_set_model
|
||||
gtk_slice_list_model_get_model
|
||||
gtk_slice_list_model_set_offset
|
||||
gtk_slice_list_model_get_offset
|
||||
gtk_slice_list_model_set_size
|
||||
gtk_slice_list_model_get_size
|
||||
<SUBSECTION Standard>
|
||||
GTK_SLICE_LIST_MODEL
|
||||
GTK_IS_SLICE_LIST_MODEL
|
||||
GTK_TYPE_SLICE_LIST_MODEL
|
||||
GTK_SLICE_LIST_MODEL_CLASS
|
||||
GTK_IS_SLICE_LIST_MODEL_CLASS
|
||||
GTK_SLICE_LIST_MODEL_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_slice_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksortlistmodel</FILE>
|
||||
<TITLE>GtkSortListModel</TITLE>
|
||||
GtkSortListModel
|
||||
gtk_sort_list_model_new
|
||||
gtk_sort_list_model_new_for_type
|
||||
gtk_sort_list_model_set_sort_func
|
||||
gtk_sort_list_model_has_sort
|
||||
gtk_sort_list_model_set_model
|
||||
gtk_sort_list_model_get_model
|
||||
gtk_sort_list_model_resort
|
||||
<SUBSECTION Standard>
|
||||
GTK_SORT_LIST_MODEL
|
||||
GTK_IS_SORT_LIST_MODEL
|
||||
GTK_TYPE_SORT_LIST_MODEL
|
||||
GTK_SORT_LIST_MODEL_CLASS
|
||||
GTK_IS_SORT_LIST_MODEL_CLASS
|
||||
GTK_SORT_LIST_MODEL_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_sort_list_model_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkspinbutton</FILE>
|
||||
<TITLE>GtkSpinButton</TITLE>
|
||||
@@ -3271,6 +3372,49 @@ GTK_TOOLTIP
|
||||
gtk_tooltip_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtktreelistmodel</FILE>
|
||||
<TITLE>GtkTreeListModel</TITLE>
|
||||
GtkTreeListModel
|
||||
GtkTreeListRow
|
||||
GtkTreeListModelCreateModelFunc
|
||||
gtk_tree_list_model_new
|
||||
gtk_tree_list_model_get_model
|
||||
gtk_tree_list_model_get_passthrough
|
||||
gtk_tree_list_model_set_autoexpand
|
||||
gtk_tree_list_model_get_autoexpand
|
||||
gtk_tree_list_model_get_child_row
|
||||
gtk_tree_list_model_get_row
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_tree_list_row_get_item
|
||||
gtk_tree_list_row_set_expanded
|
||||
gtk_tree_list_row_get_expanded
|
||||
gtk_tree_list_row_is_expandable
|
||||
gtk_tree_list_row_get_position
|
||||
gtk_tree_list_row_get_depth
|
||||
gtk_tree_list_row_get_children
|
||||
gtk_tree_list_row_get_parent
|
||||
gtk_tree_list_row_get_child_row
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TREE_LIST_MODEL
|
||||
GTK_IS_TREE_LIST_MODEL
|
||||
GTK_TYPE_TREE_LIST_MODEL
|
||||
GTK_TREE_LIST_MODEL_CLASS
|
||||
GTK_IS_TREE_LIST_MODEL_CLASS
|
||||
GTK_TREE_LIST_MODEL_GET_CLASS
|
||||
GTK_TREE_LIST_ROW
|
||||
GTK_IS_TREE_LIST_ROW
|
||||
GTK_TYPE_TREE_LIST_ROW
|
||||
GTK_TREE_LIST_ROW_CLASS
|
||||
GTK_IS_TREE_LIST_ROW_CLASS
|
||||
GTK_TREE_LIST_ROW_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
gtk_tree_list_model_get_type
|
||||
gtk_tree_list_row_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtktreemodel</FILE>
|
||||
<TITLE>GtkTreeModel</TITLE>
|
||||
@@ -4277,7 +4421,6 @@ gtk_widget_list_accel_closures
|
||||
gtk_widget_can_activate_accel
|
||||
gtk_widget_event
|
||||
gtk_widget_activate
|
||||
gtk_widget_intersect
|
||||
gtk_widget_is_focus
|
||||
gtk_widget_grab_focus
|
||||
gtk_widget_grab_default
|
||||
@@ -4460,6 +4603,10 @@ gtk_widget_class_bind_template_callback
|
||||
gtk_widget_class_bind_template_callback_full
|
||||
gtk_widget_class_set_connect_func
|
||||
|
||||
<SUBSECTION>
|
||||
gtk_widget_observe_children
|
||||
gtk_widget_observe_controllers
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_WIDGET
|
||||
GTK_IS_WIDGET
|
||||
@@ -4503,6 +4650,7 @@ gtk_window_set_destroy_with_parent
|
||||
gtk_window_set_display
|
||||
gtk_window_is_active
|
||||
gtk_window_is_maximized
|
||||
gtk_window_get_toplevels
|
||||
gtk_window_list_toplevels
|
||||
gtk_window_add_mnemonic
|
||||
gtk_window_remove_mnemonic
|
||||
@@ -6456,6 +6604,24 @@ GTK_GESTURE_SINGLE_GET_CLASS
|
||||
gtk_gesture_single_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkeventcontrollerlegacy</FILE>
|
||||
<TITLE>GtkEventControllerlegacy</TITLE>
|
||||
GtkEventControllerlegacy
|
||||
gtk_event_controller_legacy_new
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_TYPE_EVENT_CONTROLLER_LEGACY
|
||||
GTK_EVENT_CONTROLLER_LEGACY
|
||||
GTK_EVENT_CONTROLLER_LEGACY_CLASS
|
||||
GTK_IS_EVENT_CONTROLLER_LEGACY
|
||||
GTK_IS_EVENT_CONTROLLER_LEGACY_CLASS
|
||||
GTK_EVENT_CONTROLLER_LEGACY_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
gtk_event_controller_legacy_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkeventcontrollerscroll</FILE>
|
||||
<TITLE>GtkEventControllerScroll</TITLE>
|
||||
|
||||
@@ -54,6 +54,7 @@ gtk_entry_completion_get_type
|
||||
gtk_entry_get_type
|
||||
gtk_event_controller_get_type
|
||||
gtk_event_controller_key_get_type
|
||||
gtk_event_controller_legacy_get_type
|
||||
gtk_event_controller_motion_get_type
|
||||
gtk_event_controller_scroll_get_type
|
||||
gtk_expander_get_type
|
||||
|
||||
@@ -340,7 +340,6 @@ content_files = [
|
||||
'css-overview.xml',
|
||||
'css-properties.xml',
|
||||
'drawing-model.xml',
|
||||
'getting_started.xml',
|
||||
'glossary.xml',
|
||||
'gtk4-broadwayd.xml',
|
||||
'gtk4-builder-tool.xml',
|
||||
@@ -363,6 +362,7 @@ content_files = [
|
||||
'running.sgml',
|
||||
'text_widget.sgml',
|
||||
'tree_widget.sgml',
|
||||
'treeview_tutorial.xml',
|
||||
'visual_index.xml',
|
||||
'wayland.xml',
|
||||
'windows.sgml',
|
||||
@@ -372,7 +372,6 @@ content_files = [
|
||||
expand_content_files = [
|
||||
'compiling.sgml',
|
||||
'drawing-model.xml',
|
||||
'getting_started.xml',
|
||||
'glossary.xml',
|
||||
'input-handling.xml',
|
||||
'migrating-2to4.xml',
|
||||
@@ -380,9 +379,11 @@ expand_content_files = [
|
||||
'question_index.sgml',
|
||||
'text_widget.sgml',
|
||||
'tree_widget.sgml',
|
||||
'treeview_tutorial.xml',
|
||||
]
|
||||
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
configure_file(input: 'getting_started.xml.in', output: 'getting_started.xml', configuration: src_dir_conf)
|
||||
|
||||
types_conf = configuration_data()
|
||||
if os_win32
|
||||
|
||||
@@ -177,6 +177,22 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Set a proper app_id</title>
|
||||
<para>
|
||||
In GTK+4 we want the application's #GApplication
|
||||
'application-id' (and therefore the D-Bus name), the desktop
|
||||
file basename and Wayland's xdg-shell app_id to match. In
|
||||
order to achieve this with GTK+3 call g_set_prgname() with the same
|
||||
application id you passed to #GtkApplication. Rename your
|
||||
desktop files to match the application id if needed.
|
||||
</para>
|
||||
<para>
|
||||
The call to g_set_prgname() can be removed once you fully migrated
|
||||
to GTK+4.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -270,6 +286,14 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Stop using GtkEventBox</title>
|
||||
<para>
|
||||
GtkEventBox is no longer needed and has been removed.
|
||||
All widgets receive all events.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Adapt to GtkHeaderBar API changes</title>
|
||||
<para>
|
||||
@@ -408,6 +432,10 @@
|
||||
from ui files it run the command <command>gtk4-builder-tool simplify --replace</command>
|
||||
on them.
|
||||
</para>
|
||||
<para>
|
||||
The function gtk_widget_show_all(), the #GtkWidget::no-show-all property
|
||||
and its getter and setter have been removed in GTK+ 4, so you should stop using them.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||
]>
|
||||
<refentry id="TreeView-tutorial">
|
||||
<refmeta>
|
||||
<refentrytitle>TreeView Tutorial</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo>GTK Library</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>TreeView Tutorial</refname>
|
||||
<refpurpose>A tutorial on the use of GtkTreeModel, GtkTreeView, and friends</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Overview</title>
|
||||
<para>GtkTreeView is a widget that displays single- or multi-columned
|
||||
lists and trees.</para>
|
||||
|
||||
<para>The purpose of this tutorial is not to provide an exhaustive
|
||||
documentation of #GtkTreeView - that is what the API documentation is
|
||||
for, which should be read alongside with this tutorial. The goal is
|
||||
rather to present an introduction to the most commonly-used aspects
|
||||
of #GtkTreeView, and to demonstrate how the various #GtkTreeView
|
||||
components and concepts work together. Furthermore, an attempt has
|
||||
been made to shed some light on custom tree models and custom cell
|
||||
renderers, which seem to be often-mentioned, but rarely
|
||||
explained.</para>
|
||||
|
||||
<para>Developers looking for a quick and dirty introduction that
|
||||
teaches them everything they need to know in less than five paragraphs
|
||||
will not find it here. In the author's experience, developers who do
|
||||
not understand how the tree view and the models work together will run
|
||||
into problems once they try to modify the given examples, whereas
|
||||
developers who have worked with other toolkits that employ the
|
||||
Model/View/Controller-design will find that the API reference provides
|
||||
all the information they need to know in more condensed form anyway.
|
||||
Those who disagree may jump straight to the working example code of
|
||||
course.</para>
|
||||
|
||||
<para>Please note that the code examples in the following sections do
|
||||
not necessarily demonstrate how GtkTreeView is used best in a particular
|
||||
situation. There are different ways to achieve the same result, and the
|
||||
examples merely show those different ways, so that developers are able
|
||||
to decide which one is most suitable for the task at hand.</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Components</title>
|
||||
|
||||
<para>The most important concept underlying #GtkTreeView is that of
|
||||
complete separation between data and how that data is displayed on
|
||||
the screen. This is commonly known as Model/View/Controller-design,
|
||||
or MVC. Data of various type (strings, numbers, images, etc.) is
|
||||
stored in a "model". The "view" is then told which data to display,
|
||||
where to display it, and how to display it. One of the advantages
|
||||
of this approach is that you can have multiple views that display
|
||||
the same data (a directory tree for example) in different ways, or
|
||||
in the same way multiple times, with only one copy of the underlying
|
||||
data. This avoids duplication of data and programming effort if the
|
||||
same data is re-used in different contexts. Also, when the data in
|
||||
the model is updated, all views automatically get updated as
|
||||
well.</para>
|
||||
|
||||
<para>So, while #GtkTreeModel is used to store data, there are other
|
||||
components that determine which data is displayed in the #GtkTreeView
|
||||
and how it is displayed. These components are #GtkTreeViewColumn and
|
||||
#GtkCellRenderer. A #GtkTreeView is made up of tree view columns.
|
||||
These are the columns that users perceive as columns. They have a
|
||||
clickable column header with a column title that can be hidden, and
|
||||
can be resized and sorted. Tree view columns do not display any data,
|
||||
they are only used as a device to represent the user-side of the tree
|
||||
view (sorting etc.) and serve as packing widgets for the components
|
||||
that do the actual rendering of data onto the screen, namely the
|
||||
#GtkCellRenderer family of objects. There are a number of different
|
||||
cell renderers that specialise in rendering certain data like
|
||||
strings, pixbufs, or toggle buttons. More on this later.</para>
|
||||
|
||||
<para>Cell renderers are packed into tree view columns to display data.
|
||||
A tree view column needs to contain at least one cell renderer, but can
|
||||
contain multiple cell renderers. For example, if one wanted to display
|
||||
a 'Filename' column where each filename has a little icon on the left
|
||||
indicating the file type, one would pack a GtkCellRendererPixbuf and a
|
||||
GtkCellRendererText into one tree view column. Packing renderers into a
|
||||
tree view column is similar to packing widgets into a #GtkBox.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>GtkTreeModels for Data Storage: GtkListStore and GtkTreeStore</title>
|
||||
|
||||
<para>It is important to realise what #GtkTreeModel is and what it is
|
||||
not. #GtkTreeModel is basically just an 'interface' to the data store,
|
||||
meaning that it is a standardised set of functions that allows a
|
||||
#GtkTreeView widget (and the application programmer) to query certain
|
||||
characteristics of a data store, for example how many rows there are,
|
||||
which rows have children, and how many children a particular row has.
|
||||
It also provides functions to retrieve data from the data store, and
|
||||
tell the tree view what type of data is stored in the model. Every
|
||||
data store must implement the #GtkTreeModel interface and provide these
|
||||
functions. #GtkTreeModel itself only provides a way to query a data
|
||||
store's characteristics and to retrieve existing data, it does not
|
||||
provide a way to remove or add rows to the store or put data into the
|
||||
store. This is done using the specific store's functions.</para>
|
||||
|
||||
<para>GTK comes with two built-in data stores (models): #GtkListStore
|
||||
and #GtkTreeStore. As the names imply, #GtkListStore is used for simple
|
||||
lists of data items where items have no hierarchical parent-child
|
||||
relationships, and #GtkTreeStore is used for tree-like data structures,
|
||||
where items can have parent-child relationships. A list of files in a
|
||||
directory would be an example of a simple list structure, whereas a
|
||||
directory tree is an example for a tree structure. A list is basically
|
||||
just a special case of a tree with none of the items having any
|
||||
children, so one could use a tree store to maintain a simple list of
|
||||
items as well. The only reason #GtkListStore exists is in order to
|
||||
provide an easier interface that does not need to cater for
|
||||
child-parent relationships, and because a simple list model can be
|
||||
optimised for the special case where no children exist, which makes it
|
||||
faster and more efficient.</para>
|
||||
|
||||
<para>#GtkListStore and #GtkTreeStore should cater for most types of
|
||||
data an application developer might want to display in a #GtkTreeView.
|
||||
However, it should be noted that #GtkListStore and #GtkTreeStore have
|
||||
been designed to cater to a large number of potential use cases, and
|
||||
so are not overly optimized. If you already have your specialized data
|
||||
store; if you plan to store a lot of data; or if have a large number
|
||||
of rows, you should consider implementing your own custom model that
|
||||
stores and manipulates data your own way and implements the
|
||||
#GtkTreeModel interface. This will not only be more efficient, but
|
||||
probably also lead to saner code in the long run, and give you more
|
||||
control over your data. See below for more details on how to implement
|
||||
custom models.</para>
|
||||
|
||||
<para>Tree model implementations like #GtkListStore and #GtkTreeStore
|
||||
will take care of the view side for you once you have configured the
|
||||
#GtkTreeView to display what you want. If you change data in the store,
|
||||
the model will notify the tree view and your data display will be
|
||||
updated. If you add or remove rows, the model will also notify the
|
||||
store, and your row will appear in or disappear from the view as
|
||||
well.</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
@@ -12,6 +12,9 @@ docpath = join_paths(gtk_datadir, 'gtk-doc', 'html')
|
||||
version_conf = configuration_data()
|
||||
version_conf.set('GTK_VERSION', meson.project_version())
|
||||
|
||||
src_dir_conf = configuration_data()
|
||||
src_dir_conf.set('SRC_DIR', meson.source_root())
|
||||
|
||||
subdir('gdk')
|
||||
subdir('gsk')
|
||||
subdir('gtk')
|
||||
|
||||
@@ -2,8 +2,8 @@ To make gnome-shell use the desktop file and icon for this example
|
||||
while running it uninstalled, do the following:
|
||||
|
||||
mkdir -p ~/.local/share/applications
|
||||
sed -e "s#@bindir@#$PWD#" exampleapp.desktop \
|
||||
> ~/.local/share/applications/lt-exampleapp.desktop
|
||||
sed -e "s#@bindir@#$PWD#" org.gtk.exampleapp.desktop \
|
||||
> ~/.local/share/applications/org.gtk.exampleapp.desktop
|
||||
|
||||
mkdir -p ~/.local/share/icons/hicolor/48x48/apps
|
||||
cp exampleapp.png ~/.local/share/icons/hicolor/48x48/apps
|
||||
|
||||
@@ -32,6 +32,7 @@ void gdk_display_set_cursor_theme (GdkDisplay *display,
|
||||
const char *theme,
|
||||
int size);
|
||||
gboolean gdk_running_in_sandbox (void);
|
||||
gboolean gdk_should_use_portal (void);
|
||||
|
||||
const gchar * gdk_get_startup_notification_id (void);
|
||||
|
||||
|
||||
@@ -269,14 +269,27 @@ gdk_get_startup_notification_id (void)
|
||||
gboolean
|
||||
gdk_running_in_sandbox (void)
|
||||
{
|
||||
char *path;
|
||||
gboolean ret;
|
||||
return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS);
|
||||
}
|
||||
|
||||
path = g_build_filename (g_get_user_runtime_dir (), "flatpak-info", NULL);
|
||||
ret = g_file_test (path, G_FILE_TEST_EXISTS);
|
||||
g_free (path);
|
||||
gboolean
|
||||
gdk_should_use_portal (void)
|
||||
{
|
||||
static const char *use_portal = NULL;
|
||||
|
||||
return ret;
|
||||
if (G_UNLIKELY (use_portal == NULL))
|
||||
{
|
||||
if (gdk_running_in_sandbox ())
|
||||
use_portal = "1";
|
||||
else
|
||||
{
|
||||
use_portal = g_getenv ("GTK_USE_PORTAL");
|
||||
if (!use_portal)
|
||||
use_portal = "";
|
||||
}
|
||||
}
|
||||
|
||||
return use_portal[0] == '1';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ gdk_drop_read_local_async (GdkDrop *self,
|
||||
if (priv->drag == NULL)
|
||||
{
|
||||
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("Drag'n'drop from other applications is not supported."));
|
||||
_("Drag’n’drop from other applications is not supported."));
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ G_BEGIN_DECLS
|
||||
#define GDK_PRIORITY_EVENTS (G_PRIORITY_DEFAULT)
|
||||
|
||||
/**
|
||||
* GDK_PRIORITY_REDRAW:
|
||||
* GDK_PRIORITY_REDRAW: (value 120)
|
||||
*
|
||||
* This is the priority that the idle handler processing surface updates
|
||||
* is given in the
|
||||
|
||||
+8
-8
@@ -175,7 +175,7 @@ parse_rgb_value (const gchar *str,
|
||||
* - A RGBA color in the form “rgba(r,g,b,a)”
|
||||
*
|
||||
* Where “r”, “g”, “b” and “a” are respectively the red, green, blue and
|
||||
* alpha color values. In the last two cases, r g and b are either integers
|
||||
* alpha color values. In the last two cases, “r”, “g”, and “b” are either integers
|
||||
* in the range 0 to 255 or percentage values in the range 0% to 100%, and
|
||||
* a is a floating point value in the range 0 to 1.
|
||||
*
|
||||
@@ -353,18 +353,18 @@ gdk_rgba_equal (gconstpointer p1,
|
||||
* @rgba: a #GdkRGBA
|
||||
*
|
||||
* Returns a textual specification of @rgba in the form
|
||||
* `rgb (r, g, b)` or
|
||||
* `rgba (r, g, b, a)`,
|
||||
* `rgb(r,g,b)` or
|
||||
* `rgba(r g,b,a)`,
|
||||
* where “r”, “g”, “b” and “a” represent the red, green,
|
||||
* blue and alpha values respectively. r, g, and b are
|
||||
* represented as integers in the range 0 to 255, and a
|
||||
* is represented as floating point value in the range 0 to 1.
|
||||
* blue and alpha values respectively. “r”, “g”, and “b” are
|
||||
* represented as integers in the range 0 to 255, and “a”
|
||||
* is represented as a floating point value in the range 0 to 1.
|
||||
*
|
||||
* These string forms are string forms those supported by
|
||||
* These string forms are string forms that are supported by
|
||||
* the CSS3 colors module, and can be parsed by gdk_rgba_parse().
|
||||
*
|
||||
* Note that this string representation may lose some
|
||||
* precision, since r, g and b are represented as 8-bit
|
||||
* precision, since “r”, “g” and “b” are represented as 8-bit
|
||||
* integers. If this is a concern, you should use a
|
||||
* different representation.
|
||||
*
|
||||
|
||||
+3
-2
@@ -434,14 +434,15 @@ gdk_seat_tool_removed (GdkSeat *seat,
|
||||
|
||||
GdkDeviceTool *
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial)
|
||||
guint64 serial,
|
||||
guint64 hw_id)
|
||||
{
|
||||
GdkSeatClass *seat_class;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SEAT (seat), NULL);
|
||||
|
||||
seat_class = GDK_SEAT_GET_CLASS (seat);
|
||||
return seat_class->get_tool (seat, serial);
|
||||
return seat_class->get_tool (seat, serial, hw_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -282,7 +282,8 @@ gdk_seat_default_get_slaves (GdkSeat *seat,
|
||||
|
||||
static GdkDeviceTool *
|
||||
gdk_seat_default_get_tool (GdkSeat *seat,
|
||||
guint64 serial)
|
||||
guint64 serial,
|
||||
guint64 hw_id)
|
||||
{
|
||||
GdkSeatDefaultPrivate *priv;
|
||||
GdkDeviceTool *tool;
|
||||
@@ -297,7 +298,7 @@ gdk_seat_default_get_tool (GdkSeat *seat,
|
||||
{
|
||||
tool = g_ptr_array_index (priv->tools, i);
|
||||
|
||||
if (tool->serial == serial)
|
||||
if (tool->serial == serial && tool->hw_id == hw_id)
|
||||
return tool;
|
||||
}
|
||||
|
||||
@@ -457,8 +458,7 @@ gdk_seat_default_remove_tool (GdkSeatDefault *seat,
|
||||
|
||||
priv = gdk_seat_default_get_instance_private (seat);
|
||||
|
||||
if (tool != gdk_seat_get_tool (GDK_SEAT (seat),
|
||||
gdk_device_tool_get_serial (tool)))
|
||||
if (tool != gdk_seat_get_tool (GDK_SEAT (seat), tool->serial, tool->hw_id))
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (seat, "tool-removed", tool);
|
||||
|
||||
@@ -57,7 +57,8 @@ struct _GdkSeatClass
|
||||
GdkSeatCapabilities capabilities);
|
||||
|
||||
GdkDeviceTool * (* get_tool) (GdkSeat *seat,
|
||||
guint64 serial);
|
||||
guint64 serial,
|
||||
guint64 tool_id);
|
||||
GList * (* get_master_pointers) (GdkSeat *seat,
|
||||
GdkSeatCapabilities capabilities);
|
||||
};
|
||||
@@ -74,6 +75,7 @@ void gdk_seat_tool_removed (GdkSeat *seat,
|
||||
|
||||
GdkDeviceTool *
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial);
|
||||
guint64 serial,
|
||||
guint64 hw_id);
|
||||
|
||||
#endif /* __GDK_SEAT_PRIVATE_H__ */
|
||||
|
||||
+3
-31
@@ -461,12 +461,6 @@ gdk_surface_get_property (GObject *object,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_surface_is_subsurface (GdkSurface *surface)
|
||||
{
|
||||
return surface->surface_type == GDK_SURFACE_SUBSURFACE;
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
gdk_surface_get_impl_surface (GdkSurface *surface)
|
||||
{
|
||||
@@ -555,10 +549,7 @@ recompute_visible_regions_internal (GdkSurface *private,
|
||||
old_abs_y = private->abs_y;
|
||||
|
||||
/* Update absolute position */
|
||||
if ((gdk_surface_has_impl (private) &&
|
||||
private->surface_type != GDK_SURFACE_SUBSURFACE) ||
|
||||
(gdk_surface_is_toplevel (private) &&
|
||||
private->surface_type == GDK_SURFACE_SUBSURFACE))
|
||||
if (gdk_surface_has_impl (private))
|
||||
{
|
||||
/* Native surfaces and toplevel subsurfaces start here */
|
||||
private->abs_x = 0;
|
||||
@@ -677,15 +668,6 @@ gdk_surface_new (GdkDisplay *display,
|
||||
if (parent != NULL)
|
||||
g_warning (G_STRLOC "Toplevel surfaces must be created without a parent");
|
||||
break;
|
||||
case GDK_SURFACE_SUBSURFACE:
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (!GDK_IS_WAYLAND_DISPLAY (display))
|
||||
{
|
||||
g_warning (G_STRLOC "Subsurface surfaces can only be used on Wayland");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case GDK_SURFACE_CHILD:
|
||||
break;
|
||||
default:
|
||||
@@ -715,11 +697,6 @@ gdk_surface_new (GdkDisplay *display,
|
||||
native = TRUE; /* Always use native surfaces for toplevels */
|
||||
}
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (surface->surface_type == GDK_SURFACE_SUBSURFACE)
|
||||
native = TRUE; /* Always use native windows for subsurfaces as well */
|
||||
#endif
|
||||
|
||||
if (native)
|
||||
{
|
||||
/* Create the impl */
|
||||
@@ -922,7 +899,6 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface,
|
||||
case GDK_SURFACE_TOPLEVEL:
|
||||
case GDK_SURFACE_CHILD:
|
||||
case GDK_SURFACE_TEMP:
|
||||
case GDK_SURFACE_SUBSURFACE:
|
||||
if (surface->parent)
|
||||
{
|
||||
if (surface->parent->children)
|
||||
@@ -1173,10 +1149,7 @@ gdk_surface_get_parent (GdkSurface *surface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
|
||||
if (gdk_surface_is_subsurface (surface))
|
||||
return surface->transient_for;
|
||||
else
|
||||
return surface->parent;
|
||||
return surface->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1196,8 +1169,7 @@ gdk_surface_get_toplevel (GdkSurface *surface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), NULL);
|
||||
|
||||
while (surface->surface_type == GDK_SURFACE_CHILD ||
|
||||
surface->surface_type == GDK_SURFACE_SUBSURFACE)
|
||||
while (surface->surface_type == GDK_SURFACE_CHILD)
|
||||
{
|
||||
if (gdk_surface_is_toplevel (surface))
|
||||
break;
|
||||
|
||||
+2
-7
@@ -43,11 +43,7 @@ typedef struct _GdkGeometry GdkGeometry;
|
||||
* GdkSurfaceType:
|
||||
* @GDK_SURFACE_TOPLEVEL: toplevel window (used to implement #GtkWindow)
|
||||
* @GDK_SURFACE_CHILD: child surface (used to implement e.g. #GtkEntry)
|
||||
* @GDK_SURFACE_TEMP: override redirect temporary surface (used to implement
|
||||
* #GtkMenu)
|
||||
* @GDK_SURFACE_SUBSURFACE: subsurface; This surface is visually
|
||||
* tied to a toplevel, and is moved/stacked with it. Currently this window
|
||||
* type is only implemented in Wayland
|
||||
* @GDK_SURFACE_TEMP: override redirect temporary surface (used to implement #GtkMenu)
|
||||
*
|
||||
* Describes the kind of surface.
|
||||
*/
|
||||
@@ -55,8 +51,7 @@ typedef enum
|
||||
{
|
||||
GDK_SURFACE_TOPLEVEL,
|
||||
GDK_SURFACE_CHILD,
|
||||
GDK_SURFACE_TEMP,
|
||||
GDK_SURFACE_SUBSURFACE
|
||||
GDK_SURFACE_TEMP
|
||||
} GdkSurfaceType;
|
||||
|
||||
/* Size restriction enumeration.
|
||||
|
||||
@@ -190,6 +190,11 @@ gdk_vulkan_strerror (VkResult result)
|
||||
case VK_ERROR_FRAGMENTATION_EXT:
|
||||
return "A descriptor pool creation has failed due to fragmentation";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 89
|
||||
case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:
|
||||
return "Invalid DRM format modifier plane layout";
|
||||
#endif
|
||||
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
case VK_RESULT_MAX_ENUM:
|
||||
default:
|
||||
@@ -706,7 +711,7 @@ gdk_vulkan_context_get_image (GdkVulkanContext *context,
|
||||
*
|
||||
* Gets the index of the image that is currently being drawn.
|
||||
*
|
||||
* This function can only be used between gdk_cairo_context_begin_frame() and
|
||||
* This function can only be used between gdk_draw_context_begin_frame() and
|
||||
* gdk_draw_context_end_frame() calls.
|
||||
*
|
||||
* Returns: the index of the images that is being drawn
|
||||
@@ -729,7 +734,7 @@ gdk_vulkan_context_get_draw_index (GdkVulkanContext *context)
|
||||
* Gets the Vulkan semaphore that protects access to the image that is
|
||||
* currently being drawn.
|
||||
*
|
||||
* This function can only be used between gdk_cairo_context_begin_frame() and
|
||||
* This function can only be used between gdk_draw_context_begin_frame() and
|
||||
* gdk_draw_context_end_frame() calls.
|
||||
*
|
||||
* Returns: (transfer none): the VkSemaphore
|
||||
|
||||
@@ -35,12 +35,19 @@ gdk_quartz_monitor_get_workarea (GdkMonitor *monitor,
|
||||
|
||||
GDK_QUARTZ_ALLOC_POOL;
|
||||
|
||||
NSRect rect = [quartz_monitor->nsscreen visibleFrame];
|
||||
NSArray *array = [NSScreen screens];
|
||||
if (quartz_monitor->monitor_num < [array count])
|
||||
{
|
||||
NSScreen *screen = [array objectAtIndex:quartz_monitor->monitor_num];
|
||||
NSRect rect = [screen visibleFrame];
|
||||
|
||||
dest->x = rect.origin.x - quartz_screen->min_x;
|
||||
dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
|
||||
dest->width = rect.size.width;
|
||||
dest->height = rect.size.height;
|
||||
dest->x = rect.origin.x - quartz_screen->min_x;
|
||||
dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
|
||||
dest->width = rect.size.width;
|
||||
dest->height = rect.size.height;
|
||||
}
|
||||
else
|
||||
*dest = monitor->geometry;
|
||||
|
||||
GDK_QUARTZ_RELEASE_POOL;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ struct _GdkQuartzMonitor
|
||||
{
|
||||
GdkMonitor parent;
|
||||
|
||||
NSScreen *nsscreen;
|
||||
gint monitor_num;
|
||||
};
|
||||
|
||||
struct _GdkQuartzMonitorClass {
|
||||
|
||||
@@ -52,7 +52,9 @@ typedef enum
|
||||
GDK_OSX_YOSEMITE = 10,
|
||||
GDK_OSX_EL_CAPITAN = 11,
|
||||
GDK_OSX_SIERRA = 12,
|
||||
GDK_OSX_CURRENT = 12,
|
||||
GDK_OSX_HIGH_SIERRA = 13,
|
||||
GDK_OSX_MOJAVE = 14,
|
||||
GDK_OSX_CURRENT = 14,
|
||||
GDK_OSX_NEW = 99
|
||||
} GdkOSXVersion;
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
|
||||
"display", display,
|
||||
NULL);
|
||||
g_ptr_array_add (display_quartz->monitors, monitor);
|
||||
monitor->nsscreen = [array objectAtIndex:i];
|
||||
monitor->monitor_num = i;
|
||||
|
||||
NSRect rect = [[array objectAtIndex:i] frame];
|
||||
|
||||
|
||||
@@ -134,8 +134,12 @@ gdk_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *surface_impl,
|
||||
if (![surface_impl->view lockFocusIfCanDraw])
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cg_context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
if (gdk_quartz_osx_version () < GDK_OSX_YOSEMITE)
|
||||
cg_context = [[NSGraphicsContext currentContext] graphicsPort];
|
||||
else
|
||||
cg_context = [[NSGraphicsContext currentContext] CGContext];
|
||||
if (!cg_context)
|
||||
return NULL;
|
||||
CGContextSaveGState (cg_context);
|
||||
CGContextSetAllowsAntialiasing (cg_context, antialias);
|
||||
|
||||
@@ -276,15 +280,15 @@ gdk_quartz_create_cairo_surface (GdkSurfaceImplQuartz *impl,
|
||||
|
||||
cg_context = gdk_quartz_surface_get_context (impl, TRUE);
|
||||
|
||||
if (!cg_context)
|
||||
return NULL;
|
||||
|
||||
surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
|
||||
surface_data->surface_impl = impl;
|
||||
surface_data->cg_context = cg_context;
|
||||
|
||||
surface = cairo_quartz_surface_create_for_cg_context (cg_context,
|
||||
width, height);
|
||||
if (cg_context)
|
||||
surface = cairo_quartz_surface_create_for_cg_context (cg_context,
|
||||
width, height);
|
||||
else
|
||||
surface = cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
|
||||
cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
|
||||
surface_data,
|
||||
|
||||
@@ -730,7 +730,10 @@ gdk_wayland_display_finalize (GObject *object)
|
||||
|
||||
g_ptr_array_free (display_wayland->monitors, TRUE);
|
||||
|
||||
g_hash_table_destroy (display_wayland->settings);
|
||||
if (display_wayland->settings)
|
||||
g_hash_table_destroy (display_wayland->settings);
|
||||
|
||||
g_clear_object (&display_wayland->settings_portal);
|
||||
|
||||
G_OBJECT_CLASS (gdk_wayland_display_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -1207,13 +1210,21 @@ open_shared_memory (void)
|
||||
#if defined (__NR_memfd_create)
|
||||
if (!force_shm_open)
|
||||
{
|
||||
ret = syscall (__NR_memfd_create, "gdk-wayland", MFD_CLOEXEC);
|
||||
int options = MFD_CLOEXEC;
|
||||
#if defined (MFD_ALLOW_SEALING)
|
||||
options |= MFD_ALLOW_SEALING;
|
||||
#endif
|
||||
ret = syscall (__NR_memfd_create, "gdk-wayland", options);
|
||||
|
||||
/* fall back to shm_open until debian stops shipping 3.16 kernel
|
||||
* See bug 766341
|
||||
*/
|
||||
if (ret < 0 && errno == ENOSYS)
|
||||
force_shm_open = TRUE;
|
||||
#if defined (F_ADD_SEALS) && defined (F_SEAL_SHRINK)
|
||||
if (ret >= 0)
|
||||
fcntl (ret, F_ADD_SEALS, F_SEAL_SHRINK);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1368,6 +1379,19 @@ typedef enum
|
||||
GSD_FONT_ANTIALIASING_MODE_RGBA
|
||||
} GsdFontAntialiasingMode;
|
||||
|
||||
static int
|
||||
get_antialiasing (const char *s)
|
||||
{
|
||||
const char *names[] = { "none", "grayscale", "rgba" };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
if (strcmp (s, names[i]) == 0)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSD_FONT_HINTING_NONE,
|
||||
@@ -1376,6 +1400,19 @@ typedef enum
|
||||
GSD_FONT_HINTING_FULL
|
||||
} GsdFontHinting;
|
||||
|
||||
static int
|
||||
get_hinting (const char *s)
|
||||
{
|
||||
const char *names[] = { "none", "slight", "medium", "full" };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
if (strcmp (s, names[i]) == 0)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSD_FONT_RGBA_ORDER_RGBA,
|
||||
@@ -1385,6 +1422,19 @@ typedef enum
|
||||
GSD_FONT_RGBA_ORDER_VBGR
|
||||
} GsdFontRgbaOrder;
|
||||
|
||||
static int
|
||||
get_order (const char *s)
|
||||
{
|
||||
const char *names[] = { "rgba", "rgb", "bgr", "vrgb", "vbgr" };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (names); i++)
|
||||
if (strcmp (s, names[i]) == 0)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland)
|
||||
{
|
||||
@@ -1401,6 +1451,26 @@ get_dpi_from_gsettings (GdkWaylandDisplay *display_wayland)
|
||||
return 96.0 * factor;
|
||||
}
|
||||
|
||||
/* When using the Settings portal, we cache the value in
|
||||
* the fallback member, and we ignore the valid field
|
||||
*/
|
||||
typedef struct _TranslationEntry TranslationEntry;
|
||||
struct _TranslationEntry {
|
||||
gboolean valid;
|
||||
const gchar *schema;
|
||||
const gchar *key;
|
||||
const gchar *setting;
|
||||
GType type;
|
||||
union {
|
||||
const char *s;
|
||||
gint i;
|
||||
gboolean b;
|
||||
} fallback;
|
||||
};
|
||||
|
||||
static TranslationEntry * find_translation_entry_by_schema (const char *schema,
|
||||
const char *key);
|
||||
|
||||
static void
|
||||
update_xft_settings (GdkDisplay *display)
|
||||
{
|
||||
@@ -1411,25 +1481,47 @@ update_xft_settings (GdkDisplay *display)
|
||||
GsdFontRgbaOrder order;
|
||||
gboolean use_rgba = FALSE;
|
||||
GsdXftSettings xft_settings;
|
||||
double dpi;
|
||||
|
||||
settings = g_hash_table_lookup (display_wayland->settings,
|
||||
"org.gnome.settings-daemon.plugins.xsettings");
|
||||
|
||||
if (settings)
|
||||
if (display_wayland->settings_portal)
|
||||
{
|
||||
antialiasing = g_settings_get_enum (settings, "antialiasing");
|
||||
hinting = g_settings_get_enum (settings, "hinting");
|
||||
order = g_settings_get_enum (settings, "rgba-order");
|
||||
TranslationEntry *entry;
|
||||
|
||||
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "antialiasing");
|
||||
antialiasing = entry->fallback.i;
|
||||
|
||||
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "hinting");
|
||||
hinting = entry->fallback.i;
|
||||
|
||||
entry = find_translation_entry_by_schema ("org.gnome.settings-daemon.plugins.xsettings", "rgba-order");
|
||||
order = entry->fallback.i;
|
||||
|
||||
entry = find_translation_entry_by_schema ("org.gnome.desktop.interface", "text-scaling-factor");
|
||||
dpi = 96.0 * entry->fallback.i / 65536.0 * 1024; /* Xft wants 1/1024th of an inch */
|
||||
}
|
||||
else
|
||||
{
|
||||
antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE;
|
||||
hinting = GSD_FONT_HINTING_MEDIUM;
|
||||
order = GSD_FONT_RGBA_ORDER_RGB;
|
||||
settings = g_hash_table_lookup (display_wayland->settings,
|
||||
"org.gnome.settings-daemon.plugins.xsettings");
|
||||
|
||||
if (settings)
|
||||
{
|
||||
antialiasing = g_settings_get_enum (settings, "antialiasing");
|
||||
hinting = g_settings_get_enum (settings, "hinting");
|
||||
order = g_settings_get_enum (settings, "rgba-order");
|
||||
}
|
||||
else
|
||||
{
|
||||
antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE;
|
||||
hinting = GSD_FONT_HINTING_MEDIUM;
|
||||
order = GSD_FONT_RGBA_ORDER_RGB;
|
||||
}
|
||||
|
||||
dpi = get_dpi_from_gsettings (display_wayland) * 1024;
|
||||
}
|
||||
|
||||
xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE);
|
||||
xft_settings.dpi = get_dpi_from_gsettings (display_wayland) * 1024; /* Xft wants 1/1024ths of an inch */
|
||||
xft_settings.dpi = dpi;
|
||||
|
||||
switch (hinting)
|
||||
{
|
||||
@@ -1516,23 +1608,6 @@ update_xft_settings (GdkDisplay *display)
|
||||
}
|
||||
}
|
||||
|
||||
#define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences"
|
||||
#define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides"
|
||||
|
||||
typedef struct _TranslationEntry TranslationEntry;
|
||||
struct _TranslationEntry {
|
||||
gboolean valid;
|
||||
const gchar *schema;
|
||||
const gchar *key;
|
||||
const gchar *setting;
|
||||
GType type;
|
||||
union {
|
||||
const gchar *s;
|
||||
gint i;
|
||||
gboolean b;
|
||||
} fallback;
|
||||
};
|
||||
|
||||
static TranslationEntry translations[] = {
|
||||
{ FALSE, "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } },
|
||||
{ FALSE, "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } },
|
||||
@@ -1552,41 +1627,48 @@ static TranslationEntry translations[] = {
|
||||
{ FALSE, "org.gnome.desktop.sound", "input-feedback-sounds", "gtk-enable-input-feedback-sounds", G_TYPE_BOOLEAN, { . b = FALSE } },
|
||||
{ FALSE, "org.gnome.desktop.privacy", "recent-files-max-age", "gtk-recent-files-max-age", G_TYPE_INT, { .i = 30 } },
|
||||
{ FALSE, "org.gnome.desktop.privacy", "remember-recent-files", "gtk-recent-files-enabled", G_TYPE_BOOLEAN, { .b = TRUE } },
|
||||
{ FALSE, WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
|
||||
{ FALSE, CLASSIC_WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
|
||||
{ FALSE, "org.gnome.desktop.wm.preferences", "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
|
||||
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 0 } },
|
||||
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } },
|
||||
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } },
|
||||
{ FALSE, "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } },
|
||||
{ FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } },
|
||||
{ FALSE, "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } }, /* We store the factor as 16.16 */
|
||||
{ FALSE, "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } },
|
||||
{ FALSE, "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } },
|
||||
{ FALSE, "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
|
||||
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } }
|
||||
{ FALSE, "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } },
|
||||
{ FALSE, "org.gnome.fontconfig", "serial", "gtk-fontconfig-timestamp", G_TYPE_NONE, { .i = 0 } }
|
||||
};
|
||||
|
||||
|
||||
static TranslationEntry *
|
||||
find_translation_entry_by_key (GSettings *settings,
|
||||
const char *key)
|
||||
find_translation_entry_by_schema (const char *schema,
|
||||
const char *key)
|
||||
{
|
||||
guint i;
|
||||
char *schema;
|
||||
|
||||
g_object_get (settings, "schema", &schema, NULL);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (translations); i++)
|
||||
{
|
||||
if (g_str_equal (schema, translations[i].schema) &&
|
||||
g_str_equal (key, translations[i].key))
|
||||
{
|
||||
g_free (schema);
|
||||
return &translations[i];
|
||||
}
|
||||
return &translations[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static TranslationEntry *
|
||||
find_translation_entry_by_key (GSettings *settings,
|
||||
const char *key)
|
||||
{
|
||||
char *schema;
|
||||
TranslationEntry *entry;
|
||||
|
||||
g_object_get (settings, "schema", &schema, NULL);
|
||||
entry = find_translation_entry_by_schema (schema, key);
|
||||
g_free (schema);
|
||||
|
||||
return NULL;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static TranslationEntry *
|
||||
@@ -1621,6 +1703,79 @@ settings_changed (GSettings *settings,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_portal_setting (TranslationEntry *entry,
|
||||
GVariant *value,
|
||||
GdkDisplay *display)
|
||||
{
|
||||
switch (entry->type)
|
||||
{
|
||||
case G_TYPE_STRING:
|
||||
entry->fallback.s = g_intern_string (g_variant_get_string (value, NULL));
|
||||
break;
|
||||
case G_TYPE_INT:
|
||||
entry->fallback.i = g_variant_get_int32 (value);
|
||||
break;
|
||||
case G_TYPE_BOOLEAN:
|
||||
entry->fallback.b = g_variant_get_boolean (value);
|
||||
break;
|
||||
case G_TYPE_NONE:
|
||||
if (strcmp (entry->key, "serial") == 0)
|
||||
{
|
||||
entry->fallback.i = g_variant_get_int32 (value);
|
||||
break;
|
||||
}
|
||||
if (strcmp (entry->key, "antialiasing") == 0)
|
||||
entry->fallback.i = get_antialiasing (g_variant_get_string (value, NULL));
|
||||
else if (strcmp (entry->key, "hinting") == 0)
|
||||
entry->fallback.i = get_hinting (g_variant_get_string (value, NULL));
|
||||
else if (strcmp (entry->key, "rgba-order") == 0)
|
||||
entry->fallback.i = get_order (g_variant_get_string (value, NULL));
|
||||
else if (strcmp (entry->key, "text-scaling-factor") == 0)
|
||||
entry->fallback.i = (int) (g_variant_get_double (value) * 65536.0);
|
||||
update_xft_settings (display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
settings_portal_changed (GDBusProxy *proxy,
|
||||
const char *sender_name,
|
||||
const char *signal_name,
|
||||
GVariant *parameters,
|
||||
GdkDisplay *display)
|
||||
{
|
||||
if (strcmp (signal_name, "SettingChanged") == 0)
|
||||
{
|
||||
const char *namespace;
|
||||
const char *name;
|
||||
GVariant *value;
|
||||
TranslationEntry *entry;
|
||||
|
||||
g_variant_get (parameters, "(&s&sv)", &namespace, &name, &value);
|
||||
|
||||
entry = find_translation_entry_by_schema (namespace, name);
|
||||
if (entry != NULL)
|
||||
{
|
||||
char *a = g_variant_print (value, FALSE);
|
||||
g_debug ("Using changed portal setting %s %s: %s", namespace, name, a);
|
||||
g_free (a);
|
||||
apply_portal_setting (entry, value, display);
|
||||
gdk_display_setting_changed (display, entry->setting);
|
||||
}
|
||||
else
|
||||
g_debug ("Ignoring portal setting %s %s", namespace, name);
|
||||
|
||||
g_variant_unref (value);
|
||||
}
|
||||
}
|
||||
|
||||
#define PORTAL_BUS_NAME "org.freedesktop.portal.Desktop"
|
||||
#define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
|
||||
#define PORTAL_SETTINGS_INTERFACE "org.freedesktop.portal.Settings"
|
||||
|
||||
static void
|
||||
init_settings (GdkDisplay *display)
|
||||
{
|
||||
@@ -1630,6 +1785,86 @@ init_settings (GdkDisplay *display)
|
||||
GSettings *settings;
|
||||
gint i;
|
||||
|
||||
if (gdk_should_use_portal ())
|
||||
{
|
||||
GVariant *ret;
|
||||
GError *error = NULL;
|
||||
const char *schema;
|
||||
GVariant *val;
|
||||
GVariantIter *iter;
|
||||
const char *patterns[] = { "org.gnome.*", NULL };
|
||||
|
||||
display_wayland->settings_portal = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
NULL,
|
||||
PORTAL_BUS_NAME,
|
||||
PORTAL_OBJECT_PATH,
|
||||
PORTAL_SETTINGS_INTERFACE,
|
||||
NULL,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Settings portal not found: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
ret = g_dbus_proxy_call_sync (display_wayland->settings_portal,
|
||||
"ReadAll",
|
||||
g_variant_new ("(^as)", patterns),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
G_MAXINT,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Failed to read portal settings: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_clear_object (&display_wayland->settings_portal);
|
||||
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
g_variant_get (ret, "(a{sa{sv}})", &iter);
|
||||
|
||||
while (g_variant_iter_loop (iter, "{s@a{sv}}", &schema, &val))
|
||||
{
|
||||
GVariantIter *iter2 = g_variant_iter_new (val);
|
||||
const char *key;
|
||||
GVariant *v;
|
||||
|
||||
while (g_variant_iter_loop (iter2, "{sv}", &key, &v))
|
||||
{
|
||||
TranslationEntry *entry = find_translation_entry_by_schema (schema, key);
|
||||
if (entry)
|
||||
{
|
||||
char *a = g_variant_print (v, FALSE);
|
||||
g_debug ("Using portal setting for %s %s: %s\n", schema, key, a);
|
||||
g_free (a);
|
||||
apply_portal_setting (entry, v, display);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Ignoring portal setting for %s %s", schema, key);
|
||||
}
|
||||
}
|
||||
g_variant_iter_free (iter2);
|
||||
}
|
||||
g_variant_iter_free (iter);
|
||||
|
||||
g_variant_unref (ret);
|
||||
|
||||
g_signal_connect (display_wayland->settings_portal, "g-signal",
|
||||
G_CALLBACK (settings_portal_changed), display_wayland);
|
||||
|
||||
return;
|
||||
|
||||
fallback:
|
||||
g_debug ("Failed to use Settings portal; falling back to gsettings");
|
||||
}
|
||||
|
||||
g_intern_static_string ("antialiasing");
|
||||
g_intern_static_string ("hinting");
|
||||
g_intern_static_string ("rgba-order");
|
||||
@@ -1701,6 +1936,43 @@ set_value_from_entry (GdkDisplay *display,
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GSettings *settings;
|
||||
|
||||
if (display_wayland->settings_portal)
|
||||
{
|
||||
switch (entry->type)
|
||||
{
|
||||
case G_TYPE_STRING:
|
||||
g_value_set_string (value, entry->fallback.s);
|
||||
break;
|
||||
case G_TYPE_INT:
|
||||
g_value_set_int (value, entry->fallback.i);
|
||||
break;
|
||||
case G_TYPE_BOOLEAN:
|
||||
g_value_set_boolean (value, entry->fallback.b);
|
||||
break;
|
||||
case G_TYPE_NONE:
|
||||
if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp"))
|
||||
g_value_set_uint (value, (guint)entry->fallback.i);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-antialias"))
|
||||
g_value_set_int (value, display_wayland->xft_settings.antialias);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-hinting"))
|
||||
g_value_set_int (value, display_wayland->xft_settings.hinting);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-hintstyle"))
|
||||
g_value_set_static_string (value, display_wayland->xft_settings.hintstyle);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-rgba"))
|
||||
g_value_set_static_string (value, display_wayland->xft_settings.rgba);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-dpi"))
|
||||
g_value_set_int (value, display_wayland->xft_settings.dpi);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema);
|
||||
switch (entry->type)
|
||||
{
|
||||
@@ -1728,7 +2000,9 @@ set_value_from_entry (GdkDisplay *display,
|
||||
: entry->fallback.b);
|
||||
break;
|
||||
case G_TYPE_NONE:
|
||||
if (g_str_equal (entry->setting, "gtk-xft-antialias"))
|
||||
if (g_str_equal (entry->setting, "gtk-fontconfig-timestamp"))
|
||||
g_value_set_uint (value, (guint)entry->fallback.i);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-antialias"))
|
||||
g_value_set_int (value, display_wayland->xft_settings.antialias);
|
||||
else if (g_str_equal (entry->setting, "gtk-xft-hinting"))
|
||||
g_value_set_int (value, display_wayland->xft_settings.hinting);
|
||||
@@ -1753,18 +2027,14 @@ set_decoration_layout_from_entry (GdkDisplay *display,
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
GSettings *settings = NULL;
|
||||
const char *session;
|
||||
|
||||
/* Hack: until we get session-dependent defaults in GSettings,
|
||||
* swap out the usual schema for the "classic" one when
|
||||
* running in classic mode
|
||||
*/
|
||||
session = g_getenv ("XDG_CURRENT_DESKTOP");
|
||||
if (session && strstr (session, "GNOME-Classic"))
|
||||
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, CLASSIC_WM_SETTINGS_SCHEMA);
|
||||
if (display_wayland->settings_portal)
|
||||
{
|
||||
g_value_set_string (value, entry->fallback.s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings == NULL)
|
||||
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, WM_SETTINGS_SCHEMA);
|
||||
settings = (GSettings *)g_hash_table_lookup (display_wayland->settings, entry->schema);
|
||||
|
||||
if (settings)
|
||||
{
|
||||
@@ -1800,7 +2070,8 @@ gdk_wayland_display_get_setting (GdkDisplay *display,
|
||||
{
|
||||
TranslationEntry *entry;
|
||||
|
||||
if (g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0)
|
||||
if (GDK_WAYLAND_DISPLAY (display)->settings != NULL &&
|
||||
g_hash_table_size (GDK_WAYLAND_DISPLAY (display)->settings) == 0)
|
||||
return FALSE;
|
||||
|
||||
entry = find_translation_entry_by_setting (name);
|
||||
|
||||
@@ -77,6 +77,7 @@ struct _GdkWaylandDisplay
|
||||
|
||||
GHashTable *settings;
|
||||
GsdXftSettings xft_settings;
|
||||
GDBusProxy *settings_portal;
|
||||
|
||||
guint32 shell_capabilities;
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContext *shared;
|
||||
GdkWaylandGLContext *shared_wayland;
|
||||
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared == NULL)
|
||||
shared = context;
|
||||
@@ -182,20 +182,29 @@ gdk_wayland_gl_context_get_damage (GdkGLContext *context)
|
||||
eglQuerySurface (display_wayland->egl_display, egl_surface,
|
||||
EGL_BUFFER_AGE_EXT, &buffer_age);
|
||||
|
||||
if (buffer_age == 2)
|
||||
switch (buffer_age)
|
||||
{
|
||||
if (context->old_updated_area[0])
|
||||
return cairo_region_copy (context->old_updated_area[0]);
|
||||
}
|
||||
else if (buffer_age == 3)
|
||||
{
|
||||
if (context->old_updated_area[0] &&
|
||||
context->old_updated_area[1])
|
||||
{
|
||||
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
|
||||
cairo_region_union (damage, context->old_updated_area[1]);
|
||||
return damage;
|
||||
}
|
||||
case 1:
|
||||
return cairo_region_create ();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (context->old_updated_area[0])
|
||||
return cairo_region_copy (context->old_updated_area[0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (context->old_updated_area[0] &&
|
||||
context->old_updated_area[1])
|
||||
{
|
||||
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
|
||||
cairo_region_union (damage, context->old_updated_area[1]);
|
||||
return damage;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,6 @@ struct _GdkSurfaceImplWayland
|
||||
struct zxdg_popup_v6 *zxdg_popup_v6;
|
||||
|
||||
struct gtk_surface1 *gtk_surface;
|
||||
struct wl_subsurface *wl_subsurface;
|
||||
struct wl_egl_window *egl_window;
|
||||
struct wl_egl_window *dummy_egl_window;
|
||||
struct zxdg_exported_v1 *xdg_exported;
|
||||
@@ -218,8 +217,6 @@ static void gdk_wayland_surface_maybe_configure (GdkSurface *surface,
|
||||
static void maybe_set_gtk_surface_dbus_properties (GdkSurface *surface);
|
||||
static void maybe_set_gtk_surface_modal (GdkSurface *surface);
|
||||
|
||||
static void gdk_surface_request_transient_parent_commit (GdkSurface *surface);
|
||||
|
||||
static void gdk_wayland_surface_sync_margin (GdkSurface *surface);
|
||||
static void gdk_wayland_surface_sync_input_region (GdkSurface *surface);
|
||||
static void gdk_wayland_surface_sync_opaque_region (GdkSurface *surface);
|
||||
@@ -1030,31 +1027,6 @@ gdk_wayland_surface_sync_input_region (GdkSurface *surface)
|
||||
impl->input_region_dirty = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_set_input_region_if_empty (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
GdkWaylandDisplay *display;
|
||||
struct wl_region *empty;
|
||||
|
||||
if (!impl->input_region_dirty)
|
||||
return;
|
||||
|
||||
if (impl->input_region == NULL)
|
||||
return;
|
||||
|
||||
if (!cairo_region_is_empty (impl->input_region))
|
||||
return;
|
||||
|
||||
display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
empty = wl_compositor_create_region (display->compositor);
|
||||
|
||||
wl_surface_set_input_region (impl->display_server.wl_surface, empty);
|
||||
wl_region_destroy (empty);
|
||||
|
||||
impl->input_region_dirty = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_enter (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
@@ -1093,61 +1065,6 @@ static const struct wl_surface_listener surface_listener = {
|
||||
surface_leave
|
||||
};
|
||||
|
||||
static void
|
||||
on_parent_surface_committed (GdkSurfaceImplWayland *parent_impl,
|
||||
GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
|
||||
g_signal_handler_disconnect (parent_impl,
|
||||
impl->parent_surface_committed_handler);
|
||||
impl->parent_surface_committed_handler = 0;
|
||||
|
||||
wl_subsurface_set_desync (impl->display_server.wl_subsurface);
|
||||
|
||||
/* Special case if the input region is empty, it won't change on resize */
|
||||
gdk_wayland_set_input_region_if_empty (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_create_subsurface (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl, *parent_impl = NULL;
|
||||
GdkWaylandDisplay *display_wayland;
|
||||
|
||||
impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
|
||||
if (!impl->display_server.wl_surface)
|
||||
return; /* Bail out, surface and subsurface will be created later when shown */
|
||||
|
||||
if (impl->display_server.wl_subsurface)
|
||||
return;
|
||||
|
||||
if (impl->transient_for)
|
||||
parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
|
||||
|
||||
if (parent_impl && parent_impl->display_server.wl_surface)
|
||||
{
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
|
||||
impl->display_server.wl_subsurface =
|
||||
wl_subcompositor_get_subsurface (display_wayland->subcompositor,
|
||||
impl->display_server.wl_surface, parent_impl->display_server.wl_surface);
|
||||
wl_subsurface_set_position (impl->display_server.wl_subsurface,
|
||||
surface->x + surface->abs_x,
|
||||
surface->y + surface->abs_y);
|
||||
|
||||
/* In order to synchronize the initial position with the initial frame
|
||||
* content, wait with making the subsurface desynchronized until after
|
||||
* the parent was committed.
|
||||
*/
|
||||
impl->parent_surface_committed_handler =
|
||||
g_signal_connect_object (parent_impl, "committed",
|
||||
G_CALLBACK (on_parent_surface_committed),
|
||||
surface, 0);
|
||||
gdk_surface_request_transient_parent_commit (surface);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_surface_create_surface (GdkSurface *surface)
|
||||
{
|
||||
@@ -1515,7 +1432,9 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface)
|
||||
|
||||
impl->initial_fullscreen_output = NULL;
|
||||
|
||||
app_id = g_get_prgname ();
|
||||
app_id = impl->application.application_id;
|
||||
if (app_id == NULL)
|
||||
app_id = g_get_prgname ();
|
||||
|
||||
if (app_id == NULL)
|
||||
app_id = "GTK+ Application";
|
||||
@@ -1567,6 +1486,8 @@ gdk_wayland_surface_handle_configure_popup (GdkSurface *surface,
|
||||
&flipped_x,
|
||||
&flipped_y);
|
||||
|
||||
impl->position_method = POSITION_METHOD_MOVE_TO_RECT;
|
||||
|
||||
g_signal_emit_by_name (surface,
|
||||
"moved-to-rect",
|
||||
&flipped_rect,
|
||||
@@ -1789,23 +1710,15 @@ get_real_parent_and_translate (GdkSurface *surface,
|
||||
|
||||
while (parent)
|
||||
{
|
||||
GdkSurfaceImplWayland *parent_impl =
|
||||
GDK_SURFACE_IMPL_WAYLAND (parent->impl);
|
||||
GdkSurface *effective_parent = gdk_surface_get_parent (parent);
|
||||
|
||||
if ((gdk_surface_has_native (parent) &&
|
||||
!parent_impl->display_server.wl_subsurface) ||
|
||||
!effective_parent)
|
||||
if (gdk_surface_has_native (parent) && !effective_parent)
|
||||
break;
|
||||
|
||||
*x += parent->x;
|
||||
*y += parent->y;
|
||||
|
||||
if (gdk_surface_has_native (parent) &&
|
||||
parent_impl->display_server.wl_subsurface)
|
||||
parent = parent->transient_for;
|
||||
else
|
||||
parent = effective_parent;
|
||||
parent = effective_parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
@@ -2465,38 +2378,9 @@ should_map_as_popup (GdkSurface *surface)
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
should_map_as_subsurface (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
|
||||
if (GDK_SURFACE_TYPE (surface) == GDK_SURFACE_SUBSURFACE)
|
||||
if (impl->position_method == POSITION_METHOD_MOVE_TO_RECT)
|
||||
return TRUE;
|
||||
|
||||
if (GDK_SURFACE_TYPE (surface) != GDK_SURFACE_TEMP)
|
||||
return FALSE;
|
||||
|
||||
/* if we want a popup, we do not want a subsurface */
|
||||
if (should_map_as_popup (surface))
|
||||
return FALSE;
|
||||
|
||||
if (impl->transient_for)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl_parent;
|
||||
|
||||
impl_parent = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
|
||||
/* subsurface require that the parent is mapped */
|
||||
if (impl_parent->mapped)
|
||||
return TRUE;
|
||||
else
|
||||
g_warning ("Couldn't map surface %p as subsurface because its parent is not mapped.",
|
||||
surface);
|
||||
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -2532,15 +2416,7 @@ gdk_wayland_surface_map (GdkSurface *surface)
|
||||
if (impl->mapped || impl->use_custom_surface)
|
||||
return;
|
||||
|
||||
if (should_map_as_subsurface (surface))
|
||||
{
|
||||
if (impl->transient_for)
|
||||
gdk_wayland_surface_create_subsurface (surface);
|
||||
else
|
||||
g_warning ("Couldn't map surface %p as susburface yet because it doesn't have a parent",
|
||||
surface);
|
||||
}
|
||||
else if (should_map_as_popup (surface))
|
||||
if (should_map_as_popup (surface))
|
||||
{
|
||||
gboolean create_fallback = FALSE;
|
||||
struct wl_seat *grab_input_seat;
|
||||
@@ -2641,26 +2517,6 @@ gdk_wayland_surface_show (GdkSurface *surface,
|
||||
gdk_wayland_surface_map (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_subsurface (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
GdkSurfaceImplWayland *parent_impl;
|
||||
|
||||
g_return_if_fail (impl->display_server.wl_subsurface);
|
||||
g_return_if_fail (impl->transient_for);
|
||||
|
||||
parent_impl = GDK_SURFACE_IMPL_WAYLAND (impl->transient_for->impl);
|
||||
wl_subsurface_destroy (impl->display_server.wl_subsurface);
|
||||
if (impl->parent_surface_committed_handler)
|
||||
{
|
||||
g_signal_handler_disconnect (parent_impl,
|
||||
impl->parent_surface_committed_handler);
|
||||
impl->parent_surface_committed_handler = 0;
|
||||
}
|
||||
impl->display_server.wl_subsurface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
unmap_popups_for_surface (GdkSurface *surface)
|
||||
{
|
||||
@@ -2761,9 +2617,6 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
impl->initial_configure_received = FALSE;
|
||||
}
|
||||
|
||||
if (impl->display_server.wl_subsurface)
|
||||
unmap_subsurface (surface);
|
||||
|
||||
if (impl->awaiting_frame)
|
||||
{
|
||||
GdkFrameClock *frame_clock;
|
||||
@@ -2837,32 +2690,6 @@ gdk_surface_wayland_restack_toplevel (GdkSurface *surface,
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_request_transient_parent_commit (GdkSurface *surface)
|
||||
{
|
||||
GdkSurfaceImplWayland *surface_impl, *impl;
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
surface_impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
|
||||
if (!surface_impl->transient_for)
|
||||
return;
|
||||
|
||||
impl = GDK_SURFACE_IMPL_WAYLAND (surface_impl->transient_for->impl);
|
||||
|
||||
if (!impl->display_server.wl_surface || impl->pending_commit)
|
||||
return;
|
||||
|
||||
frame_clock = gdk_surface_get_frame_clock (surface_impl->transient_for);
|
||||
|
||||
if (!frame_clock)
|
||||
return;
|
||||
|
||||
impl->pending_commit = TRUE;
|
||||
gdk_frame_clock_request_phase (frame_clock,
|
||||
GDK_FRAME_CLOCK_PHASE_AFTER_PAINT);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_surface_wayland_move_resize (GdkSurface *surface,
|
||||
gboolean with_move,
|
||||
@@ -2881,14 +2708,6 @@ gdk_surface_wayland_move_resize (GdkSurface *surface,
|
||||
surface->x = x;
|
||||
surface->y = y;
|
||||
impl->position_method = POSITION_METHOD_MOVE_RESIZE;
|
||||
|
||||
if (impl->display_server.wl_subsurface)
|
||||
{
|
||||
wl_subsurface_set_position (impl->display_server.wl_subsurface,
|
||||
surface->x + surface->abs_x,
|
||||
surface->y + surface->abs_y);
|
||||
gdk_surface_request_transient_parent_commit (surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3414,9 +3233,6 @@ gdk_wayland_surface_set_transient_for (GdkSurface *surface,
|
||||
|
||||
unset_transient_for_exported (surface);
|
||||
|
||||
if (impl->display_server.wl_subsurface)
|
||||
unmap_subsurface (surface);
|
||||
|
||||
previous_parent = impl->transient_for;
|
||||
impl->transient_for = parent;
|
||||
|
||||
@@ -3429,9 +3245,6 @@ gdk_wayland_surface_set_transient_for (GdkSurface *surface,
|
||||
g_list_remove (display_wayland->orphan_dialogs, surface);
|
||||
}
|
||||
gdk_wayland_surface_sync_parent (surface, NULL);
|
||||
if (should_map_as_subsurface (surface) &&
|
||||
parent && gdk_surface_is_visible (surface))
|
||||
gdk_wayland_surface_create_subsurface (surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4098,34 +3911,6 @@ _gdk_wayland_surface_set_grab_seat (GdkSurface *surface,
|
||||
impl->grab_input_seat = seat;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_surface_new_subsurface: (constructor)
|
||||
* @display: the display to create the surface on
|
||||
* @position: position relative to the transient surface
|
||||
*
|
||||
* Creates a new subsurface surface.
|
||||
*
|
||||
* Returns: (transfer full): the new #GdkSurface
|
||||
**/
|
||||
GdkSurface *
|
||||
gdk_wayland_surface_new_subsurface (GdkDisplay *display,
|
||||
const GdkRectangle *position)
|
||||
{
|
||||
GdkSurfaceAttr attr;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
|
||||
g_return_val_if_fail (position != NULL, NULL);
|
||||
|
||||
attr.wclass = GDK_INPUT_OUTPUT;
|
||||
attr.x = position->x;
|
||||
attr.y = position->y;
|
||||
attr.width = position->width;
|
||||
attr.height = position->height;
|
||||
attr.surface_type = GDK_SURFACE_SUBSURFACE;
|
||||
|
||||
return gdk_surface_new (display, NULL, &attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_wayland_surface_get_wl_surface:
|
||||
* @surface: (type GdkWaylandSurface): a #GdkSurface
|
||||
@@ -4533,8 +4318,7 @@ gdk_wayland_surface_set_transient_for_exported (GdkSurface *surface,
|
||||
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_SURFACE (surface), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
|
||||
g_return_val_if_fail (!should_map_as_subsurface (surface) &&
|
||||
!should_map_as_popup (surface), FALSE);
|
||||
g_return_val_if_fail (!should_map_as_popup (surface), FALSE);
|
||||
|
||||
impl = GDK_SURFACE_IMPL_WAYLAND (surface->impl);
|
||||
display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
|
||||
@@ -1655,7 +1655,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
|
||||
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_PNG);
|
||||
@@ -1665,14 +1665,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.w32format = CF_DIB;
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG);
|
||||
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_JPEG);
|
||||
@@ -1682,17 +1678,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.w32format = CF_DIB;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_GIF);
|
||||
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_IMAGE_GIF);
|
||||
@@ -1702,13 +1691,6 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.w32format = CF_DIB;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_w32formats, (gpointer) fmt.contentformat, comp);
|
||||
|
||||
|
||||
@@ -1771,7 +1753,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (CF_UNICODETEXT), comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG);
|
||||
fmt.transmute = FALSE;
|
||||
|
||||
@@ -1781,14 +1763,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_PNG)), comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF);
|
||||
fmt.transmute = FALSE;
|
||||
|
||||
@@ -1798,17 +1776,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_JPEG);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_JFIF)), comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 4);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF);
|
||||
fmt.transmute = FALSE;
|
||||
|
||||
@@ -1818,17 +1789,10 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_GIF);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_PNG);
|
||||
fmt.transmute = TRUE;
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
fmt.contentformat = _gdk_atom_array_index (atoms, GDK_WIN32_ATOM_INDEX_IMAGE_BMP);
|
||||
g_array_append_val (comp, fmt);
|
||||
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (_gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_GIF)), comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.w32format = CF_DIB;
|
||||
fmt.transmute = FALSE;
|
||||
|
||||
@@ -1842,7 +1806,7 @@ gdk_win32_clipdrop_init (GdkWin32Clipdrop *win32_clipdrop)
|
||||
g_hash_table_replace (win32_clipdrop->compatibility_contentformats, GINT_TO_POINTER (CF_DIB), comp);
|
||||
|
||||
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 3);
|
||||
comp = g_array_sized_new (FALSE, FALSE, sizeof (GdkWin32ContentFormatPair), 2);
|
||||
fmt.w32format = _gdk_cf_array_index (cfs, GDK_WIN32_CF_INDEX_CFSTR_SHELLIDLIST);
|
||||
fmt.transmute = FALSE;
|
||||
|
||||
|
||||
@@ -1701,7 +1701,7 @@ ensure_stacking_on_unminimize (MSG *msg)
|
||||
g_print (" restacking %p above %p",
|
||||
msg->hwnd, lowest_transient));
|
||||
SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1782,7 +1782,7 @@ ensure_stacking_on_activate_app (MSG *msg,
|
||||
impl->transient_owner != NULL)
|
||||
{
|
||||
SetWindowPos (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1824,7 +1824,7 @@ ensure_stacking_on_activate_app (MSG *msg,
|
||||
g_print (" restacking %p above %p",
|
||||
msg->hwnd, rover));
|
||||
SetWindowPos (msg->hwnd, rover, 0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2124,6 +2124,7 @@ gdk_event_translate (MSG *msg,
|
||||
(gulong) msg->wParam,
|
||||
(gpointer) msg->lParam, _gdk_input_locale_is_ime ? " (IME)" : "",
|
||||
_gdk_input_codepage));
|
||||
gdk_display_setting_changed (display, "gtk-im-module");
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
@@ -2712,13 +2713,20 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
event = gdk_event_new (GDK_SCROLL);
|
||||
event->any.surface = window;
|
||||
event->scroll.direction = GDK_SCROLL_SMOOTH;
|
||||
|
||||
if (msg->message == WM_MOUSEWHEEL)
|
||||
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
|
||||
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
|
||||
{
|
||||
event->scroll.delta_y = (gdouble) GET_WHEEL_DELTA_WPARAM (msg->wParam) / (gdouble) WHEEL_DELTA;
|
||||
}
|
||||
else if (msg->message == WM_MOUSEHWHEEL)
|
||||
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
|
||||
GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT;
|
||||
{
|
||||
event->scroll.delta_x = (gdouble) GET_WHEEL_DELTA_WPARAM (msg->wParam) / (gdouble) WHEEL_DELTA;
|
||||
}
|
||||
/* Positive delta scrolls up, not down,
|
||||
see API documentation for WM_MOUSEWHEEL message.
|
||||
*/
|
||||
event->scroll.delta_y *= -1.0;
|
||||
event->scroll.time = _gdk_win32_get_next_tick (msg->time);
|
||||
event->scroll.x = (gint16) point.x / impl->surface_scale;
|
||||
event->scroll.y = (gint16) point.y / impl->surface_scale;
|
||||
@@ -2727,6 +2735,20 @@ gdk_event_translate (MSG *msg,
|
||||
event->scroll.state = build_pointer_event_state (msg);
|
||||
gdk_event_set_device (event, device_manager_win32->core_pointer);
|
||||
gdk_event_set_source_device (event, device_manager_win32->system_pointer);
|
||||
gdk_event_set_pointer_emulated (event, FALSE);
|
||||
|
||||
_gdk_win32_append_event (gdk_event_copy (event));
|
||||
|
||||
/* Append the discrete version too */
|
||||
if (msg->message == WM_MOUSEWHEEL)
|
||||
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
|
||||
GDK_SCROLL_UP : GDK_SCROLL_DOWN;
|
||||
else if (msg->message == WM_MOUSEHWHEEL)
|
||||
event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
|
||||
GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT;
|
||||
event->scroll.delta_x = 0;
|
||||
event->scroll.delta_y = 0;
|
||||
gdk_event_set_pointer_emulated (event, TRUE);
|
||||
|
||||
_gdk_win32_append_event (event);
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ gdk_win32_hdata_output_stream_close (GOutputStream *output_stream,
|
||||
if (priv->handle_is_buffer)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Can't transmute a single handle"));
|
||||
_("Can’t transmute a single handle"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,12 +27,39 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <pango/pangowin32.h>
|
||||
|
||||
#include "gdkproperty.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkprivate-win32.h"
|
||||
#include "gdkwin32.h"
|
||||
|
||||
static gchar*
|
||||
_get_system_font_name (HDC hdc)
|
||||
{
|
||||
NONCLIENTMETRICSW ncm;
|
||||
PangoFontDescription *font_desc;
|
||||
gchar *result, *font_desc_string;
|
||||
int logpixelsy;
|
||||
gint font_size;
|
||||
|
||||
ncm.cbSize = sizeof(NONCLIENTMETRICSW);
|
||||
if (!SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0))
|
||||
return NULL;
|
||||
|
||||
logpixelsy = GetDeviceCaps (hdc, LOGPIXELSY);
|
||||
font_desc = pango_win32_font_description_from_logfontw (&ncm.lfMessageFont);
|
||||
font_desc_string = pango_font_description_to_string (font_desc);
|
||||
pango_font_description_free (font_desc);
|
||||
|
||||
/* https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-taglogfonta */
|
||||
font_size = -MulDiv (ncm.lfMessageFont.lfHeight, 72, logpixelsy);
|
||||
result = g_strdup_printf ("%s %d", font_desc_string, font_size);
|
||||
g_free (font_desc_string);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
For reference, from gdk/x11/gdksettings.c:
|
||||
|
||||
@@ -124,61 +151,75 @@ _gdk_win32_get_setting (const gchar *name,
|
||||
g_value_set_boolean (value, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp ("gtk-xft-hinting", name) == 0)
|
||||
{
|
||||
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : 1\n", name));
|
||||
g_value_set_int (value, 1);
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp ("gtk-xft-antialias", name) == 0)
|
||||
{
|
||||
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : 1\n", name));
|
||||
g_value_set_int (value, 1);
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp ("gtk-xft-hintstyle", name) == 0)
|
||||
{
|
||||
g_value_set_static_string (value, "hintfull");
|
||||
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %s\n", name, g_value_get_string (value)));
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp ("gtk-xft-rgba", name) == 0)
|
||||
{
|
||||
unsigned int orientation = 0;
|
||||
if (SystemParametersInfoW (SPI_GETFONTSMOOTHINGORIENTATION, 0, &orientation, 0))
|
||||
{
|
||||
if (orientation == FE_FONTSMOOTHINGORIENTATIONRGB)
|
||||
g_value_set_static_string (value, "rgb");
|
||||
else if (orientation == FE_FONTSMOOTHINGORIENTATIONBGR)
|
||||
g_value_set_static_string (value, "bgr");
|
||||
else
|
||||
g_value_set_static_string (value, "none");
|
||||
}
|
||||
else
|
||||
g_value_set_static_string (value, "none");
|
||||
|
||||
GDK_NOTE(MISC, g_print ("gdk_screen_get_setting(\"%s\") : %s\n", name, g_value_get_string (value)));
|
||||
return TRUE;
|
||||
}
|
||||
else if (strcmp ("gtk-font-name", name) == 0)
|
||||
{
|
||||
NONCLIENTMETRICS ncm;
|
||||
CPINFOEX cpinfoex_default, cpinfoex_curr_thread;
|
||||
OSVERSIONINFO info;
|
||||
BOOL result_default, result_curr_thread;
|
||||
gchar *font_name = _get_system_font_name (_gdk_display_hdc);
|
||||
|
||||
info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
||||
|
||||
/* TODO: Fallback to using Pango on Windows 8 and later,
|
||||
* as this method of handling gtk-font-name does not work
|
||||
* well there, where garbled text will be displayed for texts
|
||||
* that are not supported by the default menu font. Look for
|
||||
* whether there is a better solution for this on Windows 8 and
|
||||
* later
|
||||
*/
|
||||
if (!GetVersionEx (&info) ||
|
||||
info.dwMajorVersion > 6 ||
|
||||
(info.dwMajorVersion == 6 && info.dwMinorVersion >= 2))
|
||||
return FALSE;
|
||||
|
||||
/* check whether the system default ANSI codepage matches the
|
||||
* ANSI code page of the running thread. If so, continue, otherwise
|
||||
* fall back to using Pango to handle gtk-font-name
|
||||
*/
|
||||
result_default = GetCPInfoEx (CP_ACP, 0, &cpinfoex_default);
|
||||
result_curr_thread = GetCPInfoEx (CP_THREAD_ACP, 0, &cpinfoex_curr_thread);
|
||||
|
||||
if (!result_default ||
|
||||
!result_curr_thread ||
|
||||
cpinfoex_default.CodePage != cpinfoex_curr_thread.CodePage)
|
||||
return FALSE;
|
||||
|
||||
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
||||
if (SystemParametersInfo (SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, FALSE))
|
||||
if (font_name)
|
||||
{
|
||||
/* Pango finally uses GetDeviceCaps to scale, we use simple
|
||||
* approximation here.
|
||||
*/
|
||||
int nHeight = (0 > ncm.lfMenuFont.lfHeight ? - 3 * ncm.lfMenuFont.lfHeight / 4 : 10);
|
||||
if (OUT_STRING_PRECIS == ncm.lfMenuFont.lfOutPrecision)
|
||||
GDK_NOTE(MISC, g_print("gdk_display_get_setting(%s) : ignoring bitmap font '%s'\n",
|
||||
name, ncm.lfMenuFont.lfFaceName));
|
||||
else if (ncm.lfMenuFont.lfFaceName && strlen(ncm.lfMenuFont.lfFaceName) > 0 &&
|
||||
/* Avoid issues like those described in bug #135098 */
|
||||
g_utf8_validate (ncm.lfMenuFont.lfFaceName, -1, NULL))
|
||||
/* The pango font fallback list got fixed during 1.43, before that
|
||||
* using anything but "Segoe UI" would lead to a poor glyph coverage */
|
||||
if (pango_version_check (1, 43, 0) != NULL &&
|
||||
g_ascii_strncasecmp (font_name, "Segoe UI", strlen ("Segoe UI")) != 0)
|
||||
{
|
||||
char *s = g_strdup_printf ("%s %d", ncm.lfMenuFont.lfFaceName, nHeight);
|
||||
GDK_NOTE(MISC, g_print("gdk_display_get_setting(%s) : %s\n", name, s));
|
||||
g_value_set_string (value, s);
|
||||
|
||||
g_free(s);
|
||||
return TRUE;
|
||||
g_free (font_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GDK_NOTE(MISC, g_print("gdk_screen_get_setting(\"%s\") : %s\n", name, font_name));
|
||||
g_value_take_string (value, font_name);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("gdk_screen_get_setting: Detecting the system font failed");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (strcmp ("gtk-im-module", name) == 0)
|
||||
{
|
||||
if (_gdk_input_locale_is_ime)
|
||||
g_value_set_string (value, "ime");
|
||||
else
|
||||
g_value_set_string (value, "");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
@@ -1118,7 +1118,7 @@ show_window_internal (GdkSurface *window,
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
(window->state & GDK_SURFACE_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1376,7 +1376,7 @@ gdk_win32_surface_raise (GdkSurface *window)
|
||||
if (GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP)
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOPMOST,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
|
||||
else if (window->accept_focus)
|
||||
/* Do not wrap this in an API_CALL macro as SetForegroundWindow might
|
||||
* fail when for example dragging a window belonging to a different
|
||||
@@ -1386,7 +1386,7 @@ gdk_win32_surface_raise (GdkSurface *window)
|
||||
else
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,7 +1403,7 @@ gdk_win32_surface_lower (GdkSurface *window)
|
||||
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_BOTTOM,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE));
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOOWNERZORDER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2313,7 +2313,7 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
|
||||
rect.right += after.right - before.right;
|
||||
rect.bottom += after.bottom - before.bottom;
|
||||
|
||||
flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION;
|
||||
flags = SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOREPOSITION | SWP_NOOWNERZORDER;
|
||||
|
||||
if (will_be_topmost && !was_topmost)
|
||||
{
|
||||
@@ -4767,7 +4767,7 @@ gdk_win32_surface_fullscreen (GdkSurface *window)
|
||||
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_TOP,
|
||||
x, y, width, height,
|
||||
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
|
||||
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_NOOWNERZORDER));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4790,7 +4790,7 @@ gdk_win32_surface_unfullscreen (GdkSurface *window)
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), HWND_NOTOPMOST,
|
||||
fi->r.left, fi->r.top,
|
||||
fi->r.right - fi->r.left, fi->r.bottom - fi->r.top,
|
||||
SWP_NOCOPYBITS | SWP_SHOWWINDOW));
|
||||
SWP_NOCOPYBITS | SWP_SHOWWINDOW | SWP_NOOWNERZORDER));
|
||||
|
||||
g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL);
|
||||
g_free (fi);
|
||||
@@ -4816,7 +4816,7 @@ gdk_win32_surface_set_keep_above (GdkSurface *window,
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
setting ? HWND_TOPMOST : HWND_NOTOPMOST,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
|
||||
}
|
||||
|
||||
gdk_synthesize_surface_state (window,
|
||||
@@ -4842,7 +4842,7 @@ gdk_win32_surface_set_keep_below (GdkSurface *window,
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
setting ? HWND_BOTTOM : HWND_NOTOPMOST,
|
||||
0, 0, 0, 0,
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE));
|
||||
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER));
|
||||
}
|
||||
|
||||
gdk_synthesize_surface_state (window,
|
||||
|
||||
@@ -45,6 +45,7 @@ install_headers(gdk_win32_public_headers, subdir: 'gtk-4.0/gdk/win32/')
|
||||
install_headers('gdkwin32.h', subdir: 'gtk-4.0/gdk/')
|
||||
|
||||
gdk_win32_deps = [ # FIXME
|
||||
pangowin32_dep
|
||||
]
|
||||
|
||||
libgdk_win32 = static_library('gdk-win32',
|
||||
|
||||
@@ -261,7 +261,7 @@ gdk_x11_cursor_create_for_name (GdkDisplay *display,
|
||||
/**
|
||||
* gdk_x11_display_set_cursor_theme:
|
||||
* @display: (type GdkX11Display): a #GdkDisplay
|
||||
* @theme: the name of the cursor theme to use, or %NULL to unset
|
||||
* @theme: (nullable): the name of the cursor theme to use, or %NULL to unset
|
||||
* a previously set value
|
||||
* @size: the cursor size to use, or 0 to keep the previous size
|
||||
*
|
||||
|
||||
@@ -40,6 +40,23 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static const char *wacom_type_atoms[] = {
|
||||
"STYLUS",
|
||||
"CURSOR",
|
||||
"ERASER",
|
||||
"PAD",
|
||||
"TOUCH"
|
||||
};
|
||||
#define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms)
|
||||
|
||||
enum {
|
||||
WACOM_TYPE_STYLUS,
|
||||
WACOM_TYPE_CURSOR,
|
||||
WACOM_TYPE_ERASER,
|
||||
WACOM_TYPE_PAD,
|
||||
WACOM_TYPE_TOUCH,
|
||||
};
|
||||
|
||||
struct _GdkX11DeviceManagerXI2
|
||||
{
|
||||
GdkX11DeviceManagerCore parent_object;
|
||||
@@ -999,6 +1016,66 @@ device_get_tool_serial_and_id (GdkDevice *device,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GdkDeviceToolType
|
||||
device_get_tool_type (GdkDevice *device)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
gulong nitems, bytes_after;
|
||||
guint32 *data;
|
||||
int rc, format;
|
||||
Atom type;
|
||||
Atom device_type;
|
||||
Atom types[N_WACOM_TYPE_ATOMS];
|
||||
GdkDeviceToolType tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
|
||||
rc = XIGetProperty (GDK_DISPLAY_XDISPLAY (display),
|
||||
gdk_x11_device_get_id (device),
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "Wacom Tool Type"),
|
||||
0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after,
|
||||
(guchar **) &data);
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
|
||||
if (rc != Success)
|
||||
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
if (type != XA_ATOM || format != 32 || nitems != 1)
|
||||
{
|
||||
XFree (data);
|
||||
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
device_type = *data;
|
||||
XFree (data);
|
||||
|
||||
if (device_type == 0)
|
||||
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
rc = XInternAtoms (GDK_DISPLAY_XDISPLAY (display),
|
||||
(char **) wacom_type_atoms,
|
||||
N_WACOM_TYPE_ATOMS,
|
||||
False,
|
||||
types);
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
|
||||
if (rc == 0)
|
||||
return GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
if (device_type == types[WACOM_TYPE_STYLUS])
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
|
||||
else if (device_type == types[WACOM_TYPE_CURSOR])
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
|
||||
else if (device_type == types[WACOM_TYPE_ERASER])
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
|
||||
else if (device_type == types[WACOM_TYPE_TOUCH])
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
return tool_type;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
|
||||
XIPropertyEvent *ev)
|
||||
@@ -1019,13 +1096,18 @@ handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
|
||||
device_get_tool_serial_and_id (device, &serial_id, &tool_id))
|
||||
{
|
||||
seat = gdk_device_get_seat (device);
|
||||
tool = gdk_seat_get_tool (seat, serial_id);
|
||||
tool = gdk_seat_get_tool (seat, serial_id, tool_id);
|
||||
|
||||
if (!tool && serial_id > 0)
|
||||
{
|
||||
tool = gdk_device_tool_new (serial_id, tool_id,
|
||||
GDK_DEVICE_TOOL_TYPE_UNKNOWN, 0);
|
||||
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
|
||||
GdkDeviceToolType tool_type;
|
||||
|
||||
tool_type = device_get_tool_type (device);
|
||||
if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
|
||||
{
|
||||
tool = gdk_device_tool_new (serial_id, tool_id, tool_type, 0);
|
||||
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1600,7 +1600,7 @@ gdk_x11_display_open (const gchar *display_name)
|
||||
if (!gdk_running_in_sandbox ())
|
||||
{
|
||||
/* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */
|
||||
pid_t pid = getpid ();
|
||||
long pid = getpid ();
|
||||
XChangeProperty (display_x11->xdisplay,
|
||||
display_x11->leader_window,
|
||||
gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
|
||||
@@ -2822,8 +2822,8 @@ gdk_x11_display_error_trap_pop_ignored (GdkDisplay *display)
|
||||
|
||||
/**
|
||||
* gdk_x11_set_sm_client_id:
|
||||
* @sm_client_id: the client id assigned by the session manager when the
|
||||
* connection was opened, or %NULL to remove the property.
|
||||
* @sm_client_id: (nullable): the client id assigned by the session manager
|
||||
* when the connection was opened, or %NULL to remove the property.
|
||||
*
|
||||
* Sets the `SM_CLIENT_ID` property on the application’s leader window so that
|
||||
* the window manager can save the application’s state using the X11R6 ICCCM
|
||||
|
||||
+26
-16
@@ -201,31 +201,41 @@ gdk_x11_gl_context_get_damage (GdkGLContext *context)
|
||||
{
|
||||
GdkGLContext *shared;
|
||||
GdkX11GLContext *shared_x11;
|
||||
|
||||
|
||||
shared = gdk_gl_context_get_shared_context (context);
|
||||
if (shared == NULL)
|
||||
shared = context;
|
||||
shared_x11 = GDK_X11_GL_CONTEXT (shared);
|
||||
|
||||
gdk_gl_context_make_current (shared);
|
||||
glXQueryDrawable(dpy, shared_x11->attached_drawable,
|
||||
GLX_BACK_BUFFER_AGE_EXT, &buffer_age);
|
||||
glXQueryDrawable (dpy, shared_x11->attached_drawable,
|
||||
GLX_BACK_BUFFER_AGE_EXT, &buffer_age);
|
||||
|
||||
if (buffer_age == 2)
|
||||
switch (buffer_age)
|
||||
{
|
||||
if (context->old_updated_area[0])
|
||||
return cairo_region_copy (context->old_updated_area[0]);
|
||||
}
|
||||
else if (buffer_age == 3)
|
||||
{
|
||||
if (context->old_updated_area[0] &&
|
||||
context->old_updated_area[1])
|
||||
{
|
||||
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
|
||||
cairo_region_union (damage, context->old_updated_area[1]);
|
||||
return damage;
|
||||
}
|
||||
case 1:
|
||||
return cairo_region_create ();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (context->old_updated_area[0])
|
||||
return cairo_region_copy (context->old_updated_area[0]);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (context->old_updated_area[0] &&
|
||||
context->old_updated_area[1])
|
||||
{
|
||||
cairo_region_t *damage = cairo_region_copy (context->old_updated_area[0]);
|
||||
cairo_region_union (damage, context->old_updated_area[1]);
|
||||
return damage;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return GDK_GL_CONTEXT_CLASS (gdk_x11_gl_context_parent_class)->get_damage (context);
|
||||
|
||||
@@ -140,7 +140,7 @@ gdk_x11_selection_input_stream_flush (GdkX11SelectionInputStream *stream)
|
||||
written, priv->pending_size));
|
||||
g_task_return_int (priv->pending_task, written);
|
||||
|
||||
priv->pending_task = NULL;
|
||||
g_clear_object (&priv->pending_task);
|
||||
priv->pending_data = NULL;
|
||||
priv->pending_size = 0;
|
||||
}
|
||||
|
||||
@@ -746,7 +746,7 @@ setup_toplevel_window (GdkSurface *surface,
|
||||
if (!gdk_running_in_sandbox ())
|
||||
{
|
||||
/* if sandboxed, we're likely in a pid namespace and would only confuse the wm with this */
|
||||
pid_t pid = getpid ();
|
||||
long pid = getpid ();
|
||||
XChangeProperty (xdisplay, xid,
|
||||
gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
|
||||
XA_CARDINAL, 32,
|
||||
|
||||
+49
-35
@@ -46,6 +46,7 @@ struct _GskGLDriver
|
||||
Fbo default_fbo;
|
||||
|
||||
GHashTable *textures;
|
||||
GHashTable *pointer_textures;
|
||||
|
||||
const Texture *bound_source_texture;
|
||||
const Fbo *bound_fbo;
|
||||
@@ -119,6 +120,7 @@ gsk_gl_driver_finalize (GObject *gobject)
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
g_clear_pointer (&self->textures, g_hash_table_unref);
|
||||
g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
|
||||
g_clear_object (&self->profiler);
|
||||
|
||||
if (self->gl_context == gdk_gl_context_get_current ())
|
||||
@@ -263,7 +265,28 @@ gsk_gl_driver_collect_textures (GskGLDriver *self)
|
||||
}
|
||||
}
|
||||
else
|
||||
g_hash_table_iter_remove (&iter);
|
||||
{
|
||||
/* Remove from self->pointer_textures. */
|
||||
/* TODO: Is there a better way for this? */
|
||||
if (self->pointer_textures)
|
||||
{
|
||||
GHashTableIter pointer_iter;
|
||||
gpointer value;
|
||||
gpointer p;
|
||||
|
||||
g_hash_table_iter_init (&pointer_iter, self->pointer_textures);
|
||||
while (g_hash_table_iter_next (&pointer_iter, &p, &value))
|
||||
{
|
||||
if (GPOINTER_TO_INT (value) == t->texture_id)
|
||||
{
|
||||
g_hash_table_iter_remove (&pointer_iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
return old_size - g_hash_table_size (self->textures);
|
||||
@@ -307,26 +330,6 @@ gsk_gl_driver_get_fbo (GskGLDriver *self,
|
||||
return &t->fbo;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
find_texture_by_size (GHashTable *textures,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value_p = NULL;
|
||||
|
||||
g_hash_table_iter_init (&iter, textures);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value_p))
|
||||
{
|
||||
Texture *t = value_p;
|
||||
|
||||
if (t->width == width && t->height == height)
|
||||
return t;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
create_texture (GskGLDriver *self,
|
||||
float fwidth,
|
||||
@@ -351,21 +354,7 @@ create_texture (GskGLDriver *self,
|
||||
height = MIN (height, self->max_texture_size);
|
||||
}
|
||||
|
||||
t = find_texture_by_size (self->textures, width, height);
|
||||
if (t != NULL && !t->in_use && t->user == NULL)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_message ("Reusing Texture(%d) for size %dx%d",
|
||||
t->texture_id, t->width, t->height));
|
||||
t->in_use = TRUE;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.reused_textures);
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
|
||||
t = texture_new ();
|
||||
t->texture_id = texture_id;
|
||||
t->width = width;
|
||||
@@ -547,6 +536,31 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
|
||||
gpointer pointer)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new (NULL, NULL);
|
||||
|
||||
id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_set_texture_for_pointer (GskGLDriver *self,
|
||||
gpointer pointer,
|
||||
int texture_id)
|
||||
{
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id));
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
|
||||
float width,
|
||||
|
||||
@@ -33,6 +33,11 @@ int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
int gsk_gl_driver_get_texture_for_pointer (GskGLDriver *driver,
|
||||
gpointer pointer);
|
||||
void gsk_gl_driver_set_texture_for_pointer (GskGLDriver *driver,
|
||||
gpointer pointer,
|
||||
int texture_id);
|
||||
int gsk_gl_driver_create_permanent_texture (GskGLDriver *driver,
|
||||
float width,
|
||||
float height);
|
||||
|
||||
+19
-51
@@ -24,21 +24,6 @@
|
||||
|
||||
#define ATLAS_SIZE 512
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
guint scale; /* times 1024 */
|
||||
} GlyphCacheKey;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GlyphCacheKey *key;
|
||||
GskGLCachedGlyph *value;
|
||||
cairo_surface_t *surface;
|
||||
} DirtyGlyph;
|
||||
|
||||
|
||||
static guint glyph_cache_hash (gconstpointer v);
|
||||
static gboolean glyph_cache_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
@@ -58,8 +43,6 @@ create_atlas (GskGLGlyphCache *cache)
|
||||
atlas->y = 1;
|
||||
atlas->x = 1;
|
||||
atlas->image = NULL;
|
||||
atlas->num_glyphs = 0;
|
||||
atlas->dirty_glyphs = NULL;
|
||||
|
||||
return atlas;
|
||||
}
|
||||
@@ -74,7 +57,7 @@ free_atlas (gpointer v)
|
||||
g_assert (atlas->image->texture_id == 0);
|
||||
g_free (atlas->image);
|
||||
}
|
||||
g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
|
||||
|
||||
g_free (atlas);
|
||||
}
|
||||
|
||||
@@ -153,17 +136,15 @@ dirty_glyph_free (gpointer v)
|
||||
|
||||
if (glyph->surface)
|
||||
cairo_surface_destroy (glyph->surface);
|
||||
g_free (glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_cache (GskGLGlyphCache *cache,
|
||||
GlyphCacheKey *key,
|
||||
GlyphCacheKey *key,
|
||||
GskGLCachedGlyph *value)
|
||||
{
|
||||
GskGLGlyphAtlas *atlas;
|
||||
int i;
|
||||
DirtyGlyph *dirty;
|
||||
int width = value->draw_width * key->scale / 1024;
|
||||
int height = value->draw_height * key->scale / 1024;
|
||||
|
||||
@@ -205,16 +186,12 @@ add_to_cache (GskGLGlyphCache *cache,
|
||||
|
||||
value->atlas = atlas;
|
||||
|
||||
dirty = g_new0 (DirtyGlyph, 1);
|
||||
dirty->key = key;
|
||||
dirty->value = value;
|
||||
atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty);
|
||||
atlas->pending_glyph.key = key;
|
||||
atlas->pending_glyph.value = value;
|
||||
|
||||
atlas->x = atlas->x + width + 1;
|
||||
atlas->y = MAX (atlas->y, atlas->y0 + height + 1);
|
||||
|
||||
atlas->num_glyphs++;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
if (GSK_RENDERER_DEBUG_CHECK (cache->renderer, GLYPH_CACHE))
|
||||
{
|
||||
@@ -222,9 +199,8 @@ add_to_cache (GskGLGlyphCache *cache,
|
||||
for (i = 0; i < cache->atlases->len; i++)
|
||||
{
|
||||
atlas = g_ptr_array_index (cache->atlases, i);
|
||||
g_print ("\tGskGLGlyphAtlas %d (%dx%d): %d glyphs (%d dirty), %.2g%% old pixels, filled to %d, %d / %d\n",
|
||||
g_print ("\tGskGLGlyphAtlas %d (%dx%d): %.2g%% old pixels, filled to %d, %d / %d\n",
|
||||
i, atlas->width, atlas->height,
|
||||
atlas->num_glyphs, g_list_length (atlas->dirty_glyphs),
|
||||
100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height),
|
||||
atlas->x, atlas->y0, atlas->y);
|
||||
}
|
||||
@@ -284,28 +260,20 @@ render_glyph (const GskGLGlyphAtlas *atlas,
|
||||
}
|
||||
|
||||
static void
|
||||
upload_dirty_glyphs (GskGLGlyphCache *self,
|
||||
GskGLGlyphAtlas *atlas)
|
||||
upload_dirty_glyph (GskGLGlyphCache *self,
|
||||
GskGLGlyphAtlas *atlas)
|
||||
{
|
||||
GList *l;
|
||||
guint num_regions;
|
||||
GskImageRegion *regions;
|
||||
int i;
|
||||
GskImageRegion region;
|
||||
|
||||
num_regions = g_list_length (atlas->dirty_glyphs);
|
||||
regions = alloca (sizeof (GskImageRegion) * num_regions);
|
||||
g_assert (atlas->pending_glyph.key != NULL);
|
||||
|
||||
for (l = atlas->dirty_glyphs, i = 0; l; l = l->next, i++)
|
||||
render_glyph (atlas, (DirtyGlyph *)l->data, ®ions[i]);
|
||||
render_glyph (atlas, &atlas->pending_glyph, ®ion);
|
||||
|
||||
GSK_RENDERER_NOTE (self->renderer, GLYPH_CACHE,
|
||||
g_message ("uploading %d glyphs to cache", num_regions));
|
||||
gsk_gl_image_upload_regions (atlas->image, self->gl_driver, 1, ®ion);
|
||||
|
||||
|
||||
gsk_gl_image_upload_regions (atlas->image, self->gl_driver, num_regions, regions);
|
||||
|
||||
g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
|
||||
atlas->dirty_glyphs = NULL;
|
||||
dirty_glyph_free (&atlas->pending_glyph);
|
||||
atlas->pending_glyph.key = NULL;
|
||||
atlas->pending_glyph.value = NULL;
|
||||
}
|
||||
|
||||
const GskGLCachedGlyph *
|
||||
@@ -354,12 +322,13 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
|
||||
value->draw_height = ink_rect.height;
|
||||
value->timestamp = cache->timestamp;
|
||||
value->atlas = NULL; /* For now */
|
||||
value->scale = (guint)(scale * 1024);
|
||||
|
||||
key->font = g_object_ref (font);
|
||||
key->glyph = glyph;
|
||||
key->scale = (guint)(scale * 1024);
|
||||
|
||||
if (ink_rect.width > 0 && ink_rect.height > 0)
|
||||
if (ink_rect.width > 0 && ink_rect.height > 0 && key->scale > 0)
|
||||
add_to_cache (cache, key, value);
|
||||
|
||||
g_hash_table_insert (cache->hash_table, key, value);
|
||||
@@ -369,22 +338,21 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
|
||||
}
|
||||
|
||||
GskGLImage *
|
||||
gsk_gl_glyph_cache_get_glyph_image (GskGLGlyphCache *self,
|
||||
gsk_gl_glyph_cache_get_glyph_image (GskGLGlyphCache *self,
|
||||
const GskGLCachedGlyph *glyph)
|
||||
{
|
||||
GskGLGlyphAtlas *atlas = glyph->atlas;
|
||||
|
||||
g_assert (atlas != NULL);
|
||||
|
||||
|
||||
if (atlas->image == NULL)
|
||||
{
|
||||
atlas->image = g_new0 (GskGLImage, 1);
|
||||
gsk_gl_image_create (atlas->image, self->gl_driver, atlas->width, atlas->height);
|
||||
}
|
||||
|
||||
if (atlas->dirty_glyphs)
|
||||
upload_dirty_glyphs (self, atlas);
|
||||
if (atlas->pending_glyph.key != NULL)
|
||||
upload_dirty_glyph (self, atlas);
|
||||
|
||||
return atlas->image;
|
||||
}
|
||||
|
||||
@@ -18,18 +18,34 @@ typedef struct
|
||||
guint64 timestamp;
|
||||
} GskGLGlyphCache;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
guint scale; /* times 1024 */
|
||||
} GlyphCacheKey;
|
||||
|
||||
typedef struct _DirtyGlyph DirtyGlyph;
|
||||
typedef struct _GskGLCachedGlyph GskGLCachedGlyph;
|
||||
|
||||
struct _DirtyGlyph
|
||||
{
|
||||
GlyphCacheKey *key;
|
||||
GskGLCachedGlyph *value;
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GskGLImage *image;
|
||||
int width, height;
|
||||
int x, y, y0;
|
||||
int num_glyphs;
|
||||
GList *dirty_glyphs;
|
||||
guint old_pixels;
|
||||
|
||||
DirtyGlyph pending_glyph;
|
||||
} GskGLGlyphAtlas;
|
||||
|
||||
typedef struct
|
||||
struct _GskGLCachedGlyph
|
||||
{
|
||||
GskGLGlyphAtlas *atlas;
|
||||
|
||||
@@ -43,8 +59,11 @@ typedef struct
|
||||
int draw_width;
|
||||
int draw_height;
|
||||
|
||||
float scale;
|
||||
|
||||
guint64 timestamp;
|
||||
} GskGLCachedGlyph;
|
||||
};
|
||||
|
||||
|
||||
void gsk_gl_glyph_cache_init (GskGLGlyphCache *self,
|
||||
GskRenderer *renderer,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#include <glib/gprintf.h>
|
||||
#include "gskglnodesampleprivate.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
|
||||
void
|
||||
node_sample_init (NodeSample *self)
|
||||
{
|
||||
memset (self->nodes, 0, sizeof (self->nodes));
|
||||
self->count = 0;
|
||||
}
|
||||
|
||||
void
|
||||
node_sample_reset (NodeSample *self)
|
||||
{
|
||||
node_sample_init (self);
|
||||
}
|
||||
|
||||
void
|
||||
node_sample_add (NodeSample *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
const guint node_type = gsk_render_node_get_node_type (node);
|
||||
|
||||
g_assert (node_type <= N_NODE_TYPES);
|
||||
|
||||
if (self->nodes[node_type].class_name == NULL)
|
||||
self->nodes[node_type].class_name = node->node_class->type_name;
|
||||
|
||||
self->nodes[node_type].count ++;
|
||||
self->count ++;
|
||||
}
|
||||
|
||||
void
|
||||
node_sample_print (const NodeSample *self,
|
||||
const char *prefix)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_printf ("%s:\n", prefix);
|
||||
|
||||
for (i = 0; i < N_NODE_TYPES; i ++)
|
||||
{
|
||||
if (self->nodes[i].count > 0)
|
||||
{
|
||||
double p = (double)self->nodes[i].count / (double)self->count;
|
||||
|
||||
g_printf ("%s: %u (%.2f%%)\n", self->nodes[i].class_name, self->nodes[i].count, p * 100.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
#ifndef __GSK_GL_NODE_SAMPLE_PRIVATE_H__
|
||||
#define __GSK_GL_NODE_SAMPLE_PRIVATE_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include "gskenums.h"
|
||||
#include "gskrendernode.h"
|
||||
|
||||
/* TODO: We have no other way for this...? */
|
||||
#define N_NODE_TYPES (GSK_DEBUG_NODE + 1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct {
|
||||
const char *class_name;
|
||||
guint count;
|
||||
} nodes[N_NODE_TYPES];
|
||||
guint count;
|
||||
} NodeSample;
|
||||
|
||||
void node_sample_init (NodeSample *self);
|
||||
void node_sample_reset (NodeSample *self);
|
||||
void node_sample_add (NodeSample *self,
|
||||
GskRenderNode *node);
|
||||
void node_sample_print (const NodeSample *self,
|
||||
const char *prefix);
|
||||
|
||||
#endif
|
||||
+379
-163
@@ -14,6 +14,7 @@
|
||||
#include "gskglrenderopsprivate.h"
|
||||
#include "gskcairoblurprivate.h"
|
||||
#include "gskglshadowcacheprivate.h"
|
||||
#include "gskglnodesampleprivate.h"
|
||||
|
||||
#include "gskprivate.h"
|
||||
|
||||
@@ -104,8 +105,19 @@ print_render_node_tree (GskRenderNode *root, int level)
|
||||
g_print ("%*s Texture %p\n", level * INDENT, " ", gsk_texture_node_get_texture (root));
|
||||
break;
|
||||
|
||||
case GSK_DEBUG_NODE:
|
||||
g_print ("%*s Debug: %s\n", level * INDENT, " ", gsk_debug_node_get_message (root));
|
||||
print_render_node_tree (gsk_debug_node_get_child (root), level + 1);
|
||||
break;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
g_print ("%*s Clip (%f, %f, %f, %f):\n", level * INDENT, " ",
|
||||
root->bounds.origin.x, root->bounds.origin.y, root->bounds.size.width, root->bounds.size.height);
|
||||
print_render_node_tree (gsk_clip_node_get_child (root), level + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print ("UNKNOWN: %u\n", type);
|
||||
g_print ("%*s %s\n", level * INDENT, " ", root->node_class->type_name);
|
||||
}
|
||||
|
||||
#undef INDENT
|
||||
@@ -219,18 +231,40 @@ gsk_rounded_rect_shrink_to_minimum (GskRoundedRect *self)
|
||||
MAX (self->corner[2].height, self->corner[3].height)) * 2);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
node_supports_transform (GskRenderNode *node)
|
||||
{
|
||||
/* Some nodes can't handle non-trivial transforms without being
|
||||
* rendered to a texture (e.g. rotated clips, etc.). Some however
|
||||
* work just fine, mostly because they already draw their child
|
||||
* to a texture and just render the texture manipulated in some
|
||||
* way, think opacity or color matrix. */
|
||||
const guint node_type = gsk_render_node_get_node_type (node);
|
||||
|
||||
switch (node_type)
|
||||
{
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_OPACITY_NODE:
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
case GSK_TEXTURE_NODE:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void gsk_gl_renderer_setup_render_mode (GskGLRenderer *self);
|
||||
static void add_offscreen_ops (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
float min_x,
|
||||
float max_x,
|
||||
float min_y,
|
||||
float max_y,
|
||||
GskRenderNode *child_node,
|
||||
int *texture_id,
|
||||
gboolean *is_offscreen,
|
||||
gboolean force_offscreen,
|
||||
gboolean reset_clip);
|
||||
RenderOpBuilder *builder,
|
||||
const graphene_rect_t *bounds,
|
||||
GskRenderNode *child_node,
|
||||
int *texture_id,
|
||||
gboolean *is_offscreen,
|
||||
gboolean force_offscreen,
|
||||
gboolean reset_clip);
|
||||
static void gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder);
|
||||
@@ -248,7 +282,6 @@ struct _GskGLRenderer
|
||||
union {
|
||||
Program programs[GL_N_PROGRAMS];
|
||||
struct {
|
||||
Program blend_program;
|
||||
Program blit_program;
|
||||
Program color_program;
|
||||
Program coloring_program;
|
||||
@@ -289,6 +322,49 @@ struct _GskGLRendererClass
|
||||
|
||||
G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
|
||||
|
||||
static void G_GNUC_UNUSED
|
||||
add_rect_ops (RenderOpBuilder *builder,
|
||||
const graphene_rect_t *r)
|
||||
{
|
||||
const float min_x = r->origin.x;
|
||||
const float min_y = r->origin.y;
|
||||
const float max_x = min_x + r->size.width;
|
||||
const float max_y = min_y + r->size.height;
|
||||
|
||||
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
});
|
||||
}
|
||||
|
||||
static void G_GNUC_UNUSED
|
||||
add_rect_outline_ops (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const graphene_rect_t *rect)
|
||||
{
|
||||
ops_set_program (builder, &self->color_program);
|
||||
ops_set_color (builder, &(GdkRGBA) { 1, 0, 0, 1 });
|
||||
|
||||
add_rect_ops (builder,
|
||||
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y,
|
||||
1, rect->size.height));
|
||||
add_rect_ops (builder,
|
||||
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y,
|
||||
rect->size.width, 1));
|
||||
add_rect_ops (builder,
|
||||
&GRAPHENE_RECT_INIT (rect->origin.x + rect->size.width - 1, rect->origin.y,
|
||||
1, rect->size.height));
|
||||
|
||||
add_rect_ops (builder,
|
||||
&GRAPHENE_RECT_INIT (rect->origin.x, rect->origin.y + rect->size.height - 1,
|
||||
rect->size.width, 1));
|
||||
}
|
||||
|
||||
static inline void
|
||||
rounded_rect_to_floats (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
@@ -301,7 +377,7 @@ rounded_rect_to_floats (GskGLRenderer *self,
|
||||
int i;
|
||||
graphene_rect_t transformed_bounds;
|
||||
|
||||
graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_bounds);
|
||||
ops_transform_bounds_modelview (builder, &rect->bounds, &transformed_bounds);
|
||||
|
||||
outline[0] = transformed_bounds.origin.x;
|
||||
outline[1] = transformed_bounds.origin.y;
|
||||
@@ -420,7 +496,7 @@ render_text_node (GskGLRenderer *self,
|
||||
text_scale);
|
||||
|
||||
/* e.g. whitespace */
|
||||
if (glyph->draw_width <= 0 || glyph->draw_height <= 0)
|
||||
if (glyph->draw_width <= 0 || glyph->draw_height <= 0 || glyph->scale <= 0)
|
||||
goto next;
|
||||
|
||||
cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
@@ -460,8 +536,8 @@ render_border_node (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const float min_x = node->bounds.origin.x;
|
||||
const float min_y = node->bounds.origin.y;
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
const GdkRGBA *colors = gsk_border_node_peek_colors (node);
|
||||
@@ -578,8 +654,8 @@ render_border_node (GskGLRenderer *self,
|
||||
|
||||
/* Prepare outline */
|
||||
outline = *rounded_outline;
|
||||
graphene_matrix_transform_bounds (&builder->current_modelview,
|
||||
&outline.bounds, &outline.bounds);
|
||||
ops_transform_bounds_modelview (builder, &outline.bounds, &outline.bounds);
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
outline.corner[i].width *= scale;
|
||||
@@ -587,7 +663,8 @@ render_border_node (GskGLRenderer *self,
|
||||
}
|
||||
|
||||
ops_set_program (builder, &self->border_program);
|
||||
ops_set_border (builder, widths, &outline);
|
||||
ops_set_border_width (builder, widths);
|
||||
ops_set_border (builder, &outline);
|
||||
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
@@ -689,41 +766,12 @@ render_offset_node (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
GskRenderNode *child = gsk_offset_node_get_child (node);
|
||||
const guint child_type = gsk_render_node_get_node_type (child);
|
||||
const float dx = gsk_offset_node_get_x_offset (node);
|
||||
const float dy = gsk_offset_node_get_y_offset (node);
|
||||
|
||||
/* TODO: We do this only for selected node type we know handle
|
||||
* builder->dx/dy correctly. That should be "all nodes" eventually.
|
||||
*/
|
||||
switch (child_type)
|
||||
{
|
||||
case GSK_TEXT_NODE:
|
||||
case GSK_TEXTURE_NODE:
|
||||
case GSK_COLOR_NODE:
|
||||
case GSK_COLOR_MATRIX_NODE:
|
||||
{
|
||||
ops_offset (builder, dx, dy);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
ops_offset (builder, - dx, - dy);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
graphene_matrix_t prev_mv;
|
||||
graphene_matrix_t transform, transformed_mv;
|
||||
|
||||
graphene_matrix_init_translate (&transform,
|
||||
&GRAPHENE_POINT3D_INIT(dx, dy, 1.0));
|
||||
graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
|
||||
prev_mv = ops_set_modelview (builder, &transformed_mv);
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
|
||||
ops_set_modelview (builder, &prev_mv);
|
||||
}
|
||||
}
|
||||
ops_offset (builder, dx, dy);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
ops_offset (builder, - dx, - dy);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -731,17 +779,64 @@ render_transform_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
GskRenderNode *child = gsk_transform_node_get_child (node);
|
||||
graphene_matrix_t prev_mv;
|
||||
graphene_matrix_t transform, transformed_mv;
|
||||
|
||||
graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
|
||||
graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
|
||||
prev_mv = ops_set_modelview (builder, &transformed_mv);
|
||||
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
|
||||
graphene_matrix_translate (&transformed_mv,
|
||||
&(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
/* We just added the offset to the new modelview matrix, so the following
|
||||
* cases dont' have to care about builder->dx/dy! */
|
||||
|
||||
ops_set_modelview (builder, &prev_mv);
|
||||
ops_push_modelview (builder, &transformed_mv);
|
||||
if (ops_modelview_is_simple (builder) ||
|
||||
node_supports_transform (child))
|
||||
{
|
||||
const float dx = builder->dx;
|
||||
const float dy = builder->dy;
|
||||
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
builder->dx = dx;
|
||||
builder->dy = dy;
|
||||
}
|
||||
else
|
||||
{
|
||||
const float min_x = node->bounds.origin.x;
|
||||
const float min_y = node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
|
||||
{ { min_x, min_y }, { 0, 1 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
|
||||
{ { max_x, max_y }, { 1, 0 }, },
|
||||
{ { min_x, max_y }, { 0, 0 }, },
|
||||
{ { max_x, min_y }, { 1, 1 }, },
|
||||
};
|
||||
int texture_id;
|
||||
gboolean is_offscreen;
|
||||
/* For non-trivial transforms, we draw everything on a texture and then
|
||||
* draw the texture transformed. */
|
||||
/* TODO: We should compute a modelview containing only the "non-trivial"
|
||||
* part (e.g. the rotation) and use that. We want to keep the scale
|
||||
* for the texture.
|
||||
*/
|
||||
add_offscreen_ops (self, builder,
|
||||
&node->bounds,
|
||||
child,
|
||||
&texture_id, &is_offscreen,
|
||||
FALSE, TRUE);
|
||||
ops_set_texture (builder, texture_id);
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_draw (builder, vertex_data);
|
||||
}
|
||||
ops_pop_modelview (builder);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -787,7 +882,11 @@ render_linear_gradient_node (GskGLRenderer *self,
|
||||
op.op = OP_CHANGE_LINEAR_GRADIENT;
|
||||
op.linear_gradient.n_color_stops = n_color_stops;
|
||||
op.linear_gradient.start_point = *start;
|
||||
op.linear_gradient.start_point.x += builder->dx;
|
||||
op.linear_gradient.start_point.y += builder->dy;
|
||||
op.linear_gradient.end_point = *end;
|
||||
op.linear_gradient.end_point.x += builder->dx;
|
||||
op.linear_gradient.end_point.y += builder->dy;
|
||||
ops_add (builder, &op);
|
||||
|
||||
ops_draw (builder, vertex_data);
|
||||
@@ -798,64 +897,98 @@ render_clip_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
GskRoundedRect prev_clip;
|
||||
GskRenderNode *child = gsk_clip_node_get_child (node);
|
||||
graphene_rect_t transformed_clip;
|
||||
graphene_rect_t intersection;
|
||||
GskRoundedRect child_clip;
|
||||
|
||||
transformed_clip = *gsk_clip_node_peek_clip (node);
|
||||
graphene_matrix_transform_bounds (&builder->current_modelview, &transformed_clip, &transformed_clip);
|
||||
ops_transform_bounds_modelview (builder, &transformed_clip, &transformed_clip);
|
||||
|
||||
graphene_rect_intersection (&transformed_clip,
|
||||
&builder->current_clip.bounds,
|
||||
&builder->current_clip->bounds,
|
||||
&intersection);
|
||||
|
||||
gsk_rounded_rect_init_from_rect (&child_clip, &intersection, 0.0f);
|
||||
|
||||
prev_clip = ops_set_clip (builder, &child_clip);
|
||||
ops_push_clip (builder, &child_clip);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
ops_set_clip (builder, &prev_clip);
|
||||
ops_pop_clip (builder);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gsk_rounded_rect_intersection (const GskRoundedRect *self,
|
||||
const GskRoundedRect *other,
|
||||
GskRoundedRect *out_intersection)
|
||||
{
|
||||
const graphene_rect_t *self_bounds = &self->bounds;
|
||||
const graphene_rect_t *other_bounds = &other->bounds;
|
||||
|
||||
if (graphene_rect_contains_rect (self_bounds, other_bounds))
|
||||
{
|
||||
*out_intersection = *other;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* TODO: There are a few cases here that we can express using a single
|
||||
* rounded rectangle, which are even interesting in every day usage.
|
||||
* For example, a partially scrolled-away rounded rectangle
|
||||
* might just work.
|
||||
*/
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline void
|
||||
render_rounded_clip_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const float min_x = node->bounds.origin.x;
|
||||
const float min_y = node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
GskRoundedRect child_clip = *gsk_rounded_clip_node_peek_clip (node);
|
||||
GskRoundedRect transformed_clip;
|
||||
GskRoundedRect prev_clip;
|
||||
GskRenderNode *child = gsk_rounded_clip_node_get_child (node);
|
||||
GskRoundedRect intersection;
|
||||
gboolean need_offscreen;
|
||||
int i;
|
||||
|
||||
transformed_clip = child_clip;
|
||||
graphene_matrix_transform_bounds (&builder->current_modelview, &child_clip.bounds, &transformed_clip.bounds);
|
||||
ops_transform_bounds_modelview (builder, &child_clip.bounds, &transformed_clip.bounds);
|
||||
|
||||
if (graphene_rect_contains_rect (&builder->current_clip.bounds,
|
||||
&transformed_clip.bounds))
|
||||
if (!ops_has_clip (builder))
|
||||
{
|
||||
intersection = transformed_clip;
|
||||
need_offscreen = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
need_offscreen = !gsk_rounded_rect_intersection (builder->current_clip,
|
||||
&transformed_clip,
|
||||
&intersection);
|
||||
}
|
||||
|
||||
if (!need_offscreen)
|
||||
{
|
||||
/* If they don't intersect at all, we can simply set
|
||||
* the new clip and add the render ops */
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
transformed_clip.corner[i].width *= scale;
|
||||
transformed_clip.corner[i].height *= scale;
|
||||
intersection.corner[i].width *= scale;
|
||||
intersection.corner[i].height *= scale;
|
||||
}
|
||||
|
||||
prev_clip = ops_set_clip (builder, &transformed_clip);
|
||||
ops_push_clip (builder, &intersection);
|
||||
gsk_gl_renderer_add_render_ops (self, child, builder);
|
||||
|
||||
ops_set_clip (builder, &prev_clip);
|
||||
ops_pop_clip (builder);
|
||||
}
|
||||
else if (graphene_rect_intersection (&builder->current_clip.bounds,
|
||||
&transformed_clip.bounds, NULL))
|
||||
else
|
||||
{
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
graphene_matrix_t scale_matrix;
|
||||
gboolean is_offscreen;
|
||||
int texture_id;
|
||||
@@ -876,12 +1009,12 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
child_clip.corner[i].height *= scale;
|
||||
}
|
||||
|
||||
prev_clip = ops_set_clip (builder, &child_clip);
|
||||
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
|
||||
ops_push_clip (builder, &child_clip);
|
||||
add_offscreen_ops (self, builder, &node->bounds,
|
||||
child,
|
||||
&texture_id, &is_offscreen, TRUE, FALSE);
|
||||
ops_pop_clip (builder);
|
||||
|
||||
ops_set_clip (builder, &prev_clip);
|
||||
ops_set_program (builder, &self->blit_program);
|
||||
ops_set_texture (builder, texture_id);
|
||||
|
||||
@@ -911,7 +1044,9 @@ render_color_matrix_node (GskGLRenderer *self,
|
||||
int texture_id;
|
||||
gboolean is_offscreen;
|
||||
|
||||
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
|
||||
/* Pass min_x/max_x/min_y/max_y without builder->dx/dy! */
|
||||
add_offscreen_ops (self, builder,
|
||||
&node->bounds,
|
||||
gsk_color_matrix_node_get_child (node),
|
||||
&texture_id, &is_offscreen, FALSE, TRUE);
|
||||
|
||||
@@ -948,16 +1083,23 @@ render_blur_node (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const GskQuadVertex *vertex_data)
|
||||
{
|
||||
const float min_x = node->bounds.origin.x;
|
||||
const float min_y = node->bounds.origin.y;
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
int texture_id;
|
||||
gboolean is_offscreen;
|
||||
RenderOp op;
|
||||
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
|
||||
|
||||
/* TODO(perf): We're forcing the child offscreen even if it's a texture
|
||||
* so the resulting offscreen texture is bigger by the gaussian blur factor
|
||||
* (see gsk_blur_node_new), but we didn't have to do that if the blur
|
||||
* shader could handle that situation. */
|
||||
|
||||
add_offscreen_ops (self, builder,
|
||||
&node->bounds,
|
||||
gsk_blur_node_get_child (node),
|
||||
&texture_id, &is_offscreen, FALSE, TRUE);
|
||||
&texture_id, &is_offscreen, TRUE, TRUE);
|
||||
|
||||
ops_set_program (builder, &self->blur_program);
|
||||
op.op = OP_CHANGE_BLUR;
|
||||
@@ -1063,15 +1205,14 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
const float spread = gsk_outset_shadow_node_get_spread (node);
|
||||
const float dx = gsk_outset_shadow_node_get_dx (node);
|
||||
const float dy = gsk_outset_shadow_node_get_dy (node);
|
||||
const float min_x = outline->bounds.origin.x - spread - blur_extra / 2.0;
|
||||
const float min_y = outline->bounds.origin.y - spread - blur_extra / 2.0;
|
||||
const float min_x = builder->dx + outline->bounds.origin.x - spread - blur_extra / 2.0;
|
||||
const float min_y = builder->dy + outline->bounds.origin.y - spread - blur_extra / 2.0;
|
||||
const float max_x = min_x + outline->bounds.size.width + (spread + blur_extra/2.0) * 2;
|
||||
const float max_y = min_y + outline->bounds.size.height + (spread + blur_extra/2.0) * 2;
|
||||
float texture_width, texture_height;
|
||||
RenderOp op;
|
||||
graphene_matrix_t identity;
|
||||
graphene_matrix_t prev_projection;
|
||||
graphene_matrix_t prev_modelview;
|
||||
graphene_rect_t prev_viewport;
|
||||
graphene_matrix_t item_proj;
|
||||
int blurred_texture_id;
|
||||
@@ -1106,7 +1247,7 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
int texture_id, render_target;
|
||||
int blurred_render_target;
|
||||
int prev_render_target;
|
||||
GskRoundedRect prev_clip, blit_clip;
|
||||
GskRoundedRect blit_clip;
|
||||
|
||||
texture_id = gsk_gl_driver_create_texture (self->gl_driver, texture_width, texture_height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
|
||||
@@ -1124,12 +1265,12 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
op.op = OP_CLEAR;
|
||||
ops_add (builder, &op);
|
||||
prev_projection = ops_set_projection (builder, &item_proj);
|
||||
prev_modelview = ops_set_modelview (builder, &identity);
|
||||
ops_push_modelview (builder, &identity);
|
||||
prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
|
||||
|
||||
/* Draw outline */
|
||||
ops_set_program (builder, &self->color_program);
|
||||
prev_clip = ops_set_clip (builder, &offset_outline);
|
||||
ops_push_clip (builder, &offset_outline);
|
||||
ops_set_color (builder, gsk_outset_shadow_node_peek_color (node));
|
||||
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
|
||||
{ { 0, }, { 0, 1 }, },
|
||||
@@ -1147,6 +1288,7 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
blurred_render_target = gsk_gl_driver_create_render_target (self->gl_driver, blurred_texture_id, TRUE, TRUE);
|
||||
|
||||
ops_set_render_target (builder, blurred_render_target);
|
||||
ops_pop_clip (builder);
|
||||
op.op = OP_CLEAR;
|
||||
ops_add (builder, &op);
|
||||
|
||||
@@ -1160,7 +1302,7 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
op.blur.radius = blur_radius;
|
||||
ops_add (builder, &op);
|
||||
|
||||
ops_set_clip (builder, &blit_clip);
|
||||
ops_push_clip (builder, &blit_clip);
|
||||
ops_set_texture (builder, texture_id);
|
||||
ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
|
||||
{ { 0, 0 }, { 0, 1 }, },
|
||||
@@ -1173,9 +1315,9 @@ render_outset_shadow_node (GskGLRenderer *self,
|
||||
});
|
||||
|
||||
|
||||
ops_set_clip (builder, &prev_clip);
|
||||
ops_pop_clip (builder);
|
||||
ops_set_viewport (builder, &prev_viewport);
|
||||
ops_set_modelview (builder, &prev_modelview);
|
||||
ops_pop_modelview (builder);
|
||||
ops_set_projection (builder, &prev_projection);
|
||||
ops_set_render_target (builder, prev_render_target);
|
||||
|
||||
@@ -1459,11 +1601,6 @@ render_shadow_node (GskGLRenderer *self,
|
||||
|
||||
g_assert (shadow->radius <= 0);
|
||||
|
||||
min_x = shadow_child->bounds.origin.x;
|
||||
min_y = shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
if (gsk_render_node_get_node_type (shadow_child) == GSK_TEXT_NODE)
|
||||
{
|
||||
ops_offset (builder, dx, dy);
|
||||
@@ -1472,9 +1609,14 @@ render_shadow_node (GskGLRenderer *self,
|
||||
continue;
|
||||
}
|
||||
|
||||
min_x = builder->dx + shadow_child->bounds.origin.x;
|
||||
min_y = builder->dy + shadow_child->bounds.origin.y;
|
||||
max_x = min_x + shadow_child->bounds.size.width;
|
||||
max_y = min_y + shadow_child->bounds.size.height;
|
||||
|
||||
/* Draw the child offscreen, without the offset. */
|
||||
add_offscreen_ops (self, builder,
|
||||
min_x, max_x, min_y, max_y,
|
||||
&shadow_child->bounds,
|
||||
shadow_child, &texture_id, &is_offscreen, FALSE, TRUE);
|
||||
|
||||
ops_offset (builder, dx, dy);
|
||||
@@ -1522,8 +1664,8 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
GskRenderNode *node,
|
||||
RenderOpBuilder *builder)
|
||||
{
|
||||
const float min_x = node->bounds.origin.x;
|
||||
const float min_y = node->bounds.origin.y;
|
||||
const float min_x = builder->dx + node->bounds.origin.x;
|
||||
const float min_y = builder->dy + node->bounds.origin.y;
|
||||
const float max_x = min_x + node->bounds.size.width;
|
||||
const float max_y = min_y + node->bounds.size.height;
|
||||
GskRenderNode *start_node = gsk_cross_fade_node_get_start_child (node);
|
||||
@@ -1546,10 +1688,14 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
/* TODO: We create 2 textures here as big as the cross-fade node, but both the
|
||||
* start and the end node might be a lot smaller than that. */
|
||||
|
||||
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, start_node,
|
||||
add_offscreen_ops (self, builder,
|
||||
&node->bounds,
|
||||
start_node,
|
||||
&start_texture_id, &is_offscreen1, TRUE, TRUE);
|
||||
|
||||
add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y, end_node,
|
||||
add_offscreen_ops (self, builder,
|
||||
&node->bounds,
|
||||
end_node,
|
||||
&end_texture_id, &is_offscreen2, TRUE, TRUE);
|
||||
|
||||
ops_set_program (builder, &self->cross_fade_program);
|
||||
@@ -1777,8 +1923,7 @@ apply_border_op (const Program *program,
|
||||
float widths[4];
|
||||
float heights[4];
|
||||
int i;
|
||||
OP_PRINT (" -> Border (%f, %f, %f, %f)",
|
||||
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
|
||||
OP_PRINT (" -> Border Outline");
|
||||
|
||||
outline[0] = o->bounds.origin.x;
|
||||
outline[1] = o->bounds.origin.y;
|
||||
@@ -1791,12 +1936,21 @@ apply_border_op (const Program *program,
|
||||
heights[i] = o->corner[i].height;
|
||||
}
|
||||
|
||||
glUniform4fv (program->border.widths_location, 1, op->border.widths);
|
||||
glUniform4fv (program->border.outline_location, 1, outline);
|
||||
glUniform4fv (program->border.corner_widths_location, 1, widths);
|
||||
glUniform4fv (program->border.corner_heights_location, 1, heights);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_border_width_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
{
|
||||
OP_PRINT (" -> Border width (%f, %f, %f, %f)",
|
||||
op->border.widths[0], op->border.widths[1], op->border.widths[2], op->border.widths[3]);
|
||||
|
||||
glUniform4fv (program->border.widths_location, 1, op->border.widths);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_border_color_op (const Program *program,
|
||||
const RenderOp *op)
|
||||
@@ -1847,21 +2001,19 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
int i;
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *vs;
|
||||
const char *fs;
|
||||
} program_definitions[] = {
|
||||
{ "blend", "blend.vs.glsl", "blend.fs.glsl" },
|
||||
{ "blit", "blit.vs.glsl", "blit.fs.glsl" },
|
||||
{ "color", "blit.vs.glsl", "color.fs.glsl" },
|
||||
{ "coloring", "blit.vs.glsl", "coloring.fs.glsl" },
|
||||
{ "color matrix", "blit.vs.glsl", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "blit.vs.glsl", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blit.vs.glsl", "blur.fs.glsl" },
|
||||
{ "inset shadow", "blit.vs.glsl", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "blit.vs.glsl", "outset_shadow.fs.glsl" },
|
||||
{ "unblurred outset shadow", "blit.vs.glsl", "unblurred_outset_shadow.fs.glsl" },
|
||||
{ "border", "blit.vs.glsl", "border.fs.glsl" },
|
||||
{ "cross fade", "blit.vs.glsl", "cross_fade.fs.glsl" },
|
||||
{ "blit", "blit.fs.glsl" },
|
||||
{ "color", "color.fs.glsl" },
|
||||
{ "coloring", "coloring.fs.glsl" },
|
||||
{ "color matrix", "color_matrix.fs.glsl" },
|
||||
{ "linear gradient", "linear_gradient.fs.glsl" },
|
||||
{ "blur", "blur.fs.glsl" },
|
||||
{ "inset shadow", "inset_shadow.fs.glsl" },
|
||||
{ "outset shadow", "outset_shadow.fs.glsl" },
|
||||
{ "unblurred outset shadow", "unblurred_outset_shadow.fs.glsl" },
|
||||
{ "border", "border.fs.glsl" },
|
||||
{ "cross fade", "cross_fade.fs.glsl" },
|
||||
};
|
||||
|
||||
builder = gsk_shader_builder_new ();
|
||||
@@ -1902,13 +2054,17 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
gsk_shader_builder_add_define (builder, "GSK_DEBUG", "1");
|
||||
#endif
|
||||
|
||||
gsk_shader_builder_set_common_vertex_shader (builder, "blit.vs.glsl",
|
||||
&shader_error);
|
||||
|
||||
g_assert_no_error (shader_error);
|
||||
|
||||
for (i = 0; i < GL_N_PROGRAMS; i ++)
|
||||
{
|
||||
Program *prog = &self->programs[i];
|
||||
|
||||
prog->index = i;
|
||||
prog->id = gsk_shader_builder_create_program (builder,
|
||||
program_definitions[i].vs,
|
||||
program_definitions[i].fs,
|
||||
&shader_error);
|
||||
|
||||
@@ -1917,7 +2073,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
g_propagate_prefixed_error (error, shader_error,
|
||||
"Unable to create '%s' program (from %s and %s):\n",
|
||||
program_definitions[i].name,
|
||||
program_definitions[i].vs,
|
||||
"blit.vs.glsl",
|
||||
program_definitions[i].fs);
|
||||
|
||||
g_object_unref (builder);
|
||||
@@ -2140,12 +2296,11 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
{
|
||||
graphene_rect_t transformed_node_bounds;
|
||||
|
||||
graphene_matrix_transform_bounds (&builder->current_modelview,
|
||||
&node->bounds,
|
||||
&transformed_node_bounds);
|
||||
graphene_rect_offset (&transformed_node_bounds, builder->dx, builder->dy);
|
||||
ops_transform_bounds_modelview (builder,
|
||||
&node->bounds,
|
||||
&transformed_node_bounds);
|
||||
|
||||
if (!graphene_rect_intersection (&builder->current_clip.bounds,
|
||||
if (!graphene_rect_intersection (&builder->current_clip->bounds,
|
||||
&transformed_node_bounds, NULL))
|
||||
return;
|
||||
}
|
||||
@@ -2254,30 +2409,29 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
}
|
||||
|
||||
static void
|
||||
add_offscreen_ops (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
float min_x,
|
||||
float max_x,
|
||||
float min_y,
|
||||
float max_y,
|
||||
GskRenderNode *child_node,
|
||||
int *texture_id,
|
||||
gboolean *is_offscreen,
|
||||
gboolean force_offscreen,
|
||||
gboolean reset_clip)
|
||||
add_offscreen_ops (GskGLRenderer *self,
|
||||
RenderOpBuilder *builder,
|
||||
const graphene_rect_t *bounds,
|
||||
GskRenderNode *child_node,
|
||||
int *texture_id_out,
|
||||
gboolean *is_offscreen,
|
||||
gboolean force_offscreen,
|
||||
gboolean reset_clip)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const float width = (max_x - min_x) * scale;
|
||||
const float height = (max_y - min_y) * scale;
|
||||
const float width = bounds->size.width * scale;
|
||||
const float height = bounds->size.height * scale;
|
||||
const float dx = builder->dx;
|
||||
const float dy = builder->dy;
|
||||
int render_target;
|
||||
int prev_render_target;
|
||||
RenderOp op;
|
||||
graphene_matrix_t identity;
|
||||
graphene_matrix_t prev_projection;
|
||||
graphene_matrix_t prev_modelview;
|
||||
graphene_rect_t prev_viewport;
|
||||
graphene_matrix_t item_proj;
|
||||
GskRoundedRect prev_clip;
|
||||
float prev_opacity;
|
||||
int texture_id = 0;
|
||||
|
||||
/* We need the child node as a texture. If it already is one, we don't need to draw
|
||||
* it on a framebuffer of course. */
|
||||
@@ -2288,22 +2442,37 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
|
||||
get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
|
||||
|
||||
*texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||
texture,
|
||||
gl_min_filter,
|
||||
gl_mag_filter);
|
||||
*texture_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||
texture,
|
||||
gl_min_filter,
|
||||
gl_mag_filter);
|
||||
*is_offscreen = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
*texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
|
||||
render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
|
||||
/* Check if we've already cached the drawn texture. */
|
||||
{
|
||||
const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
|
||||
|
||||
if (cached_id != 0)
|
||||
{
|
||||
*texture_id_out = cached_id;
|
||||
/* We didn't render it offscreen, but hand out an offscreen texture id */
|
||||
*is_offscreen = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
|
||||
render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
|
||||
|
||||
graphene_matrix_init_ortho (&item_proj,
|
||||
min_x * scale, max_x * scale,
|
||||
min_y * scale, max_y * scale,
|
||||
bounds->origin.x * scale,
|
||||
(bounds->origin.x + bounds->size.width) * scale,
|
||||
bounds->origin.y * scale,
|
||||
(bounds->origin.y + bounds->size.height) * scale,
|
||||
ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
|
||||
graphene_matrix_scale (&item_proj, 1, -1, 1);
|
||||
graphene_matrix_init_identity (&identity);
|
||||
@@ -2314,27 +2483,39 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
op.op = OP_CLEAR;
|
||||
ops_add (builder, &op);
|
||||
prev_projection = ops_set_projection (builder, &item_proj);
|
||||
prev_modelview = ops_set_modelview (builder, &identity);
|
||||
prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (min_x * scale,
|
||||
min_y * scale,
|
||||
width, height));
|
||||
ops_push_modelview (builder, &identity);
|
||||
prev_viewport = ops_set_viewport (builder,
|
||||
&GRAPHENE_RECT_INIT (bounds->origin.x * scale,
|
||||
bounds->origin.y * scale,
|
||||
width, height));
|
||||
if (reset_clip)
|
||||
prev_clip = ops_set_clip (builder,
|
||||
&GSK_ROUNDED_RECT_INIT (min_x * scale,
|
||||
min_y * scale,
|
||||
width, height));
|
||||
ops_push_clip (builder,
|
||||
&GSK_ROUNDED_RECT_INIT (bounds->origin.x * scale,
|
||||
bounds->origin.y * scale,
|
||||
width, height));
|
||||
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
prev_opacity = ops_set_opacity (builder, 1.0);
|
||||
|
||||
gsk_gl_renderer_add_render_ops (self, child_node, builder);
|
||||
|
||||
ops_set_opacity (builder, prev_opacity);
|
||||
builder->dx = dx;
|
||||
builder->dy = dy;
|
||||
|
||||
if (reset_clip)
|
||||
ops_set_clip (builder, &prev_clip);
|
||||
ops_pop_clip (builder);
|
||||
|
||||
ops_set_viewport (builder, &prev_viewport);
|
||||
ops_set_modelview (builder, &prev_modelview);
|
||||
ops_pop_modelview (builder);
|
||||
ops_set_projection (builder, &prev_projection);
|
||||
ops_set_render_target (builder, prev_render_target);
|
||||
|
||||
*is_offscreen = TRUE;
|
||||
*texture_id_out = texture_id;
|
||||
|
||||
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2481,6 +2662,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
|
||||
apply_border_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_BORDER_WIDTH:
|
||||
apply_border_width_op (program, op);
|
||||
break;
|
||||
|
||||
case OP_CHANGE_UNBLURRED_OUTSET_SHADOW:
|
||||
apply_unblurred_outset_shadow_op (program, op);
|
||||
break;
|
||||
@@ -2491,6 +2676,10 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
|
||||
glDrawArrays (GL_TRIANGLES, op->draw.vao_offset, op->draw.vao_size);
|
||||
break;
|
||||
|
||||
case OP_DUMP_FRAMEBUFFER:
|
||||
dump_framebuffer (op->dump.filename, op->dump.width, op->dump.height);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
@@ -2548,11 +2737,35 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
memset (&render_op_builder, 0, sizeof (render_op_builder));
|
||||
render_op_builder.renderer = self;
|
||||
render_op_builder.current_projection = projection;
|
||||
render_op_builder.current_modelview = modelview;
|
||||
render_op_builder.current_viewport = *viewport;
|
||||
render_op_builder.current_opacity = 1.0f;
|
||||
render_op_builder.render_ops = self->render_ops;
|
||||
gsk_rounded_rect_init_from_rect (&render_op_builder.current_clip, viewport, 0.0f);
|
||||
ops_push_modelview (&render_op_builder, &modelview);
|
||||
|
||||
/* Initial clip is self->render_region! */
|
||||
if (self->render_region != NULL)
|
||||
{
|
||||
GskRoundedRect transformed_render_region = { 0, };
|
||||
cairo_rectangle_int_t render_extents;
|
||||
|
||||
cairo_region_get_extents (self->render_region, &render_extents);
|
||||
|
||||
ops_transform_bounds_modelview (&render_op_builder,
|
||||
&GRAPHENE_RECT_INIT (render_extents.x,
|
||||
render_extents.y,
|
||||
render_extents.width,
|
||||
render_extents.height),
|
||||
&transformed_render_region.bounds);
|
||||
ops_push_clip (&render_op_builder, &transformed_render_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
ops_push_clip (&render_op_builder,
|
||||
&GSK_ROUNDED_RECT_INIT (viewport->origin.x,
|
||||
viewport->origin.y,
|
||||
viewport->size.width,
|
||||
viewport->size.height));
|
||||
}
|
||||
|
||||
if (fbo_id != 0)
|
||||
ops_set_render_target (&render_op_builder, fbo_id);
|
||||
@@ -2561,6 +2774,9 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
|
||||
|
||||
/* We correctly reset the state everywhere */
|
||||
g_assert_cmpint (render_op_builder.current_render_target, ==, fbo_id);
|
||||
ops_pop_modelview (&render_op_builder);
|
||||
ops_pop_clip (&render_op_builder);
|
||||
ops_finish (&render_op_builder);
|
||||
|
||||
/*g_message ("Ops: %u", self->render_ops->len);*/
|
||||
|
||||
|
||||
+312
-60
@@ -1,5 +1,22 @@
|
||||
#include "gskglrenderopsprivate.h"
|
||||
|
||||
static inline gboolean
|
||||
rect_equal (const graphene_rect_t *a,
|
||||
const graphene_rect_t *b)
|
||||
{
|
||||
return memcmp (a, b, sizeof (graphene_rect_t)) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
ops_finish (RenderOpBuilder *builder)
|
||||
{
|
||||
if (builder->mv_stack)
|
||||
g_array_free (builder->mv_stack, TRUE);
|
||||
|
||||
if (builder->clip_stack)
|
||||
g_array_free (builder->clip_stack, TRUE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
rgba_to_float (const GdkRGBA *c,
|
||||
float *f)
|
||||
@@ -10,13 +27,134 @@ rgba_to_float (const GdkRGBA *c,
|
||||
f[3] = c->alpha;
|
||||
}
|
||||
|
||||
/* Debugging only! */
|
||||
void
|
||||
ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
const char *filename,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
op.op = OP_DUMP_FRAMEBUFFER;
|
||||
op.dump.filename = g_strdup (filename);
|
||||
op.dump.width = width;
|
||||
op.dump.height = height;
|
||||
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
float
|
||||
ops_get_scale (const RenderOpBuilder *builder)
|
||||
{
|
||||
const graphene_matrix_t *mv = &builder->current_modelview;
|
||||
const MatrixStackEntry *head;
|
||||
|
||||
return MAX (graphene_matrix_get_x_scale (mv),
|
||||
graphene_matrix_get_y_scale (mv));
|
||||
g_assert (builder->mv_stack != NULL);
|
||||
g_assert (builder->mv_stack->len >= 1);
|
||||
|
||||
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
/* TODO: Use two separate values */
|
||||
return MAX (head->metadata.scale_x,
|
||||
head->metadata.scale_y);
|
||||
}
|
||||
|
||||
static void
|
||||
extract_matrix_metadata (const graphene_matrix_t *m,
|
||||
OpsMatrixMetadata *md)
|
||||
{
|
||||
graphene_vec3_t col1;
|
||||
graphene_vec3_t col2;
|
||||
|
||||
/* Translate */
|
||||
md->translate_x = graphene_matrix_get_value (m, 3, 0);
|
||||
md->translate_y = graphene_matrix_get_value (m, 3, 1);
|
||||
|
||||
/* Scale */
|
||||
graphene_vec3_init (&col1,
|
||||
graphene_matrix_get_value (m, 0, 0),
|
||||
graphene_matrix_get_value (m, 1, 0),
|
||||
graphene_matrix_get_value (m, 2, 0));
|
||||
|
||||
graphene_vec3_init (&col2,
|
||||
graphene_matrix_get_value (m, 0, 1),
|
||||
graphene_matrix_get_value (m, 1, 1),
|
||||
graphene_matrix_get_value (m, 2, 1));
|
||||
|
||||
md->scale_x = graphene_vec3_length (&col1);
|
||||
md->scale_y = graphene_vec3_length (&col2);
|
||||
|
||||
/* A simple matrix (in our case) is one that doesn't do anything but scale
|
||||
* and/or translate.
|
||||
*
|
||||
* For orher matrices, we fall back to offscreen drawing.
|
||||
*/
|
||||
md->simple = TRUE;
|
||||
{
|
||||
static const guchar check_zero[4][4] = {
|
||||
{ 0, 1, 0, 1 }, /* If any of the values marked as '1' here is non-zero, */
|
||||
{ 1, 0, 0, 1 }, /* We have to resort to offscreen drawing later on. */
|
||||
{ 1, 1, 0, 1 },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
int x, y;
|
||||
|
||||
for (x = 0; x < 4; x ++)
|
||||
for (y = 0; y < 4; y ++)
|
||||
if (check_zero[y][x] &&
|
||||
graphene_matrix_get_value (m, y, x) != 0.0f)
|
||||
{
|
||||
md->simple = FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
md->only_translation = (md->simple && md->scale_x == 1 && md->scale_y == 1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ops_transform_bounds_modelview (const RenderOpBuilder *builder,
|
||||
const graphene_rect_t *src,
|
||||
graphene_rect_t *dst)
|
||||
{
|
||||
const float scale = ops_get_scale (builder);
|
||||
const MatrixStackEntry *head;
|
||||
|
||||
g_assert (builder->mv_stack != NULL);
|
||||
g_assert (builder->mv_stack->len >= 1);
|
||||
|
||||
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
if (head->metadata.only_translation)
|
||||
{
|
||||
*dst = *src;
|
||||
graphene_rect_offset (dst,
|
||||
head->metadata.translate_x,
|
||||
head->metadata.translate_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphene_matrix_transform_bounds (builder->current_modelview,
|
||||
src,
|
||||
dst);
|
||||
}
|
||||
|
||||
graphene_rect_offset (dst, builder->dx * scale, builder->dy * scale);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ops_modelview_is_simple (const RenderOpBuilder *builder)
|
||||
{
|
||||
const MatrixStackEntry *head;
|
||||
|
||||
g_assert (builder->mv_stack != NULL);
|
||||
g_assert (builder->mv_stack->len >= 1);
|
||||
|
||||
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
return head->metadata.simple;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -29,6 +167,7 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
static const graphene_matrix_t empty_matrix;
|
||||
static const graphene_rect_t empty_rect;
|
||||
RenderOp op;
|
||||
ProgramState *program_state;
|
||||
|
||||
if (builder->current_program == program)
|
||||
return;
|
||||
@@ -38,58 +177,61 @@ ops_set_program (RenderOpBuilder *builder,
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->current_program = program;
|
||||
|
||||
program_state = &builder->program_state[program->index];
|
||||
|
||||
/* If the projection is not yet set for this program, we use the current one. */
|
||||
if (memcmp (&empty_matrix, &builder->program_state[program->index].projection, sizeof (graphene_matrix_t)) == 0 ||
|
||||
memcmp (&builder->current_projection, &builder->program_state[program->index].projection, sizeof (graphene_matrix_t)) != 0)
|
||||
if (memcmp (&empty_matrix, &program_state->projection, sizeof (graphene_matrix_t)) == 0 ||
|
||||
memcmp (&builder->current_projection, &program_state->projection, sizeof (graphene_matrix_t)) != 0)
|
||||
{
|
||||
op.op = OP_CHANGE_PROJECTION;
|
||||
op.projection = builder->current_projection;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->program_state[program->index].projection = builder->current_projection;
|
||||
program_state->projection = builder->current_projection;
|
||||
}
|
||||
|
||||
if (memcmp (&empty_matrix, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) == 0 ||
|
||||
memcmp (&builder->current_modelview, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) != 0)
|
||||
if (memcmp (&empty_matrix, &program_state->modelview, sizeof (graphene_matrix_t)) == 0 ||
|
||||
memcmp (builder->current_modelview, &program_state->modelview, sizeof (graphene_matrix_t)) != 0)
|
||||
{
|
||||
op.op = OP_CHANGE_MODELVIEW;
|
||||
op.modelview = builder->current_modelview;
|
||||
op.modelview = *builder->current_modelview;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->program_state[program->index].modelview = builder->current_modelview;
|
||||
program_state->modelview = *builder->current_modelview;
|
||||
}
|
||||
|
||||
if (memcmp (&empty_rect, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) == 0 ||
|
||||
memcmp (&builder->current_viewport, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) != 0)
|
||||
if (rect_equal (&empty_rect, &program_state->viewport) ||
|
||||
!rect_equal (&builder->current_viewport, &program_state->viewport))
|
||||
{
|
||||
op.op = OP_CHANGE_VIEWPORT;
|
||||
op.viewport = builder->current_viewport;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->program_state[program->index].viewport = builder->current_viewport;
|
||||
program_state->viewport = builder->current_viewport;
|
||||
}
|
||||
|
||||
if (memcmp (&empty_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect)) == 0 ||
|
||||
memcmp (&builder->current_clip, &builder->program_state[program->index].clip, sizeof (GskRoundedRect)) != 0)
|
||||
if (memcmp (&empty_clip, &program_state->clip, sizeof (GskRoundedRect)) == 0 ||
|
||||
memcmp (&builder->current_clip, &program_state->clip, sizeof (GskRoundedRect)) != 0)
|
||||
{
|
||||
op.op = OP_CHANGE_CLIP;
|
||||
op.clip = builder->current_clip;
|
||||
op.clip = *builder->current_clip;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->program_state[program->index].clip = builder->current_clip;
|
||||
program_state->clip = *builder->current_clip;
|
||||
}
|
||||
|
||||
if (builder->program_state[program->index].opacity != builder->current_opacity)
|
||||
if (program_state->opacity != builder->current_opacity)
|
||||
{
|
||||
op.op = OP_CHANGE_OPACITY;
|
||||
op.opacity = builder->current_opacity;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
builder->program_state[program->index].opacity = builder->current_opacity;
|
||||
program_state->opacity = builder->current_opacity;
|
||||
}
|
||||
|
||||
builder->current_program_state = &builder->program_state[program->index];
|
||||
}
|
||||
|
||||
GskRoundedRect
|
||||
static void
|
||||
ops_set_clip (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
RenderOp *last_op;
|
||||
GskRoundedRect prev_clip;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
@@ -110,25 +252,62 @@ ops_set_clip (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->program_state[builder->current_program->index].clip = *clip;
|
||||
|
||||
prev_clip = builder->current_clip;
|
||||
builder->current_clip = *clip;
|
||||
|
||||
return prev_clip;
|
||||
builder->current_program_state->clip = *clip;
|
||||
}
|
||||
|
||||
graphene_matrix_t
|
||||
void
|
||||
ops_push_clip (RenderOpBuilder *self,
|
||||
const GskRoundedRect *clip)
|
||||
{
|
||||
if (G_UNLIKELY (self->clip_stack == NULL))
|
||||
self->clip_stack = g_array_new (FALSE, TRUE, sizeof (GskRoundedRect));
|
||||
|
||||
g_assert (self->clip_stack != NULL);
|
||||
|
||||
g_array_append_val (self->clip_stack, *clip);
|
||||
self->current_clip = &g_array_index (self->clip_stack, GskRoundedRect, self->clip_stack->len - 1);
|
||||
ops_set_clip (self, clip);
|
||||
}
|
||||
|
||||
void
|
||||
ops_pop_clip (RenderOpBuilder *self)
|
||||
{
|
||||
const GskRoundedRect *head;
|
||||
|
||||
g_assert (self->clip_stack);
|
||||
g_assert (self->clip_stack->len >= 1);
|
||||
|
||||
self->clip_stack->len --;
|
||||
head = &g_array_index (self->clip_stack, GskRoundedRect, self->clip_stack->len - 1);
|
||||
|
||||
if (self->clip_stack->len >= 1)
|
||||
{
|
||||
self->current_clip = head;
|
||||
ops_set_clip (self, head);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->current_clip = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
ops_has_clip (RenderOpBuilder *self)
|
||||
{
|
||||
return self->clip_stack != NULL &&
|
||||
self->clip_stack->len > 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ops_set_modelview (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *modelview)
|
||||
{
|
||||
RenderOp op;
|
||||
graphene_matrix_t prev_mv;
|
||||
|
||||
if (builder->current_program &&
|
||||
memcmp (&builder->program_state[builder->current_program->index].modelview, modelview,
|
||||
memcmp (&builder->current_program_state->modelview, modelview,
|
||||
sizeof (graphene_matrix_t)) == 0)
|
||||
return *modelview;
|
||||
return;
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
@@ -152,12 +331,52 @@ ops_set_modelview (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->program_state[builder->current_program->index].modelview = *modelview;
|
||||
builder->current_program_state->modelview = *modelview;
|
||||
}
|
||||
|
||||
prev_mv = builder->current_modelview;
|
||||
builder->current_modelview = *modelview;
|
||||
void
|
||||
ops_push_modelview (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *mv)
|
||||
{
|
||||
MatrixStackEntry *entry;
|
||||
|
||||
return prev_mv;
|
||||
if (G_UNLIKELY (builder->mv_stack == NULL))
|
||||
builder->mv_stack = g_array_new (FALSE, TRUE, sizeof (MatrixStackEntry));
|
||||
|
||||
g_assert (builder->mv_stack != NULL);
|
||||
|
||||
g_array_set_size (builder->mv_stack, builder->mv_stack->len + 1);
|
||||
entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
|
||||
entry->matrix = *mv;
|
||||
extract_matrix_metadata (mv, &entry->metadata);
|
||||
|
||||
builder->current_modelview = &entry->matrix;
|
||||
ops_set_modelview (builder, mv);
|
||||
}
|
||||
|
||||
void
|
||||
ops_pop_modelview (RenderOpBuilder *builder)
|
||||
{
|
||||
const graphene_matrix_t *m;
|
||||
const MatrixStackEntry *head;
|
||||
|
||||
g_assert (builder->mv_stack);
|
||||
g_assert (builder->mv_stack->len >= 1);
|
||||
|
||||
builder->mv_stack->len --;
|
||||
head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
|
||||
m = &head->matrix;
|
||||
|
||||
if (builder->mv_stack->len >= 1)
|
||||
{
|
||||
builder->current_modelview = m;
|
||||
ops_set_modelview (builder, m);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder->current_modelview = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
graphene_matrix_t
|
||||
@@ -189,7 +408,7 @@ ops_set_projection (RenderOpBuilder *builder,
|
||||
}
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->program_state[builder->current_program->index].projection = *projection;
|
||||
builder->current_program_state->projection = *projection;
|
||||
|
||||
prev_mv = builder->current_projection;
|
||||
builder->current_projection = *projection;
|
||||
@@ -204,12 +423,16 @@ ops_set_viewport (RenderOpBuilder *builder,
|
||||
RenderOp op;
|
||||
graphene_rect_t prev_viewport;
|
||||
|
||||
if (builder->current_program_state != NULL &&
|
||||
rect_equal (&builder->current_program_state->viewport, viewport))
|
||||
return builder->current_program_state->viewport;
|
||||
|
||||
op.op = OP_CHANGE_VIEWPORT;
|
||||
op.viewport = *viewport;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->program_state[builder->current_program->index].viewport = *viewport;
|
||||
builder->current_program_state->viewport = *viewport;
|
||||
|
||||
prev_viewport = builder->current_viewport;
|
||||
builder->current_viewport = *viewport;
|
||||
@@ -243,9 +466,28 @@ ops_set_render_target (RenderOpBuilder *builder,
|
||||
return render_target_id;
|
||||
|
||||
prev_render_target = builder->current_render_target;
|
||||
op.op = OP_CHANGE_RENDER_TARGET;
|
||||
op.render_target_id = render_target_id;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
|
||||
if (builder->render_ops->len > 0)
|
||||
{
|
||||
RenderOp *last_op = &g_array_index (builder->render_ops, RenderOp, builder->render_ops->len - 1);
|
||||
if (last_op->op == OP_CHANGE_RENDER_TARGET)
|
||||
{
|
||||
last_op->render_target_id = render_target_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
op.op = OP_CHANGE_RENDER_TARGET;
|
||||
op.render_target_id = render_target_id;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op.op = OP_CHANGE_RENDER_TARGET;
|
||||
op.render_target_id = render_target_id;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
builder->current_render_target = render_target_id;
|
||||
|
||||
return prev_render_target;
|
||||
@@ -288,7 +530,7 @@ ops_set_opacity (RenderOpBuilder *builder,
|
||||
builder->current_opacity = opacity;
|
||||
|
||||
if (builder->current_program != NULL)
|
||||
builder->program_state[builder->current_program->index].opacity = opacity;
|
||||
builder->current_program_state->opacity = opacity;
|
||||
|
||||
return prev_opacity;
|
||||
}
|
||||
@@ -299,10 +541,10 @@ ops_set_color (RenderOpBuilder *builder,
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
if (gdk_rgba_equal (color, &builder->program_state[builder->current_program->index].color))
|
||||
if (gdk_rgba_equal (color, &builder->current_program_state->color))
|
||||
return;
|
||||
|
||||
builder->program_state[builder->current_program->index].color = *color;
|
||||
builder->current_program_state->color = *color;
|
||||
|
||||
op.op = OP_CHANGE_COLOR;
|
||||
op.color = *color;
|
||||
@@ -317,15 +559,15 @@ ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
RenderOp op;
|
||||
|
||||
if (memcmp (matrix,
|
||||
&builder->program_state[builder->current_program->index].color_matrix.matrix,
|
||||
&builder->current_program_state->color_matrix.matrix,
|
||||
sizeof (graphene_matrix_t)) == 0 &&
|
||||
memcmp (offset,
|
||||
&builder->program_state[builder->current_program->index].color_matrix.offset,
|
||||
&builder->current_program_state->color_matrix.offset,
|
||||
sizeof (graphene_vec4_t)) == 0)
|
||||
return;
|
||||
|
||||
builder->program_state[builder->current_program->index].color_matrix.matrix = *matrix;
|
||||
builder->program_state[builder->current_program->index].color_matrix.offset = *offset;
|
||||
builder->current_program_state->color_matrix.matrix = *matrix;
|
||||
builder->current_program_state->color_matrix.offset = *offset;
|
||||
|
||||
op.op = OP_CHANGE_COLOR_MATRIX;
|
||||
op.color_matrix.matrix = *matrix;
|
||||
@@ -335,30 +577,40 @@ ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
|
||||
void
|
||||
ops_set_border (RenderOpBuilder *builder,
|
||||
const float *widths,
|
||||
const GskRoundedRect *outline)
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
/* TODO: Assert that current_program == border program? */
|
||||
|
||||
if (memcmp (&builder->program_state[builder->current_program->index].border.widths,
|
||||
widths, sizeof (float) * 4) == 0 &&
|
||||
memcmp (&builder->program_state[builder->current_program->index].border.outline,
|
||||
if (memcmp (&builder->current_program_state->border.outline,
|
||||
outline, sizeof (GskRoundedRect)) == 0)
|
||||
return;
|
||||
|
||||
memcpy (&builder->program_state[builder->current_program->index].border.widths,
|
||||
widths, sizeof (float) * 4);
|
||||
|
||||
builder->program_state[builder->current_program->index].border.outline = *outline;
|
||||
builder->current_program_state->border.outline = *outline;
|
||||
|
||||
op.op = OP_CHANGE_BORDER;
|
||||
op.border.outline = *outline;
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
void
|
||||
ops_set_border_width (RenderOpBuilder *builder,
|
||||
const float *widths)
|
||||
{
|
||||
RenderOp op;
|
||||
|
||||
if (memcmp (builder->current_program_state->border.widths,
|
||||
widths, sizeof (float) * 4) == 0)
|
||||
return;
|
||||
|
||||
memcpy (&builder->current_program_state->border.widths,
|
||||
widths, sizeof (float) * 4);
|
||||
|
||||
op.op = OP_CHANGE_BORDER_WIDTH;
|
||||
op.border.widths[0] = widths[0];
|
||||
op.border.widths[1] = widths[1];
|
||||
op.border.widths[2] = widths[2];
|
||||
op.border.widths[3] = widths[3];
|
||||
op.border.outline = *outline;
|
||||
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
@@ -370,11 +622,11 @@ ops_set_border_color (RenderOpBuilder *builder,
|
||||
op.op = OP_CHANGE_BORDER_COLOR;
|
||||
rgba_to_float (color, op.border.color);
|
||||
|
||||
if (memcmp (&op.border.color, &builder->program_state[builder->current_program->index].border.color,
|
||||
if (memcmp (&op.border.color, &builder->current_program_state->border.color,
|
||||
sizeof (float) * 4) == 0)
|
||||
return;
|
||||
|
||||
rgba_to_float (color, builder->program_state[builder->current_program->index].border.color);
|
||||
rgba_to_float (color, builder->current_program_state->border.color);
|
||||
|
||||
g_array_append_val (builder->render_ops, op);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,26 @@
|
||||
#include "gskglrendererprivate.h"
|
||||
|
||||
#define GL_N_VERTICES 6
|
||||
#define GL_N_PROGRAMS 12
|
||||
#define GL_N_PROGRAMS 11
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float translate_x;
|
||||
float translate_y;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
|
||||
guint simple : 1;
|
||||
guint only_translation : 1;
|
||||
} OpsMatrixMetadata;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
OpsMatrixMetadata metadata;
|
||||
} MatrixStackEntry;
|
||||
|
||||
enum {
|
||||
OP_NONE,
|
||||
@@ -31,10 +50,12 @@ enum {
|
||||
OP_CHANGE_OUTSET_SHADOW = 15,
|
||||
OP_CHANGE_BORDER = 16,
|
||||
OP_CHANGE_BORDER_COLOR = 17,
|
||||
OP_CHANGE_CROSS_FADE = 18,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 19,
|
||||
OP_CLEAR = 20,
|
||||
OP_DRAW = 21,
|
||||
OP_CHANGE_BORDER_WIDTH = 18,
|
||||
OP_CHANGE_CROSS_FADE = 19,
|
||||
OP_CHANGE_UNBLURRED_OUTSET_SHADOW = 20,
|
||||
OP_CLEAR = 21,
|
||||
OP_DRAW = 22,
|
||||
OP_DUMP_FRAMEBUFFER = 23,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
@@ -188,40 +209,46 @@ typedef struct
|
||||
float progress;
|
||||
int source2;
|
||||
} cross_fade;
|
||||
struct {
|
||||
char *filename;
|
||||
int width;
|
||||
int height;
|
||||
} dump;
|
||||
};
|
||||
} RenderOp;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Per-Program State */
|
||||
struct {
|
||||
GskRoundedRect clip;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
int source_texture;
|
||||
graphene_rect_t viewport;
|
||||
float opacity;
|
||||
/* Per-program state */
|
||||
union {
|
||||
GdkRGBA color;
|
||||
struct {
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} color_matrix;
|
||||
struct {
|
||||
float widths[4];
|
||||
float color[4];
|
||||
GskRoundedRect outline;
|
||||
} border;
|
||||
};
|
||||
} program_state[GL_N_PROGRAMS];
|
||||
GskRoundedRect clip;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
int source_texture;
|
||||
graphene_rect_t viewport;
|
||||
float opacity;
|
||||
/* Per-program state */
|
||||
union {
|
||||
GdkRGBA color;
|
||||
struct {
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} color_matrix;
|
||||
struct {
|
||||
float widths[4];
|
||||
float color[4];
|
||||
GskRoundedRect outline;
|
||||
} border;
|
||||
};
|
||||
} ProgramState;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ProgramState program_state[GL_N_PROGRAMS];
|
||||
/* Current global state */
|
||||
ProgramState *current_program_state;
|
||||
const Program *current_program;
|
||||
int current_render_target;
|
||||
int current_texture;
|
||||
GskRoundedRect current_clip;
|
||||
graphene_matrix_t current_modelview;
|
||||
|
||||
graphene_matrix_t current_projection;
|
||||
graphene_rect_t current_viewport;
|
||||
float current_opacity;
|
||||
@@ -231,20 +258,41 @@ typedef struct
|
||||
|
||||
GArray *render_ops;
|
||||
GskGLRenderer *renderer;
|
||||
|
||||
/* Stack of modelview matrices */
|
||||
GArray *mv_stack;
|
||||
/* Pointer into mv_stack */
|
||||
const graphene_matrix_t *current_modelview;
|
||||
|
||||
/* Same thing */
|
||||
GArray *clip_stack;
|
||||
const GskRoundedRect *current_clip;
|
||||
} RenderOpBuilder;
|
||||
|
||||
|
||||
void ops_dump_framebuffer (RenderOpBuilder *builder,
|
||||
const char *filename,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
void ops_finish (RenderOpBuilder *builder);
|
||||
void ops_push_modelview (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *mv);
|
||||
void ops_pop_modelview (RenderOpBuilder *builder);
|
||||
gboolean ops_modelview_is_simple (const RenderOpBuilder *builder);
|
||||
float ops_get_scale (const RenderOpBuilder *builder);
|
||||
|
||||
void ops_set_program (RenderOpBuilder *builder,
|
||||
const Program *program);
|
||||
|
||||
GskRoundedRect ops_set_clip (RenderOpBuilder *builder,
|
||||
void ops_push_clip (RenderOpBuilder *builder,
|
||||
const GskRoundedRect *clip);
|
||||
void ops_pop_clip (RenderOpBuilder *builder);
|
||||
gboolean ops_has_clip (RenderOpBuilder *builder);
|
||||
|
||||
graphene_matrix_t ops_set_modelview (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *modelview);
|
||||
void ops_transform_bounds_modelview (const RenderOpBuilder *builder,
|
||||
const graphene_rect_t *src,
|
||||
graphene_rect_t *dst);
|
||||
|
||||
graphene_matrix_t ops_set_projection (RenderOpBuilder *builder,
|
||||
const graphene_matrix_t *projection);
|
||||
@@ -268,8 +316,9 @@ void ops_set_color_matrix (RenderOpBuilder *builder,
|
||||
const graphene_vec4_t *offset);
|
||||
|
||||
void ops_set_border (RenderOpBuilder *builder,
|
||||
const float *widths,
|
||||
const GskRoundedRect *outline);
|
||||
void ops_set_border_width (RenderOpBuilder *builder,
|
||||
const float *widths);
|
||||
|
||||
void ops_set_border_color (RenderOpBuilder *builder,
|
||||
const GdkRGBA *color);
|
||||
|
||||
+29
-11
@@ -15,6 +15,9 @@ struct _GskShaderBuilder
|
||||
char *vertex_preamble;
|
||||
char *fragment_preamble;
|
||||
|
||||
|
||||
int common_vertex_shader_id;
|
||||
|
||||
int version;
|
||||
|
||||
GPtrArray *defines;
|
||||
@@ -37,6 +40,9 @@ gsk_shader_builder_finalize (GObject *gobject)
|
||||
|
||||
g_clear_pointer (&self->defines, g_ptr_array_unref);
|
||||
|
||||
if (self->common_vertex_shader_id > 0)
|
||||
glDeleteShader (self->common_vertex_shader_id);
|
||||
|
||||
G_OBJECT_CLASS (gsk_shader_builder_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
@@ -230,27 +236,39 @@ gsk_shader_builder_compile_shader (GskShaderBuilder *builder,
|
||||
return shader_id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
|
||||
const char *vertex_shader,
|
||||
GError **error)
|
||||
{
|
||||
int shader_id;
|
||||
|
||||
|
||||
shader_id = gsk_shader_builder_compile_shader (self,
|
||||
GL_VERTEX_SHADER,
|
||||
self->vertex_preamble,
|
||||
vertex_shader,
|
||||
error);
|
||||
|
||||
g_assert (shader_id > 0);
|
||||
self->common_vertex_shader_id = shader_id;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *vertex_shader,
|
||||
const char *fragment_shader,
|
||||
GError **error)
|
||||
{
|
||||
int vertex_id, fragment_id;
|
||||
int vertex_id;
|
||||
int fragment_id;
|
||||
int program_id;
|
||||
int status;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_SHADER_BUILDER (builder), -1);
|
||||
g_return_val_if_fail (vertex_shader != NULL, -1);
|
||||
g_return_val_if_fail (fragment_shader != NULL, -1);
|
||||
g_return_val_if_fail (builder->common_vertex_shader_id != 0, -1);
|
||||
|
||||
vertex_id = gsk_shader_builder_compile_shader (builder, GL_VERTEX_SHADER,
|
||||
builder->vertex_preamble,
|
||||
vertex_shader,
|
||||
error);
|
||||
if (vertex_id < 0)
|
||||
return -1;
|
||||
|
||||
vertex_id = builder->common_vertex_shader_id;
|
||||
fragment_id = gsk_shader_builder_compile_shader (builder, GL_FRAGMENT_SHADER,
|
||||
builder->fragment_preamble,
|
||||
fragment_shader,
|
||||
@@ -290,8 +308,8 @@ gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
out:
|
||||
if (vertex_id > 0)
|
||||
{
|
||||
/* We delete the common vertex shader when destroying the shader builder */
|
||||
glDetachShader (program_id, vertex_id);
|
||||
glDeleteShader (vertex_id);
|
||||
}
|
||||
|
||||
if (fragment_id > 0)
|
||||
|
||||
@@ -25,8 +25,11 @@ void gsk_shader_builder_add_define (GskShad
|
||||
const char *define_name,
|
||||
const char *define_value);
|
||||
|
||||
void gsk_shader_builder_set_common_vertex_shader (GskShaderBuilder *self,
|
||||
const char *vertex_shader,
|
||||
GError **error);
|
||||
|
||||
int gsk_shader_builder_create_program (GskShaderBuilder *builder,
|
||||
const char *vertex_shader,
|
||||
const char *fragment_shader,
|
||||
GError **error);
|
||||
|
||||
|
||||
+1
-2
@@ -1,6 +1,4 @@
|
||||
gsk_private_gl_shaders = [
|
||||
'resources/glsl/blend.fs.glsl',
|
||||
'resources/glsl/blend.vs.glsl',
|
||||
'resources/glsl/blit.fs.glsl',
|
||||
'resources/glsl/blit.vs.glsl',
|
||||
'resources/glsl/color.fs.glsl',
|
||||
@@ -43,6 +41,7 @@ gsk_private_sources = files([
|
||||
'gl/gskgldriver.c',
|
||||
'gl/gskglrenderops.c',
|
||||
'gl/gskglshadowcache.c',
|
||||
'gl/gskglnodesample.c',
|
||||
])
|
||||
|
||||
gsk_public_headers = files([
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
vec3 BlendMultiply(vec3 Cb, vec3 Cs) {
|
||||
return Cb * Cs;
|
||||
}
|
||||
|
||||
vec3 BlendScreen(vec3 Cb, vec3 Cs) {
|
||||
return Cb + Cs - (Cb * Cs);
|
||||
}
|
||||
|
||||
vec3 BlendHardLight(vec3 Cb, vec3 Cs) {
|
||||
vec3 m = BlendMultiply(Cb, 2.0 * Cs);
|
||||
vec3 s = BlendScreen(Cb, 2.0 * Cs - 1.0);
|
||||
vec3 edge = vec3(0.5, 0.5, 0.5);
|
||||
|
||||
/* Use mix() and step() to avoid a branch */
|
||||
return mix(m, s, step(edge, Cs));
|
||||
}
|
||||
|
||||
vec3 BlendOverlay(vec3 Cb, vec3 Cs) {
|
||||
return BlendHardLight(Cs, Cb);
|
||||
}
|
||||
|
||||
vec3 BlendDarken(vec3 Cb, vec3 Cs) {
|
||||
return min(Cb, Cs);
|
||||
}
|
||||
|
||||
vec3 BlendLighten(vec3 Cb, vec3 Cs) {
|
||||
return max(Cb, Cs);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 Cs = Texture(u_source, vUv);
|
||||
vec4 Cb = Texture(u_mask, vUv);
|
||||
vec3 res;
|
||||
|
||||
if (uBlendMode == 0) {
|
||||
res = Cs.xyz;
|
||||
}
|
||||
else if (uBlendMode == 1) {
|
||||
res = BlendMultiply(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else if (uBlendMode == 2) {
|
||||
res = BlendScreen(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else if (uBlendMode == 3) {
|
||||
res = BlendOverlay(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else if (uBlendMode == 4) {
|
||||
res = BlendDarken(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else if (uBlendMode == 5) {
|
||||
res = BlendLighten(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else if (uBlendMode == 8) {
|
||||
res = BlendHardLight(Cb.xyz, Cs.xyz);
|
||||
}
|
||||
else {
|
||||
// Use red for debugging missing blend modes
|
||||
res = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
setOutputColor(vec4(res, Cs.a) * u_alpha);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
void main() {
|
||||
gl_Position = u_modelview * u_projection * vec4(aPosition, 0.0, 1.0);
|
||||
|
||||
vUv = vec2(aUv.x, aUv.y);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ developers, including those developing proprietary software, without
|
||||
any license fees or royalties.</description>
|
||||
<homepage rdf:resource="http://www.gtk.org/" />
|
||||
<license rdf:resource="http://usefulinc.com/doap/licenses/lgpl" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/enter_bug.cgi?product=gtk%2B" />
|
||||
<bug-database rdf:resource="https://gitlab.gnome.org/GNOME/gtk/issues/" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/gtk+/" />
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gtk-list" />
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list" />
|
||||
@@ -39,8 +39,8 @@ any license fees or royalties.</description>
|
||||
|
||||
<repository>
|
||||
<GitRepository>
|
||||
<browse rdf:resource="http://git.gnome.org/browse/gtk+/"/>
|
||||
<location rdf:resource="git://git.gnome.org/gtk+"/>
|
||||
<browse rdf:resource="https://gitlab.gnome.org/GNOME/gtk/"/>
|
||||
<location rdf:resource="https://gitlab.gnome.org/GNOME/gtk.git"/>
|
||||
</GitRepository>
|
||||
</repository>
|
||||
|
||||
|
||||
@@ -46,11 +46,13 @@ static const struct {
|
||||
static GtkCellRendererState gtk_cell_accessible_get_state (GtkCellAccessible *cell);
|
||||
static void atk_action_interface_init (AtkActionIface *iface);
|
||||
static void atk_component_interface_init (AtkComponentIface *iface);
|
||||
static void atk_table_cell_interface_init (AtkTableCellIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkCellAccessible, gtk_cell_accessible, GTK_TYPE_ACCESSIBLE,
|
||||
G_ADD_PRIVATE (GtkCellAccessible)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_ACTION, atk_action_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init))
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, atk_component_interface_init)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_TABLE_CELL, atk_table_cell_interface_init))
|
||||
|
||||
static gint
|
||||
gtk_cell_accessible_get_index_in_parent (AtkObject *obj)
|
||||
@@ -366,6 +368,90 @@ atk_component_interface_init (AtkComponentIface *iface)
|
||||
iface->grab_focus = gtk_cell_accessible_grab_focus;
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_cell_accessible_get_column_span (AtkTableCell *table_cell)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
gtk_cell_accessible_get_column_header_cells (AtkTableCell *table_cell)
|
||||
{
|
||||
GtkCellAccessible *cell;
|
||||
AtkObject *parent;
|
||||
|
||||
cell = GTK_CELL_ACCESSIBLE (table_cell);
|
||||
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
|
||||
|
||||
return gtk_cell_accessible_parent_get_column_header_cells (GTK_CELL_ACCESSIBLE_PARENT (parent),
|
||||
cell);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_cell_accessible_get_position (AtkTableCell *table_cell,
|
||||
gint *row,
|
||||
gint *column)
|
||||
{
|
||||
GtkCellAccessible *cell;
|
||||
AtkObject *parent;
|
||||
|
||||
cell = GTK_CELL_ACCESSIBLE (table_cell);
|
||||
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
|
||||
|
||||
gtk_cell_accessible_parent_get_cell_position (GTK_CELL_ACCESSIBLE_PARENT (parent),
|
||||
cell,
|
||||
row, column);
|
||||
return ((row && *row > 0) || (column && *column > 0));
|
||||
}
|
||||
|
||||
static int
|
||||
gtk_cell_accessible_get_row_span (AtkTableCell *table_cell)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
gtk_cell_accessible_get_row_header_cells (AtkTableCell *table_cell)
|
||||
{
|
||||
GtkCellAccessible *cell;
|
||||
AtkObject *parent;
|
||||
|
||||
cell = GTK_CELL_ACCESSIBLE (table_cell);
|
||||
parent = gtk_widget_get_accessible (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)));
|
||||
|
||||
return gtk_cell_accessible_parent_get_row_header_cells (GTK_CELL_ACCESSIBLE_PARENT (parent),
|
||||
cell);
|
||||
}
|
||||
|
||||
static AtkObject *
|
||||
gtk_cell_accessible_get_table (AtkTableCell *table_cell)
|
||||
{
|
||||
AtkObject *obj;
|
||||
|
||||
obj = ATK_OBJECT (table_cell);
|
||||
do
|
||||
{
|
||||
AtkRole role;
|
||||
obj = atk_object_get_parent (obj);
|
||||
role = atk_object_get_role (obj);
|
||||
if (role == ATK_ROLE_TABLE || role == ATK_ROLE_TREE_TABLE)
|
||||
break;
|
||||
}
|
||||
while (obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void
|
||||
atk_table_cell_interface_init (AtkTableCellIface *iface)
|
||||
{
|
||||
iface->get_column_span = gtk_cell_accessible_get_column_span;
|
||||
iface->get_column_header_cells = gtk_cell_accessible_get_column_header_cells;
|
||||
iface->get_position = gtk_cell_accessible_get_position;
|
||||
iface->get_row_span = gtk_cell_accessible_get_row_span;
|
||||
iface->get_row_header_cells = gtk_cell_accessible_get_row_header_cells;
|
||||
iface->get_table = gtk_cell_accessible_get_table;
|
||||
}
|
||||
|
||||
static GtkCellRendererState
|
||||
gtk_cell_accessible_get_state (GtkCellAccessible *cell)
|
||||
{
|
||||
|
||||
@@ -187,3 +187,69 @@ gtk_cell_accessible_parent_update_relationset (GtkCellAccessibleParent *parent,
|
||||
if (iface->update_relationset)
|
||||
(iface->update_relationset) (parent, cell, relationset);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_cell_accessible_parent_get_cell_position (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
gint *row,
|
||||
gint *column)
|
||||
{
|
||||
GtkCellAccessibleParentIface *iface;
|
||||
|
||||
g_return_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent));
|
||||
g_return_if_fail (GTK_IS_CELL_ACCESSIBLE (cell));
|
||||
|
||||
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
|
||||
|
||||
if (iface->get_cell_position)
|
||||
(iface->get_cell_position) (parent, cell, row, column);
|
||||
else
|
||||
{
|
||||
if (row)
|
||||
*row = -1;
|
||||
if (column)
|
||||
*column = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cell_accessible_parent_get_column_header_cells:
|
||||
* Returns: (transfer full) (element-type AtkObject)
|
||||
*/
|
||||
GPtrArray *
|
||||
gtk_cell_accessible_parent_get_column_header_cells (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell)
|
||||
{
|
||||
GtkCellAccessibleParentIface *iface;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE (cell), NULL);
|
||||
|
||||
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
|
||||
|
||||
if (iface->get_column_header_cells)
|
||||
return (iface->get_column_header_cells) (parent, cell);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_cell_accessible_parent_get_row_header_cells:
|
||||
* Returns: (transfer full) (element-type AtkObject)
|
||||
*/
|
||||
GPtrArray *
|
||||
gtk_cell_accessible_parent_get_row_header_cells (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell)
|
||||
{
|
||||
GtkCellAccessibleParentIface *iface;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE_PARENT (parent), NULL);
|
||||
g_return_val_if_fail (GTK_IS_CELL_ACCESSIBLE (cell), NULL);
|
||||
|
||||
iface = GTK_CELL_ACCESSIBLE_PARENT_GET_IFACE (parent);
|
||||
|
||||
if (iface->get_row_header_cells)
|
||||
return (iface->get_row_header_cells) (parent, cell);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,14 @@ struct _GtkCellAccessibleParentIface
|
||||
void ( *update_relationset) (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
AtkRelationSet *relationset);
|
||||
void ( *get_cell_position) (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
gint *row,
|
||||
gint *column);
|
||||
GPtrArray * ( *get_column_header_cells) (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell);
|
||||
GPtrArray * ( *get_row_header_cells) (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
@@ -115,6 +123,17 @@ GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cell_accessible_parent_update_relationset (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
AtkRelationSet *relationset);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_cell_accessible_parent_get_cell_position(GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
gint *row,
|
||||
gint *column);
|
||||
|
||||
GPtrArray *gtk_cell_accessible_parent_get_column_header_cells (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell);
|
||||
|
||||
GPtrArray *gtk_cell_accessible_parent_get_row_header_cells (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -1174,11 +1174,12 @@ gtk_tree_view_accessible_grab_cell_focus (GtkCellAccessibleParent *parent,
|
||||
if (gtk_widget_is_toplevel (toplevel))
|
||||
{
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
gtk_window_present_with_time (GTK_WINDOW (toplevel),
|
||||
gdk_x11_get_server_time (gtk_widget_get_surface (widget)));
|
||||
#else
|
||||
gtk_window_present (GTK_WINDOW (toplevel));
|
||||
if (GDK_IS_X11_DISPLAY (gtk_widget_get_display (toplevel)))
|
||||
gtk_window_present_with_time (GTK_WINDOW (toplevel),
|
||||
gdk_x11_get_server_time (gtk_widget_get_surface (widget)));
|
||||
else
|
||||
#endif
|
||||
gtk_window_present (GTK_WINDOW (toplevel));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -1391,6 +1392,56 @@ gtk_tree_view_accessible_update_relationset (GtkCellAccessibleParent *parent,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_tree_view_accessible_get_cell_position (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell,
|
||||
gint *row,
|
||||
gint *column)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkTreeView *tree_view;
|
||||
GtkTreeViewAccessibleCellInfo *cell_info;
|
||||
GtkTreeViewAccessible *accessible;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
|
||||
if (widget == NULL)
|
||||
return;
|
||||
|
||||
tree_view = GTK_TREE_VIEW (widget);
|
||||
accessible = GTK_TREE_VIEW_ACCESSIBLE (parent);
|
||||
cell_info = find_cell_info (accessible, cell);
|
||||
if (!cell_info)
|
||||
return;
|
||||
|
||||
if (row)
|
||||
(*row) = _gtk_rbtree_node_get_index (cell_info->tree, cell_info->node);
|
||||
if (column)
|
||||
(*column) = get_column_number (tree_view, cell_info->cell_col_ref);
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
gtk_tree_view_accessible_get_column_header_cells (GtkCellAccessibleParent *parent,
|
||||
GtkCellAccessible *cell)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkTreeViewAccessibleCellInfo *cell_info;
|
||||
GtkTreeViewAccessible *accessible;
|
||||
GPtrArray *array;
|
||||
|
||||
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (parent));
|
||||
if (widget == NULL)
|
||||
return NULL;
|
||||
|
||||
accessible = GTK_TREE_VIEW_ACCESSIBLE (parent);
|
||||
cell_info = find_cell_info (accessible, cell);
|
||||
if (!cell_info)
|
||||
return NULL;
|
||||
|
||||
array = g_ptr_array_new_full (1, g_object_unref);
|
||||
g_ptr_array_add (array, g_object_ref (get_header_from_column ( (cell_info->cell_col_ref))));
|
||||
return array;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
|
||||
{
|
||||
@@ -1403,6 +1454,8 @@ gtk_cell_accessible_parent_interface_init (GtkCellAccessibleParentIface *iface)
|
||||
iface->activate = gtk_tree_view_accessible_activate;
|
||||
iface->edit = gtk_tree_view_accessible_edit;
|
||||
iface->update_relationset = gtk_tree_view_accessible_update_relationset;
|
||||
iface->get_cell_position = gtk_tree_view_accessible_get_cell_position;
|
||||
iface->get_column_header_cells = gtk_tree_view_accessible_get_column_header_cells;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -59,8 +59,9 @@ notify_cb (GObject *obj,
|
||||
|
||||
/* Translate GtkWidget::size-allocate to AtkComponent::bounds-changed */
|
||||
static void
|
||||
size_allocate_cb (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
size_allocate_cb (GtkWidget *widget,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
AtkObject* accessible;
|
||||
AtkRectangle rect;
|
||||
@@ -68,10 +69,14 @@ size_allocate_cb (GtkWidget *widget,
|
||||
accessible = gtk_widget_get_accessible (widget);
|
||||
if (ATK_IS_COMPONENT (accessible))
|
||||
{
|
||||
rect.x = allocation->x;
|
||||
rect.y = allocation->y;
|
||||
rect.width = allocation->width;
|
||||
rect.height = allocation->height;
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
|
||||
rect.x = alloc.x;
|
||||
rect.y = alloc.y;
|
||||
rect.width = alloc.width;
|
||||
rect.height = alloc.height;
|
||||
|
||||
g_signal_emit_by_name (accessible, "bounds-changed", &rect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkViewport, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkVolumeButton, g_object_unref)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkPaperSize, gtk_paper_size_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkRecentInfo, gtk_recent_info_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkSelectionData, gtk_selection_data_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTextIter, gtk_text_iter_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkTreeIter, gtk_tree_iter_free)
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
#include <gtk/gtkenums.h>
|
||||
#include <gtk/gtkeventcontroller.h>
|
||||
#include <gtk/gtkeventcontrollerkey.h>
|
||||
#include <gtk/gtkeventcontrollerlegacy.h>
|
||||
#include <gtk/gtkeventcontrollermotion.h>
|
||||
#include <gtk/gtkeventcontrollerscroll.h>
|
||||
#include <gtk/gtkexpander.h>
|
||||
@@ -104,6 +105,8 @@
|
||||
#include <gtk/gtkfilechoosernative.h>
|
||||
#include <gtk/gtkfilechooserwidget.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/gtkfilterlistmodel.h>
|
||||
#include <gtk/gtkflattenlistmodel.h>
|
||||
#include <gtk/gtkflowbox.h>
|
||||
#include <gtk/gtkfontbutton.h>
|
||||
#include <gtk/gtkfontchooser.h>
|
||||
@@ -139,6 +142,7 @@
|
||||
#include <gtk/gtkliststore.h>
|
||||
#include <gtk/gtklockbutton.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
#include <gtk/gtkmaplistmodel.h>
|
||||
#include <gtk/gtkmediacontrols.h>
|
||||
#include <gtk/gtkmediafile.h>
|
||||
#include <gtk/gtkmediastream.h>
|
||||
@@ -192,7 +196,9 @@
|
||||
#include <gtk/gtkshortcutsshortcut.h>
|
||||
#include <gtk/gtkshortcutswindow.h>
|
||||
#include <gtk/gtkshow.h>
|
||||
#include <gtk/gtkslicelistmodel.h>
|
||||
#include <gtk/gtksnapshot.h>
|
||||
#include <gtk/gtksortlistmodel.h>
|
||||
#include <gtk/gtkstacksidebar.h>
|
||||
#include <gtk/gtksizegroup.h>
|
||||
#include <gtk/gtksizerequest.h>
|
||||
@@ -220,6 +226,7 @@
|
||||
#include <gtk/gtktooltip.h>
|
||||
#include <gtk/gtktestutils.h>
|
||||
#include <gtk/gtktreednd.h>
|
||||
#include <gtk/gtktreelistmodel.h>
|
||||
#include <gtk/gtktreemodel.h>
|
||||
#include <gtk/gtktreemodelfilter.h>
|
||||
#include <gtk/gtktreemodelsort.h>
|
||||
|
||||
+9
-4
@@ -160,14 +160,19 @@ static void gtk_accel_label_measure (GtkWidget *widget,
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_accel_label_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline)
|
||||
gtk_accel_label_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkAccelLabel *al = GTK_ACCEL_LABEL (widget);
|
||||
GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (al);
|
||||
|
||||
gtk_widget_size_allocate (priv->box, allocation, baseline);
|
||||
gtk_widget_size_allocate (priv->box,
|
||||
&(GtkAllocation) {
|
||||
0, 0,
|
||||
width, height
|
||||
},baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ gtk_actionable_get_action_target_value (GtkActionable *actionable)
|
||||
/**
|
||||
* gtk_actionable_set_action_target_value:
|
||||
* @actionable: a #GtkActionable widget
|
||||
* @target_value: a #GVariant to set as the target value, or %NULL
|
||||
* @target_value: (nullable): a #GVariant to set as the target value, or %NULL
|
||||
*
|
||||
* Sets the target value of an actionable widget.
|
||||
*
|
||||
|
||||
+11
-15
@@ -259,22 +259,19 @@ gtk_action_bar_set_child_property (GtkContainer *container,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_bar_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkActionBar *self = GTK_ACTION_BAR (widget);
|
||||
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (self);
|
||||
|
||||
gtk_widget_snapshot_child (GTK_WIDGET (self), priv->revealer, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_action_bar_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
int baseline)
|
||||
gtk_action_bar_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkActionBarPrivate *priv = gtk_action_bar_get_instance_private (GTK_ACTION_BAR (widget));
|
||||
gtk_widget_size_allocate (priv->revealer, allocation, baseline);
|
||||
|
||||
gtk_widget_size_allocate (priv->revealer,
|
||||
&(GtkAllocation) {
|
||||
0, 0,
|
||||
width, height
|
||||
},
|
||||
baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -364,7 +361,6 @@ gtk_action_bar_class_init (GtkActionBarClass *klass)
|
||||
object_class->get_property = gtk_action_bar_get_property;
|
||||
object_class->finalize = gtk_action_bar_finalize;
|
||||
|
||||
widget_class->snapshot = gtk_action_bar_snapshot;
|
||||
widget_class->size_allocate = gtk_action_bar_size_allocate;
|
||||
widget_class->measure = gtk_action_bar_measure_;
|
||||
widget_class->destroy = gtk_action_bar_destroy;
|
||||
|
||||
+169
-79
@@ -1,4 +1,4 @@
|
||||
/* gtkappchooserbutton.c: an app-chooser combobox
|
||||
/* gtkappchooserbutton.c: an app-chooser button
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
@@ -44,7 +44,7 @@
|
||||
* emitted when they are selected.
|
||||
*
|
||||
* To track changes in the selected application, use the
|
||||
* #GtkComboBox::changed signal.
|
||||
* #GtkAppChooserbutton::changed signal.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
@@ -71,6 +71,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
SIGNAL_CHANGED,
|
||||
SIGNAL_CUSTOM_ITEM_ACTIVATED,
|
||||
NUM_SIGNALS
|
||||
};
|
||||
@@ -103,7 +104,9 @@ static void real_insert_separator (GtkAppChooserButton *self,
|
||||
static guint signals[NUM_SIGNALS] = { 0, };
|
||||
static GParamSpec *properties[NUM_PROPERTIES];
|
||||
|
||||
struct _GtkAppChooserButtonPrivate {
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *combobox;
|
||||
GtkListStore *store;
|
||||
|
||||
gchar *content_type;
|
||||
@@ -113,9 +116,9 @@ struct _GtkAppChooserButtonPrivate {
|
||||
gboolean show_default_item;
|
||||
|
||||
GHashTable *custom_item_names;
|
||||
};
|
||||
} GtkAppChooserButtonPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserButton, gtk_app_chooser_button, GTK_TYPE_COMBO_BOX,
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkAppChooserButton, gtk_app_chooser_button, GTK_TYPE_WIDGET,
|
||||
G_ADD_PRIVATE (GtkAppChooserButton)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_APP_CHOOSER,
|
||||
app_chooser_iface_init));
|
||||
@@ -174,6 +177,8 @@ select_application_func_cb (GtkTreeModel *model,
|
||||
gpointer user_data)
|
||||
{
|
||||
SelectAppData *data = user_data;
|
||||
GtkAppChooserButton *self = data->self;
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GAppInfo *app_to_match = data->info;
|
||||
GAppInfo *app = NULL;
|
||||
gboolean custom;
|
||||
@@ -191,7 +196,7 @@ select_application_func_cb (GtkTreeModel *model,
|
||||
result = TRUE;
|
||||
else if (g_app_info_equal (app, app_to_match))
|
||||
{
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (data->self), iter);
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combobox), iter);
|
||||
result = TRUE;
|
||||
}
|
||||
else
|
||||
@@ -206,13 +211,14 @@ static void
|
||||
gtk_app_chooser_button_select_application (GtkAppChooserButton *self,
|
||||
GAppInfo *info)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
SelectAppData *data;
|
||||
|
||||
data = g_slice_new0 (SelectAppData);
|
||||
data->self = g_object_ref (self);
|
||||
data->info = g_object_ref (info);
|
||||
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (self->priv->store),
|
||||
gtk_tree_model_foreach (GTK_TREE_MODEL (priv->store),
|
||||
select_application_func_cb, data);
|
||||
|
||||
select_app_data_free (data);
|
||||
@@ -224,6 +230,7 @@ other_application_dialog_response_cb (GtkDialog *dialog,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAppChooserButton *self = user_data;
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GAppInfo *info;
|
||||
|
||||
if (response_id != GTK_RESPONSE_OK)
|
||||
@@ -231,7 +238,7 @@ other_application_dialog_response_cb (GtkDialog *dialog,
|
||||
/* reset the active item, otherwise we are stuck on
|
||||
* 'Other application…'
|
||||
*/
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (self), self->priv->last_active);
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox), priv->last_active);
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
return;
|
||||
}
|
||||
@@ -250,17 +257,18 @@ other_application_dialog_response_cb (GtkDialog *dialog,
|
||||
static void
|
||||
other_application_item_activated_cb (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkWidget *dialog, *widget;
|
||||
GtkWindow *toplevel;
|
||||
|
||||
toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (self)));
|
||||
dialog = gtk_app_chooser_dialog_new_for_content_type (toplevel,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
self->priv->content_type);
|
||||
priv->content_type);
|
||||
|
||||
gtk_window_set_modal (GTK_WINDOW (dialog), gtk_window_get_modal (toplevel));
|
||||
gtk_app_chooser_dialog_set_heading (GTK_APP_CHOOSER_DIALOG (dialog),
|
||||
self->priv->heading);
|
||||
priv->heading);
|
||||
|
||||
widget = gtk_app_chooser_dialog_get_widget (GTK_APP_CHOOSER_DIALOG (dialog));
|
||||
g_object_set (widget,
|
||||
@@ -277,20 +285,21 @@ static void
|
||||
gtk_app_chooser_button_ensure_dialog_item (GtkAppChooserButton *self,
|
||||
GtkTreeIter *prev_iter)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter, iter2;
|
||||
|
||||
if (!self->priv->show_dialog_item || !self->priv->content_type)
|
||||
if (!priv->show_dialog_item || !priv->content_type)
|
||||
return;
|
||||
|
||||
if (prev_iter == NULL)
|
||||
gtk_list_store_append (self->priv->store, &iter);
|
||||
gtk_list_store_append (priv->store, &iter);
|
||||
else
|
||||
gtk_list_store_insert_after (self->priv->store, &iter, prev_iter);
|
||||
gtk_list_store_insert_after (priv->store, &iter, prev_iter);
|
||||
|
||||
real_insert_separator (self, FALSE, &iter);
|
||||
iter2 = iter;
|
||||
|
||||
gtk_list_store_insert_after (self->priv->store, &iter, &iter2);
|
||||
gtk_list_store_insert_after (priv->store, &iter, &iter2);
|
||||
real_insert_custom_item (self, CUSTOM_ITEM_OTHER_APP,
|
||||
_("Other application…"), NULL,
|
||||
FALSE, &iter);
|
||||
@@ -301,6 +310,7 @@ insert_one_application (GtkAppChooserButton *self,
|
||||
GAppInfo *app,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GIcon *icon;
|
||||
|
||||
icon = g_app_info_get_icon (app);
|
||||
@@ -310,7 +320,7 @@ insert_one_application (GtkAppChooserButton *self,
|
||||
else
|
||||
g_object_ref (icon);
|
||||
|
||||
gtk_list_store_set (self->priv->store, iter,
|
||||
gtk_list_store_set (priv->store, iter,
|
||||
COLUMN_APP_INFO, app,
|
||||
COLUMN_LABEL, g_app_info_get_name (app),
|
||||
COLUMN_ICON, icon,
|
||||
@@ -323,25 +333,26 @@ insert_one_application (GtkAppChooserButton *self,
|
||||
static void
|
||||
gtk_app_chooser_button_populate (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GList *recommended_apps = NULL, *l;
|
||||
GAppInfo *app, *default_app = NULL;
|
||||
GtkTreeIter iter, iter2;
|
||||
gboolean cycled_recommended;
|
||||
|
||||
#ifndef G_OS_WIN32
|
||||
if (self->priv->content_type)
|
||||
recommended_apps = g_app_info_get_recommended_for_type (self->priv->content_type);
|
||||
if (priv->content_type)
|
||||
recommended_apps = g_app_info_get_recommended_for_type (priv->content_type);
|
||||
#endif
|
||||
cycled_recommended = FALSE;
|
||||
|
||||
if (self->priv->show_default_item)
|
||||
if (priv->show_default_item)
|
||||
{
|
||||
if (self->priv->content_type)
|
||||
default_app = g_app_info_get_default_for_type (self->priv->content_type, FALSE);
|
||||
if (priv->content_type)
|
||||
default_app = g_app_info_get_default_for_type (priv->content_type, FALSE);
|
||||
|
||||
if (default_app != NULL)
|
||||
{
|
||||
get_first_iter (self->priv->store, &iter);
|
||||
get_first_iter (priv->store, &iter);
|
||||
cycled_recommended = TRUE;
|
||||
|
||||
insert_one_application (self, default_app, &iter);
|
||||
@@ -359,12 +370,12 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
|
||||
|
||||
if (cycled_recommended)
|
||||
{
|
||||
gtk_list_store_insert_after (self->priv->store, &iter2, &iter);
|
||||
gtk_list_store_insert_after (priv->store, &iter2, &iter);
|
||||
iter = iter2;
|
||||
}
|
||||
else
|
||||
{
|
||||
get_first_iter (self->priv->store, &iter);
|
||||
get_first_iter (priv->store, &iter);
|
||||
cycled_recommended = TRUE;
|
||||
}
|
||||
|
||||
@@ -379,21 +390,22 @@ gtk_app_chooser_button_populate (GtkAppChooserButton *self)
|
||||
else
|
||||
gtk_app_chooser_button_ensure_dialog_item (self, &iter);
|
||||
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (self), 0);
|
||||
gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combobox), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkCellRenderer *cell;
|
||||
GtkCellArea *area;
|
||||
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (self),
|
||||
GTK_TREE_MODEL (self->priv->store));
|
||||
gtk_combo_box_set_model (GTK_COMBO_BOX (priv->combobox),
|
||||
GTK_TREE_MODEL (priv->store));
|
||||
|
||||
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (self));
|
||||
area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (priv->combobox));
|
||||
|
||||
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (self),
|
||||
gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (priv->combobox),
|
||||
row_separator_func, NULL, NULL);
|
||||
|
||||
cell = gtk_cell_renderer_pixbuf_new ();
|
||||
@@ -402,7 +414,7 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
|
||||
"expand", FALSE,
|
||||
"fixed-size", FALSE,
|
||||
NULL);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combobox), cell,
|
||||
"gicon", COLUMN_ICON,
|
||||
NULL);
|
||||
|
||||
@@ -411,7 +423,7 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
|
||||
"align", FALSE,
|
||||
"expand", TRUE,
|
||||
NULL);
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (self), cell,
|
||||
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->combobox), cell,
|
||||
"text", COLUMN_LABEL,
|
||||
NULL);
|
||||
|
||||
@@ -421,11 +433,12 @@ gtk_app_chooser_button_build_ui (GtkAppChooserButton *self)
|
||||
static void
|
||||
gtk_app_chooser_button_remove_non_custom (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
gboolean custom, res;
|
||||
|
||||
model = GTK_TREE_MODEL (self->priv->store);
|
||||
model = GTK_TREE_MODEL (priv->store);
|
||||
|
||||
if (!gtk_tree_model_get_iter_first (model, &iter))
|
||||
return;
|
||||
@@ -442,9 +455,11 @@ gtk_app_chooser_button_remove_non_custom (GtkAppChooserButton *self)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_button_changed (GtkComboBox *object)
|
||||
gtk_app_chooser_button_changed (GtkComboBox *object,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (object);
|
||||
GtkAppChooserButton *self = user_data;
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
gchar *name = NULL;
|
||||
gboolean custom;
|
||||
@@ -453,7 +468,7 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
|
||||
if (!gtk_combo_box_get_active_iter (object, &iter))
|
||||
return;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
|
||||
COLUMN_NAME, &name,
|
||||
COLUMN_CUSTOM, &custom,
|
||||
-1);
|
||||
@@ -464,7 +479,7 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
|
||||
{
|
||||
name_quark = g_quark_from_string (name);
|
||||
g_signal_emit (self, signals[SIGNAL_CUSTOM_ITEM_ACTIVATED], name_quark, name);
|
||||
self->priv->last_active = gtk_combo_box_get_active (object);
|
||||
priv->last_active = gtk_combo_box_get_active (object);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -475,7 +490,9 @@ gtk_app_chooser_button_changed (GtkComboBox *object)
|
||||
g_free (name);
|
||||
}
|
||||
else
|
||||
self->priv->last_active = gtk_combo_box_get_active (object);
|
||||
priv->last_active = gtk_combo_box_get_active (object);
|
||||
|
||||
g_signal_emit (self, signals[SIGNAL_CHANGED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -491,13 +508,14 @@ static GAppInfo *
|
||||
gtk_app_chooser_button_get_app_info (GtkAppChooser *object)
|
||||
{
|
||||
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (object);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
GAppInfo *info;
|
||||
|
||||
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (self), &iter))
|
||||
if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (priv->combobox), &iter))
|
||||
return NULL;
|
||||
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
|
||||
COLUMN_APP_INFO, &info,
|
||||
-1);
|
||||
|
||||
@@ -522,11 +540,12 @@ gtk_app_chooser_button_set_property (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CONTENT_TYPE:
|
||||
self->priv->content_type = g_value_dup_string (value);
|
||||
priv->content_type = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_SHOW_DIALOG_ITEM:
|
||||
gtk_app_chooser_button_set_show_dialog_item (self, g_value_get_boolean (value));
|
||||
@@ -550,20 +569,21 @@ gtk_app_chooser_button_get_property (GObject *obj,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_CONTENT_TYPE:
|
||||
g_value_set_string (value, self->priv->content_type);
|
||||
g_value_set_string (value, priv->content_type);
|
||||
break;
|
||||
case PROP_SHOW_DIALOG_ITEM:
|
||||
g_value_set_boolean (value, self->priv->show_dialog_item);
|
||||
g_value_set_boolean (value, priv->show_dialog_item);
|
||||
break;
|
||||
case PROP_SHOW_DEFAULT_ITEM:
|
||||
g_value_set_boolean (value, self->priv->show_default_item);
|
||||
g_value_set_boolean (value, priv->show_default_item);
|
||||
break;
|
||||
case PROP_HEADING:
|
||||
g_value_set_string (value, self->priv->heading);
|
||||
g_value_set_string (value, priv->heading);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
|
||||
@@ -575,15 +595,46 @@ static void
|
||||
gtk_app_chooser_button_finalize (GObject *obj)
|
||||
{
|
||||
GtkAppChooserButton *self = GTK_APP_CHOOSER_BUTTON (obj);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_hash_table_destroy (self->priv->custom_item_names);
|
||||
g_free (self->priv->content_type);
|
||||
g_free (self->priv->heading);
|
||||
g_object_unref (self->priv->store);
|
||||
g_hash_table_destroy (priv->custom_item_names);
|
||||
g_free (priv->content_type);
|
||||
g_free (priv->heading);
|
||||
g_object_unref (priv->store);
|
||||
gtk_widget_unparent (priv->combobox);
|
||||
|
||||
G_OBJECT_CLASS (gtk_app_chooser_button_parent_class)->finalize (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_button_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum,
|
||||
int *natural,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
GtkAppChooserButton *button = GTK_APP_CHOOSER_BUTTON (widget);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (button);
|
||||
|
||||
gtk_widget_measure (priv->combobox, orientation, for_size,
|
||||
minimum, natural,
|
||||
minimum_baseline, natural_baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_button_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkAppChooserButton *button = GTK_APP_CHOOSER_BUTTON (widget);
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (button);
|
||||
|
||||
gtk_widget_size_allocate (priv->combobox, &(GtkAllocation){0, 0, width, height}, baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
app_chooser_iface_init (GtkAppChooserIface *iface)
|
||||
{
|
||||
@@ -595,14 +646,15 @@ static void
|
||||
gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
|
||||
{
|
||||
GObjectClass *oclass = G_OBJECT_CLASS (klass);
|
||||
GtkComboBoxClass *combo_class = GTK_COMBO_BOX_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
oclass->set_property = gtk_app_chooser_button_set_property;
|
||||
oclass->get_property = gtk_app_chooser_button_get_property;
|
||||
oclass->finalize = gtk_app_chooser_button_finalize;
|
||||
oclass->constructed = gtk_app_chooser_button_constructed;
|
||||
|
||||
combo_class->changed = gtk_app_chooser_button_changed;
|
||||
widget_class->measure = gtk_app_chooser_button_measure;
|
||||
widget_class->size_allocate = gtk_app_chooser_button_size_allocate;
|
||||
|
||||
g_object_class_override_property (oclass, PROP_CONTENT_TYPE, "content-type");
|
||||
|
||||
@@ -649,6 +701,16 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
|
||||
|
||||
g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
|
||||
|
||||
signals[SIGNAL_CHANGED] =
|
||||
g_signal_new (I_("changed"),
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GtkAppChooserButtonClass, changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
|
||||
/**
|
||||
* GtkAppChooserButton::custom-item-activated:
|
||||
* @self: the object which received the signal
|
||||
@@ -667,21 +729,29 @@ gtk_app_chooser_button_class_init (GtkAppChooserButtonClass *klass)
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
1, G_TYPE_STRING);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_button_init (GtkAppChooserButton *self)
|
||||
{
|
||||
self->priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
self->priv->custom_item_names =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
self->priv->store = gtk_list_store_new (NUM_COLUMNS,
|
||||
G_TYPE_APP_INFO,
|
||||
G_TYPE_STRING, /* name */
|
||||
G_TYPE_STRING, /* label */
|
||||
G_TYPE_ICON,
|
||||
G_TYPE_BOOLEAN, /* separator */
|
||||
G_TYPE_BOOLEAN); /* custom */
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
|
||||
|
||||
priv->custom_item_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
priv->store = gtk_list_store_new (NUM_COLUMNS,
|
||||
G_TYPE_APP_INFO,
|
||||
G_TYPE_STRING, /* name */
|
||||
G_TYPE_STRING, /* label */
|
||||
G_TYPE_ICON,
|
||||
G_TYPE_BOOLEAN, /* separator */
|
||||
G_TYPE_BOOLEAN); /* custom */
|
||||
priv->combobox = gtk_combo_box_new_with_model (GTK_TREE_MODEL (priv->store));
|
||||
gtk_widget_set_parent (priv->combobox, GTK_WIDGET (self));
|
||||
|
||||
g_signal_connect (priv->combobox, "changed",
|
||||
G_CALLBACK (gtk_app_chooser_button_changed), self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -689,14 +759,15 @@ app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self,
|
||||
const gchar *name,
|
||||
GtkTreeIter *set_me)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
gchar *custom_name = NULL;
|
||||
|
||||
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (self->priv->store), &iter))
|
||||
if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter))
|
||||
return FALSE;
|
||||
|
||||
do {
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->store), &iter,
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
|
||||
COLUMN_NAME, &custom_name,
|
||||
-1);
|
||||
|
||||
@@ -709,7 +780,7 @@ app_chooser_button_iter_from_custom_name (GtkAppChooserButton *self,
|
||||
}
|
||||
|
||||
g_free (custom_name);
|
||||
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (self->priv->store), &iter));
|
||||
} while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -722,20 +793,21 @@ real_insert_custom_item (GtkAppChooserButton *self,
|
||||
gboolean custom,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
if (custom)
|
||||
{
|
||||
if (g_hash_table_lookup (self->priv->custom_item_names, name) != NULL)
|
||||
if (g_hash_table_lookup (priv->custom_item_names, name) != NULL)
|
||||
{
|
||||
g_warning ("Attempting to add custom item %s to GtkAppChooserButton, "
|
||||
"when there's already an item with the same name", name);
|
||||
return;
|
||||
}
|
||||
|
||||
g_hash_table_insert (self->priv->custom_item_names,
|
||||
g_hash_table_insert (priv->custom_item_names,
|
||||
g_strdup (name), GINT_TO_POINTER (1));
|
||||
}
|
||||
|
||||
gtk_list_store_set (self->priv->store, iter,
|
||||
gtk_list_store_set (priv->store, iter,
|
||||
COLUMN_NAME, name,
|
||||
COLUMN_LABEL, label,
|
||||
COLUMN_ICON, icon,
|
||||
@@ -749,7 +821,9 @@ real_insert_separator (GtkAppChooserButton *self,
|
||||
gboolean custom,
|
||||
GtkTreeIter *iter)
|
||||
{
|
||||
gtk_list_store_set (self->priv->store, iter,
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
gtk_list_store_set (priv->store, iter,
|
||||
COLUMN_CUSTOM, custom,
|
||||
COLUMN_SEPARATOR, TRUE,
|
||||
-1);
|
||||
@@ -784,11 +858,12 @@ gtk_app_chooser_button_new (const gchar *content_type)
|
||||
void
|
||||
gtk_app_chooser_button_append_separator (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
|
||||
|
||||
gtk_list_store_append (self->priv->store, &iter);
|
||||
gtk_list_store_append (priv->store, &iter);
|
||||
real_insert_separator (self, TRUE, &iter);
|
||||
}
|
||||
|
||||
@@ -812,12 +887,13 @@ gtk_app_chooser_button_append_custom_item (GtkAppChooserButton *self,
|
||||
const gchar *label,
|
||||
GIcon *icon)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
gtk_list_store_append (self->priv->store, &iter);
|
||||
gtk_list_store_append (priv->store, &iter);
|
||||
real_insert_custom_item (self, name, label, icon, TRUE, &iter);
|
||||
}
|
||||
|
||||
@@ -836,19 +912,20 @@ void
|
||||
gtk_app_chooser_button_set_active_custom_item (GtkAppChooserButton *self,
|
||||
const gchar *name)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
if (!g_hash_table_contains (self->priv->custom_item_names, name) ||
|
||||
if (!g_hash_table_contains (priv->custom_item_names, name) ||
|
||||
!app_chooser_button_iter_from_custom_name (self, name, &iter))
|
||||
{
|
||||
g_warning ("Can't find the item named %s in the app chooser.", name);
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self), &iter);
|
||||
gtk_combo_box_set_active_iter (GTK_COMBO_BOX (priv->combobox), &iter);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -863,9 +940,11 @@ gtk_app_chooser_button_set_active_custom_item (GtkAppChooserButton *self,
|
||||
gboolean
|
||||
gtk_app_chooser_button_get_show_dialog_item (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), FALSE);
|
||||
|
||||
return self->priv->show_dialog_item;
|
||||
return priv->show_dialog_item;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -880,9 +959,10 @@ void
|
||||
gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self,
|
||||
gboolean setting)
|
||||
{
|
||||
if (self->priv->show_dialog_item != setting)
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
if (priv->show_dialog_item != setting)
|
||||
{
|
||||
self->priv->show_dialog_item = setting;
|
||||
priv->show_dialog_item = setting;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_DIALOG_ITEM]);
|
||||
|
||||
@@ -902,9 +982,11 @@ gtk_app_chooser_button_set_show_dialog_item (GtkAppChooserButton *self,
|
||||
gboolean
|
||||
gtk_app_chooser_button_get_show_default_item (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), FALSE);
|
||||
|
||||
return self->priv->show_default_item;
|
||||
return priv->show_default_item;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -919,9 +1001,13 @@ void
|
||||
gtk_app_chooser_button_set_show_default_item (GtkAppChooserButton *self,
|
||||
gboolean setting)
|
||||
{
|
||||
if (self->priv->show_default_item != setting)
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
|
||||
|
||||
if (priv->show_default_item != setting)
|
||||
{
|
||||
self->priv->show_default_item = setting;
|
||||
priv->show_default_item = setting;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_DEFAULT_ITEM]);
|
||||
|
||||
@@ -941,10 +1027,12 @@ void
|
||||
gtk_app_chooser_button_set_heading (GtkAppChooserButton *self,
|
||||
const gchar *heading)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_return_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self));
|
||||
|
||||
g_free (self->priv->heading);
|
||||
self->priv->heading = g_strdup (heading);
|
||||
g_free (priv->heading);
|
||||
priv->heading = g_strdup (heading);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_HEADING]);
|
||||
}
|
||||
@@ -961,7 +1049,9 @@ gtk_app_chooser_button_set_heading (GtkAppChooserButton *self,
|
||||
const gchar *
|
||||
gtk_app_chooser_button_get_heading (GtkAppChooserButton *self)
|
||||
{
|
||||
GtkAppChooserButtonPrivate *priv = gtk_app_chooser_button_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_APP_CHOOSER_BUTTON (self), NULL);
|
||||
|
||||
return self->priv->heading;
|
||||
return priv->heading;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* gtkappchooserbutton.h: an app-chooser combobox
|
||||
* gtkappchooserbutton.h: an app-chooser button
|
||||
*
|
||||
* Copyright (C) 2010 Red Hat, Inc.
|
||||
*
|
||||
@@ -26,7 +26,7 @@
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkcombobox.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -40,13 +40,9 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkAppChooserButton GtkAppChooserButton;
|
||||
typedef struct _GtkAppChooserButtonClass GtkAppChooserButtonClass;
|
||||
typedef struct _GtkAppChooserButtonPrivate GtkAppChooserButtonPrivate;
|
||||
|
||||
struct _GtkAppChooserButton {
|
||||
GtkComboBox parent;
|
||||
|
||||
/*< private >*/
|
||||
GtkAppChooserButtonPrivate *priv;
|
||||
GtkWidget parent_instance;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -57,10 +53,11 @@ struct _GtkAppChooserButton {
|
||||
* is activated from the dropdown menu.
|
||||
*/
|
||||
struct _GtkAppChooserButtonClass {
|
||||
GtkComboBoxClass parent_class;
|
||||
GtkWidgetClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
|
||||
void (* changed) (GtkAppChooserButton *self);
|
||||
void (* custom_item_activated) (GtkAppChooserButton *self,
|
||||
const gchar *item_name);
|
||||
|
||||
|
||||
@@ -934,16 +934,21 @@ gtk_app_chooser_widget_snapshot (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_app_chooser_widget_size_allocate (GtkWidget *widget,
|
||||
const GtkAllocation *allocation,
|
||||
gtk_app_chooser_widget_size_allocate (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkAppChooserWidget *self = GTK_APP_CHOOSER_WIDGET (widget);
|
||||
GtkAppChooserWidgetPrivate *priv = gtk_app_chooser_widget_get_instance_private (self);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_app_chooser_widget_parent_class)->size_allocate (widget, allocation, baseline);
|
||||
GTK_WIDGET_CLASS (gtk_app_chooser_widget_parent_class)->size_allocate (widget, width, height, baseline);
|
||||
|
||||
gtk_widget_size_allocate (priv->overlay, allocation, baseline);
|
||||
gtk_widget_size_allocate (priv->overlay,
|
||||
&(GtkAllocation) {
|
||||
0, 0,
|
||||
width, height
|
||||
},baseline);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
+148
-10
@@ -24,9 +24,13 @@
|
||||
|
||||
#include "gtkapplicationprivate.h"
|
||||
#include "gtksettings.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLICATION_IMPL)
|
||||
|
||||
#define DBUS_BUS_NAME "org.freedesktop.DBus"
|
||||
#define DBUS_OBJECT_PATH "/org/freedesktop/DBus"
|
||||
#define DBUS_BUS_INTERFACE "org.freedesktop.DBus"
|
||||
#define GNOME_DBUS_NAME "org.gnome.SessionManager"
|
||||
#define GNOME_DBUS_OBJECT_PATH "/org/gnome/SessionManager"
|
||||
#define GNOME_DBUS_INTERFACE "org.gnome.SessionManager"
|
||||
@@ -35,6 +39,9 @@ G_DEFINE_TYPE (GtkApplicationImplDBus, gtk_application_impl_dbus, GTK_TYPE_APPLI
|
||||
#define XFCE_DBUS_OBJECT_PATH "/org/xfce/SessionManager"
|
||||
#define XFCE_DBUS_INTERFACE "org.xfce.Session.Manager"
|
||||
#define XFCE_DBUS_CLIENT_INTERFACE "org.xfce.Session.Client"
|
||||
#define GNOME_SCREENSAVER_DBUS_NAME "org.gnome.ScreenSaver"
|
||||
#define GNOME_SCREENSAVER_DBUS_OBJECT_PATH "/org/gnome/ScreenSaver"
|
||||
#define GNOME_SCREENSAVER_DBUS_INTERFACE "org.gnome.ScreenSaver"
|
||||
|
||||
static void
|
||||
unregister_client (GtkApplicationImplDBus *dbus)
|
||||
@@ -171,6 +178,63 @@ stash_desktop_autostart_id (void)
|
||||
g_unsetenv ("DESKTOP_AUTOSTART_ID");
|
||||
}
|
||||
|
||||
static void
|
||||
screensaver_signal_session (GDBusProxy *proxy,
|
||||
const char *sender_name,
|
||||
const char *signal_name,
|
||||
GVariant *parameters,
|
||||
GtkApplication *application)
|
||||
{
|
||||
gboolean active;
|
||||
|
||||
if (!g_str_equal (signal_name, "ActiveChanged"))
|
||||
return;
|
||||
|
||||
g_variant_get (parameters, "(b)", &active);
|
||||
gtk_application_set_screensaver_active (application, active);
|
||||
}
|
||||
|
||||
static void
|
||||
screensaver_signal_portal (GDBusConnection *connection,
|
||||
const char *sender_name,
|
||||
const char *object_path,
|
||||
const char *interface_name,
|
||||
const char *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer data)
|
||||
{
|
||||
GtkApplication *application = data;
|
||||
gboolean active;
|
||||
GVariant *state;
|
||||
|
||||
if (!g_str_equal (signal_name, "StateChanged"))
|
||||
return;
|
||||
|
||||
g_variant_get (parameters, "(o@a{sv})", NULL, &state);
|
||||
g_variant_lookup (state, "screensaver-active", "b", &active);
|
||||
gtk_application_set_screensaver_active (application, active);
|
||||
}
|
||||
|
||||
static void
|
||||
create_monitor_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GDBusProxy *proxy = G_DBUS_PROXY (source);
|
||||
GError *error = NULL;
|
||||
GVariant *ret = NULL;
|
||||
|
||||
ret = g_dbus_proxy_call_finish (proxy, result, &error);
|
||||
if (ret == NULL)
|
||||
{
|
||||
g_warning ("Creating a portal monitor failed: %s", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_unref (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
|
||||
gboolean register_session)
|
||||
@@ -195,6 +259,9 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
|
||||
dbus->object_path = g_application_get_dbus_object_path (G_APPLICATION (impl->application));
|
||||
dbus->unique_name = g_dbus_connection_get_unique_name (dbus->session);
|
||||
|
||||
if (gdk_should_use_portal ())
|
||||
goto out;
|
||||
|
||||
g_debug ("Connecting to session manager");
|
||||
|
||||
/* Try the GNOME session manager first */
|
||||
@@ -236,6 +303,27 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
|
||||
if (!register_session)
|
||||
goto out;
|
||||
|
||||
dbus->ss_proxy = gtk_application_get_proxy_if_service_present (dbus->session,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
GNOME_SCREENSAVER_DBUS_NAME,
|
||||
GNOME_SCREENSAVER_DBUS_OBJECT_PATH,
|
||||
GNOME_SCREENSAVER_DBUS_INTERFACE,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_debug ("Failed to get the GNOME screensaver proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&dbus->ss_proxy);
|
||||
}
|
||||
|
||||
if (dbus->ss_proxy)
|
||||
{
|
||||
g_signal_connect (dbus->ss_proxy, "g-signal",
|
||||
G_CALLBACK (screensaver_signal_session), impl->application);
|
||||
}
|
||||
|
||||
g_debug ("Registering client '%s' '%s'", dbus->application_id, client_id);
|
||||
|
||||
res = g_dbus_proxy_call_sync (dbus->sm_proxy,
|
||||
@@ -304,9 +392,9 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
|
||||
if (id && id[0])
|
||||
{
|
||||
res = g_dbus_connection_call_sync (dbus->session,
|
||||
"org.freedesktop.DBus",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.DBus",
|
||||
DBUS_BUS_NAME,
|
||||
DBUS_OBJECT_PATH,
|
||||
DBUS_BUS_INTERFACE,
|
||||
"GetId",
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -336,18 +424,51 @@ gtk_application_impl_dbus_startup (GtkApplicationImpl *impl,
|
||||
"gtk-shell-shows-menubar", FALSE,
|
||||
NULL);
|
||||
|
||||
if (dbus->sm_proxy == NULL)
|
||||
if (dbus->sm_proxy == NULL && dbus->session)
|
||||
{
|
||||
dbus->inhibit_proxy = gtk_application_get_proxy_if_service_present (dbus->session,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Inhibit",
|
||||
PORTAL_BUS_NAME,
|
||||
PORTAL_OBJECT_PATH,
|
||||
PORTAL_INHIBIT_INTERFACE,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_debug ("Failed to get an inhibit portal proxy: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (register_session)
|
||||
{
|
||||
char *token;
|
||||
GVariantBuilder opt_builder;
|
||||
|
||||
/* Monitor screensaver state */
|
||||
|
||||
dbus->session_id = gtk_get_portal_session_path (dbus->session, &token);
|
||||
dbus->state_changed_handler =
|
||||
g_dbus_connection_signal_subscribe (dbus->session,
|
||||
PORTAL_BUS_NAME,
|
||||
PORTAL_INHIBIT_INTERFACE,
|
||||
"StateChanged",
|
||||
PORTAL_OBJECT_PATH,
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
|
||||
screensaver_signal_portal,
|
||||
impl->application,
|
||||
NULL);
|
||||
g_variant_builder_init (&opt_builder, G_VARIANT_TYPE_VARDICT);
|
||||
g_variant_builder_add (&opt_builder, "{sv}",
|
||||
"session_handle_token", g_variant_new_string (token));
|
||||
g_dbus_proxy_call (dbus->inhibit_proxy,
|
||||
"CreateMonitor",
|
||||
g_variant_new ("(sa{sv})", "", &opt_builder),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
G_MAXINT,
|
||||
NULL,
|
||||
create_monitor_cb, dbus);
|
||||
g_free (token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,7 +631,7 @@ gtk_application_impl_dbus_inhibit (GtkApplicationImpl *impl,
|
||||
g_variant_new ("(s@usu)",
|
||||
dbus->application_id,
|
||||
window ? gtk_application_impl_dbus_get_window_system_id (dbus, window) : g_variant_new_uint32 (0),
|
||||
reason,
|
||||
reason ? reason : "",
|
||||
flags),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
G_MAXINT,
|
||||
@@ -608,9 +729,9 @@ gtk_application_impl_dbus_uninhibit (GtkApplicationImpl *impl,
|
||||
if (handle->cookie == cookie)
|
||||
{
|
||||
g_dbus_connection_call (dbus->session,
|
||||
"org.freedesktop.portal.Desktop",
|
||||
PORTAL_BUS_NAME,
|
||||
handle->handle,
|
||||
"org.freedesktop.portal.Request",
|
||||
PORTAL_REQUEST_INTERFACE,
|
||||
"Close",
|
||||
g_variant_new ("()"),
|
||||
G_VARIANT_TYPE_UNIT,
|
||||
@@ -667,11 +788,28 @@ gtk_application_impl_dbus_finalize (GObject *object)
|
||||
{
|
||||
GtkApplicationImplDBus *dbus = (GtkApplicationImplDBus *) object;
|
||||
|
||||
if (dbus->session_id)
|
||||
{
|
||||
g_dbus_connection_call (dbus->session,
|
||||
PORTAL_BUS_NAME,
|
||||
dbus->session_id,
|
||||
PORTAL_SESSION_INTERFACE,
|
||||
"Close",
|
||||
NULL, NULL, 0, -1, NULL, NULL, NULL);
|
||||
|
||||
g_free (dbus->session_id);
|
||||
}
|
||||
|
||||
if (dbus->state_changed_handler)
|
||||
g_dbus_connection_signal_unsubscribe (dbus->session,
|
||||
dbus->state_changed_handler);
|
||||
|
||||
g_clear_object (&dbus->inhibit_proxy);
|
||||
g_slist_free_full (dbus->inhibit_handles, inhibit_handle_free);
|
||||
g_free (dbus->app_menu_path);
|
||||
g_free (dbus->menubar_path);
|
||||
g_clear_object (&dbus->sm_proxy);
|
||||
g_clear_object (&dbus->ss_proxy);
|
||||
|
||||
G_OBJECT_CLASS (gtk_application_impl_dbus_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
+39
-2
@@ -137,6 +137,7 @@ static guint gtk_application_signals[LAST_SIGNAL];
|
||||
enum {
|
||||
PROP_ZERO,
|
||||
PROP_REGISTER_SESSION,
|
||||
PROP_SCREENSAVER_ACTIVE,
|
||||
PROP_APP_MENU,
|
||||
PROP_MENUBAR,
|
||||
PROP_ACTIVE_WINDOW,
|
||||
@@ -157,6 +158,7 @@ typedef struct
|
||||
guint last_window_id;
|
||||
|
||||
gboolean register_session;
|
||||
gboolean screensaver_active;
|
||||
GtkActionMuxer *muxer;
|
||||
GtkBuilder *menus_builder;
|
||||
gchar *help_overlay_path;
|
||||
@@ -385,8 +387,6 @@ gtk_application_init (GtkApplication *application)
|
||||
{
|
||||
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
|
||||
|
||||
priv = gtk_application_get_instance_private (application);
|
||||
|
||||
priv->muxer = gtk_action_muxer_new ();
|
||||
|
||||
priv->accels = gtk_application_accels_new ();
|
||||
@@ -534,6 +534,10 @@ gtk_application_get_property (GObject *object,
|
||||
g_value_set_boolean (value, priv->register_session);
|
||||
break;
|
||||
|
||||
case PROP_SCREENSAVER_ACTIVE:
|
||||
g_value_set_boolean (value, priv->screensaver_active);
|
||||
break;
|
||||
|
||||
case PROP_APP_MENU:
|
||||
g_value_set_object (value, gtk_application_get_app_menu (application));
|
||||
break;
|
||||
@@ -653,6 +657,8 @@ gtk_application_class_init (GtkApplicationClass *class)
|
||||
* GtkApplication:register-session:
|
||||
*
|
||||
* Set this property to %TRUE to register with the session manager.
|
||||
* This will make GTK+ track the session state (such as the
|
||||
* #GtkApplication::screensaver-active property).
|
||||
*/
|
||||
gtk_application_props[PROP_REGISTER_SESSION] =
|
||||
g_param_spec_boolean ("register-session",
|
||||
@@ -661,6 +667,24 @@ gtk_application_class_init (GtkApplicationClass *class)
|
||||
FALSE,
|
||||
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GtkApplication:screensaver-active:
|
||||
*
|
||||
* This property is %TRUE if GTK+ believes that the screensaver is
|
||||
* currently active. GTK+ only tracks session state (including this)
|
||||
* when #GtkApplication::register-session is set to %TRUE.
|
||||
*
|
||||
* Tracking the screensaver state is supported on Linux.
|
||||
*
|
||||
* Since: 3.24
|
||||
*/
|
||||
gtk_application_props[PROP_SCREENSAVER_ACTIVE] =
|
||||
g_param_spec_boolean ("screensaver-active",
|
||||
P_("Screensaver Active"),
|
||||
P_("Whether the screensaver is active"),
|
||||
FALSE,
|
||||
G_PARAM_READABLE|G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gtk_application_props[PROP_APP_MENU] =
|
||||
g_param_spec_object ("app-menu",
|
||||
P_("Application menu"),
|
||||
@@ -1370,3 +1394,16 @@ gtk_application_get_menu_by_id (GtkApplication *application,
|
||||
|
||||
return G_MENU (object);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_application_set_screensaver_active (GtkApplication *application,
|
||||
gboolean active)
|
||||
{
|
||||
GtkApplicationPrivate *priv = gtk_application_get_instance_private (application);
|
||||
|
||||
if (priv->screensaver_active != active)
|
||||
{
|
||||
priv->screensaver_active = active;
|
||||
g_object_notify (G_OBJECT (application), "screensaver-active");
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user