Compare commits
478 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd06452b0f | |||
| 4e166f39fe | |||
| 5f79958716 | |||
| aee0af34af | |||
| 7e32eb2e98 | |||
| 7ea7d5c390 | |||
| e3e9dda429 | |||
| a3ab25bf1d | |||
| 095dec9238 | |||
| 0e34365139 | |||
| 88a62564f1 | |||
| 6ac94dc5c3 | |||
| 5a9a0874bd | |||
| 91992111c3 | |||
| 120d874805 | |||
| 9454bad891 | |||
| 9cb410fd9b | |||
| 0f3fbed13c | |||
| 43ee9746bd | |||
| 7283c5c22f | |||
| 8b71fe4af6 | |||
| b627fb5970 | |||
| be3ad1ef99 | |||
| 54264a9f78 | |||
| 65380c66bd | |||
| 8c96991ce0 | |||
| 07a44993ac | |||
| 60d2d25463 | |||
| 907f99b176 | |||
| ce6aa73c64 | |||
| 257bef85d0 | |||
| a48df87a85 | |||
| fe4cd7cf0f | |||
| 229b34d478 | |||
| 1985f2c9ad | |||
| 01d57a7566 | |||
| 7a4b2c10c7 | |||
| 208b2d37b6 | |||
| ef98912779 | |||
| b1e3b18ede | |||
| 0194cadbc0 | |||
| b4dfc4adfc | |||
| fd556ec377 | |||
| 1dbc1d67f5 | |||
| 8790c83a76 | |||
| 6b202fb838 | |||
| f69476435f | |||
| 8df6e2cdaf | |||
| 2861ab38ac | |||
| 23c2122c13 | |||
| 5b83ffa4a0 | |||
| cf8e3157a7 | |||
| 7323172755 | |||
| cfee8f4b11 | |||
| 7ae099c94c | |||
| 42298d8ab1 | |||
| 68912698f1 | |||
| c8c56f8d42 | |||
| 7f48b5a05c | |||
| 1e5e977b37 | |||
| 62d44b6bc7 | |||
| 862afeffe0 | |||
| 92f9195015 | |||
| fc6e08082b | |||
| af7516b797 | |||
| 3f1821e372 | |||
| b569470b87 | |||
| f1a3235039 | |||
| 34e90005af | |||
| 4f1cc8ec6d | |||
| 5242205a65 | |||
| 59633a6781 | |||
| d82316edda | |||
| 0815640b22 | |||
| 26de2eae20 | |||
| 8fa358c4d4 | |||
| fc72449228 | |||
| 84a304e66e | |||
| ecf1b7c18a | |||
| a7c5b53f46 | |||
| 09736dde93 | |||
| 66c00dc9f3 | |||
| 3eacf8bd39 | |||
| 34e9ef9e78 | |||
| a5955106ea | |||
| ea0cfed735 | |||
| f312d1ee6a | |||
| 69b6f4cf4f | |||
| d7e1c377fe | |||
| cc17577763 | |||
| ef4ae61c66 | |||
| e04ea3f311 | |||
| 77a2cd4d8d | |||
| 0986981d1a | |||
| 913f850f83 | |||
| ed31da3730 | |||
| 428ff6c4ab | |||
| 53786841cc | |||
| 8f8ece44a8 | |||
| 41a892b958 | |||
| b494ed5876 | |||
| 7b589f991d | |||
| d83faf82d7 | |||
| cd46016238 | |||
| f2a3218455 | |||
| 85b1959714 | |||
| b23600ae4b | |||
| bdc43b8fca | |||
| da2ef6911f | |||
| 0626246367 | |||
| 0edfafdfdf | |||
| 1863b79fb3 | |||
| 9aa90f8df0 | |||
| 8080d9e7c1 | |||
| f432ee775f | |||
| 77f9cb11a9 | |||
| d92e3cb864 | |||
| 733fa156b9 | |||
| d181d53762 | |||
| 644e6f8ebe | |||
| 0b4c695d65 | |||
| 448287bd58 | |||
| 5e6aff69c6 | |||
| d88e616711 | |||
| 0e5c94a094 | |||
| bb0aeec99c | |||
| 880e3ef289 | |||
| 94a09263d7 | |||
| ab9106ac89 | |||
| ff6451a77e | |||
| 4f2d63b8ac | |||
| 81c97f0910 | |||
| d1b52cc292 | |||
| ddedb39329 | |||
| d45987e637 | |||
| b95eceea60 | |||
| 2774e80fc4 | |||
| 7c207c4868 | |||
| c6c8abcf21 | |||
| a59c967675 | |||
| c3329f5fcc | |||
| 4f06e46759 | |||
| 7e522a8c55 | |||
| d9447fd2e7 | |||
| 95214f3697 | |||
| fe64c998f8 | |||
| 84582ad762 | |||
| fcc7a58058 | |||
| 8a48becb7e | |||
| 465446430e | |||
| 4060c43ae7 | |||
| 4ec9a2a330 | |||
| 90c017a762 | |||
| e011434223 | |||
| b1ccb4103d | |||
| 8033809f8b | |||
| 66ba1f76ba | |||
| 0ca822c716 | |||
| 4ac288c1b4 | |||
| 64316ab185 | |||
| 4d90a693ae | |||
| 0c5f943783 | |||
| 42fc165b94 | |||
| 20a4e3f351 | |||
| f3f90e1d71 | |||
| b018da2acd | |||
| ab5f3f59ce | |||
| 0127217e10 | |||
| 16a476fe22 | |||
| c8ca6930c5 | |||
| c4f33f36de | |||
| 0543c48862 | |||
| fcb17a86e6 | |||
| 5633b5b637 | |||
| f7eaf69d67 | |||
| 32411943ea | |||
| 58fa5d7617 | |||
| f9ee1967f4 | |||
| 6a376f0a30 | |||
| 66826c26db | |||
| 8d1e37789e | |||
| 6c39a5946e | |||
| 2a98928286 | |||
| c7806eb908 | |||
| 9015734e65 | |||
| f5159e1ecb | |||
| aec2f50d82 | |||
| 74860f7602 | |||
| a9175e0c03 | |||
| e1c56555af | |||
| 24120c8fd0 | |||
| f284331f79 | |||
| a82de96e1a | |||
| eba9b116ed | |||
| 1f89b3c7df | |||
| c739b9fe7f | |||
| 556b729b97 | |||
| 9fd5558acd | |||
| b7422c0f62 | |||
| ace684c7ab | |||
| 752e704e99 | |||
| 8c7e13746b | |||
| c2311c7154 | |||
| 44fa748826 | |||
| dfed398371 | |||
| 962ba49a8e | |||
| 5811e443f8 | |||
| f55e1392d4 | |||
| 0fbe5ba40c | |||
| 980ea63d78 | |||
| dcc3533363 | |||
| 28964aa0a4 | |||
| 7fd8a0ac99 | |||
| d919ed4e4b | |||
| 61ec6fb5eb | |||
| 237eb8bb90 | |||
| ff57cd9331 | |||
| c97d02f487 | |||
| 36ced69ebf | |||
| 427a52a9ad | |||
| 9b5aee0d1b | |||
| ee5afdf919 | |||
| 49a6b5d50a | |||
| dd7a0cbeb7 | |||
| 38d808f3e2 | |||
| 16a608b9e5 | |||
| f1ff37e970 | |||
| 71c68f5f36 | |||
| 0d3265edc7 | |||
| 854e40c60c | |||
| 882387a62a | |||
| 73f7370ead | |||
| 8e9241f3ba | |||
| 3c67931f5f | |||
| 06f3b5dfd4 | |||
| 05acb70d1c | |||
| 7b380b2ffc | |||
| f6e4b964b7 | |||
| 0b2d08f076 | |||
| 1ad1a9fe4a | |||
| fe15db92bd | |||
| 682b7773fc | |||
| 9055b6c6e5 | |||
| 9fd56dc5ad | |||
| 1ec7f2bbcd | |||
| 4eb7208e35 | |||
| 1ad88f7662 | |||
| 96b30073cf | |||
| 456956a2bd | |||
| 4c794505da | |||
| f627c9443e | |||
| 06fa9befe0 | |||
| a95dc5d609 | |||
| 2abe588e91 | |||
| ecdee288a7 | |||
| e363fcca3c | |||
| f46fb7c6fc | |||
| 985d964a34 | |||
| 2a0286c19c | |||
| 9a05af61e8 | |||
| 68d2e9c068 | |||
| 89ba937fd3 | |||
| 840cd6f10f | |||
| cccfc1a38d | |||
| ff26aa2fa7 | |||
| 7192e67a6f | |||
| 5354b91e64 | |||
| c9c6b7bb2a | |||
| c93fa922dc | |||
| 8d7bfa2628 | |||
| e6a4cc8ba2 | |||
| 7926ee68b8 | |||
| 239d47791d | |||
| 33f210bc85 | |||
| 021aae84dd | |||
| e8508762f5 | |||
| a0bbdfbeee | |||
| f6561fc401 | |||
| dfe56c8b70 | |||
| 7f29b466be | |||
| 8f5a185ae5 | |||
| 309b28fa2c | |||
| e9f311e6b6 | |||
| 045262282b | |||
| a44701faa2 | |||
| eeee3151b6 | |||
| 0cd077e80f | |||
| 0e9b098f4e | |||
| 40b5002338 | |||
| 28fd3fbf50 | |||
| 10c782b106 | |||
| 5dd1803288 | |||
| 7e9f2e2311 | |||
| 610a5d6c0d | |||
| 5453628491 | |||
| 6e0596e122 | |||
| 0ca8d74842 | |||
| 04f8170841 | |||
| 1124793702 | |||
| 8d4b0f05da | |||
| ca8ba8ce87 | |||
| 849e3403cd | |||
| 02a7a30978 | |||
| 79568d2944 | |||
| ae45be7875 | |||
| 73e8b39bc6 | |||
| 72b2938e43 | |||
| 785aaa8c03 | |||
| 1d7983da05 | |||
| cb652c7f0f | |||
| a2b84fc98a | |||
| 0d9bbc9d64 | |||
| 6fd5e5f61c | |||
| b7285bd688 | |||
| 938e50c876 | |||
| e76bfcf2f6 | |||
| ee06ac3ad2 | |||
| 19a8870f76 | |||
| d828f2477e | |||
| 99a3a7e94e | |||
| 4d2bad4c11 | |||
| ed14df9738 | |||
| a516441513 | |||
| d75abc9104 | |||
| bc83969f6b | |||
| dff8e34bc9 | |||
| 6d9662cf8d | |||
| 2e6b32083e | |||
| b4b42a462a | |||
| a48a2a3dc9 | |||
| 9628599620 | |||
| 3a4d5ff5c3 | |||
| e7fa2571ca | |||
| ad719a9c47 | |||
| 0c4ea9bc7c | |||
| 24de5ffd4e | |||
| 4933bc505f | |||
| ecbee35f93 | |||
| 5552b5c0ec | |||
| 2baa899e32 | |||
| aaaddd1b47 | |||
| d4d4c7e119 | |||
| ea33264a87 | |||
| 4054f33221 | |||
| b6767d2eef | |||
| 90d84a2af8 | |||
| eb34311c2c | |||
| ea7ddc031c | |||
| 1ff17f1a7e | |||
| 8232ab4440 | |||
| bb82e3e1fb | |||
| 1702cdaff6 | |||
| a4583b03a1 | |||
| b12169776e | |||
| 85f85bbec8 | |||
| afc7b46264 | |||
| 86db9e2ce0 | |||
| 1afc7a9210 | |||
| cb6c720d37 | |||
| 35eae8751f | |||
| a246d1a995 | |||
| 718d68eccd | |||
| fb4023af22 | |||
| 370ecd5d15 | |||
| fdff21ae13 | |||
| 69500f356e | |||
| 3b794c4951 | |||
| 72614fdb67 | |||
| 230ee92857 | |||
| c6c952477a | |||
| fd4f22bba5 | |||
| 1e8d7c7891 | |||
| 73316a83c4 | |||
| b2d22d8125 | |||
| afb75bedfe | |||
| ee34781a13 | |||
| 9fc80a0bd5 | |||
| d4203d147a | |||
| a1dda0ec3c | |||
| f9b66dff8b | |||
| dbbc16947f | |||
| dc47abc60e | |||
| ca9ba3cc80 | |||
| 59f6218426 | |||
| f533d08537 | |||
| 230aa7899e | |||
| cc51604267 | |||
| 3b2622267d | |||
| 4fc05e7c64 | |||
| 4e680cae48 | |||
| d957e40a63 | |||
| d1bc8e580d | |||
| 5dadee1591 | |||
| ea7a61a763 | |||
| 8bd6927daf | |||
| 67912c1051 | |||
| 6314a5240d | |||
| e7f55d8706 | |||
| 671756cb13 | |||
| 7cf567b4f9 | |||
| 82e695d94a | |||
| 2104d7b062 | |||
| 6c4739a2f1 | |||
| f858daeca4 | |||
| efa0033fb4 | |||
| 546378e65c | |||
| a997dea414 | |||
| e75af999dc | |||
| e8dcbbe86f | |||
| 3c048caa30 | |||
| 925d2ba9ae | |||
| 645070ef7f | |||
| 2fe1f47e6d | |||
| db8f87d539 | |||
| a75d97c788 | |||
| ea9e414ad6 | |||
| c1bcbcdee5 | |||
| 8f293f3153 | |||
| 70380661fe | |||
| d91d0f1c0a | |||
| 1db696be79 | |||
| 9a30ea1f69 | |||
| 0495359eca | |||
| 1995b9d92c | |||
| 29c0babdda | |||
| 5b55456b75 | |||
| 70205f59a4 | |||
| df7889d7f3 | |||
| 26c25cc6b7 | |||
| 2cf90b6158 | |||
| f8e89f2224 | |||
| 30afac9a6b | |||
| dac56dd757 | |||
| e4ca3a285e | |||
| 30b5a33444 | |||
| e647ebae87 | |||
| 0b34af438f | |||
| a9949a102b | |||
| 90296dab76 | |||
| ed605f01a2 | |||
| bed3c6f807 | |||
| f6221835ef | |||
| 7e9ce1b266 | |||
| c40f29cb54 | |||
| d7afa91023 | |||
| 9bd6d431af | |||
| f126986c2b | |||
| 865564b32f | |||
| 3ae6da10b1 | |||
| 1b9002afd3 | |||
| 9e72260c3b | |||
| 9d52b4e269 | |||
| 6ed4eece04 | |||
| cfaddb5d47 | |||
| 7c861d8b59 | |||
| 1c3457adfb | |||
| a2e46c4d39 | |||
| df1d024059 | |||
| e492dac7fe | |||
| fabe0516fa | |||
| 84971b9076 | |||
| 5efc33fe65 | |||
| 52c228fd9e | |||
| 674b5b808e | |||
| af62aa4497 | |||
| 137a7096c3 | |||
| 703e5ab9a8 | |||
| e2dc94d0e8 | |||
| b821103d1e | |||
| b40c9d8dcd | |||
| e934a8984d | |||
| fa3bbed200 | |||
| b4069ba15b | |||
| 3b96cf3789 | |||
| 1237fd9ab5 | |||
| 1e5a9eb7b9 | |||
| 41fc0955f6 | |||
| 2f5278a139 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
# See https://wiki.apertis.org/Guidelines/Coding_conventions#Code_formatting
|
||||
# See https://www.apertis.org/policies/coding_conventions/#code-formatting
|
||||
BasedOnStyle: GNU
|
||||
AlwaysBreakAfterDefinitionReturnType: All
|
||||
BreakBeforeBinaryOperators: None
|
||||
|
||||
+33
-36
@@ -78,6 +78,7 @@ style-check-diff:
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/reftests/output/*/*.node"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.node"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/headless/*/*.log"
|
||||
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
|
||||
@@ -209,52 +210,54 @@ msys2-mingw64:
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/gtkdll.tar.gz"
|
||||
|
||||
macos-x86_64:
|
||||
macos:
|
||||
rules:
|
||||
# Do not run in forks as the runner is not available there.
|
||||
# (except for dehesselle who maintains the runner)
|
||||
- if: $CI_PROJECT_NAMESPACE == "GNOME"
|
||||
- if: $CI_PROJECT_NAMESPACE == "dehesselle"
|
||||
- if: $CI_PROJECT_NAMESPACE != "GNOME" && $CI_PROJECT_NAMESPACE != "dehesselle"
|
||||
when: never
|
||||
- if: $RUNNER == "macosintel"
|
||||
variables:
|
||||
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
||||
NINJA_PKG: $CI_API_V4_URL/projects/30745/packages/generic/ninja_macos/v1.11.1.1+9/ninja-1.11.1.1-cp38-cp38-macosx_11_0_x86_64.whl
|
||||
when: manual
|
||||
allow_failure: true
|
||||
- if: $RUNNER == "macosarm"
|
||||
variables:
|
||||
SDKROOT: /opt/sdks/MacOSX11.3.sdk
|
||||
NINJA_PKG: ninja==1.11.1.1
|
||||
stage: build
|
||||
parallel:
|
||||
matrix:
|
||||
- RUNNER: [ "macosintel", "macosarm" ]
|
||||
tags:
|
||||
- macosintel
|
||||
- ${RUNNER}
|
||||
needs: []
|
||||
variables:
|
||||
MESON_FORCE_BACKTRACKE: 1
|
||||
EXTRA_MESON_FLAGS: ""
|
||||
BACKEND_FLAGS: "-Dx11-backend=false -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dmedia-gstreamer=disabled -Dintrospection=enabled -Dgobject-introspection:werror=false"
|
||||
TMPDIR: /Users/Shared/work/tmp
|
||||
SDKROOT: /opt/sdks/MacOSX10.13.4.sdk
|
||||
PIP_CACHE_DIR: /Users/Shared/build/cache
|
||||
PIPENV_CACHE_DIR: $PIP_CACHE_DIR
|
||||
PYTHONPYCACHEPREFIX: $PIP_CACHE_DIR
|
||||
EXTRA_MESON_FLAGS: "-Dgobject-introspection:werror=false"
|
||||
before_script:
|
||||
# Not using ccache on purpose as it accelerates the build so much that it
|
||||
# can trigger race conditions in the gobject-introspection subproject.
|
||||
- bash .gitlab-ci/show-info-osx.sh
|
||||
- /opt/macports/bin/python3.10 -m venv .venv
|
||||
- ln -s /opt/cmake/CMake.app/Contents/bin/cmake .venv/bin
|
||||
- ln -s /opt/pkg-config/bin/pkg-config .venv/bin
|
||||
- ln -s /opt/bison/bin/bison .venv/bin
|
||||
- .gitlab-ci/show-info-macos.sh
|
||||
- python3 -m venv .venv
|
||||
# Building the introspection feature requires pkg-config and bison.
|
||||
- curl -L $CI_API_V4_URL/projects/30437/packages/generic/pkgconfig/v0.29.2+10/pkg-config-0.29.2+10_$(uname -m).tar.xz | tar -C .venv -xJ
|
||||
- curl -L $CI_API_V4_URL/projects/30438/packages/generic/bison/v3.8.2+3/bison-3.8.2+3_$(uname -m).tar.xz | tar -C .venv -xJ
|
||||
- source .venv/bin/activate
|
||||
- pip3 install meson==1.2.0
|
||||
- pip3 install ninja==1.11.1
|
||||
- pip3 install /Users/Shared/build/pkgs/PyGObject-3.44.0-cp310-cp310-macosx_10_13_x86_64.whl
|
||||
/Users/Shared/build/pkgs/pycairo-1.23.0-cp310-cp310-macosx_10_13_x86_64.whl
|
||||
- pip3 install meson==1.3.2 $NINJA_PKG
|
||||
# We're not setting up ccache here on purpose as it accelerates the build
|
||||
# so much that it triggers race conditions in the gobject-introspection
|
||||
# subproject.
|
||||
script:
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
-Dx11-backend=false
|
||||
-Dbroadway-backend=true
|
||||
-Dmacos-backend=true
|
||||
-Dmedia-gstreamer=disabled
|
||||
-Dintrospection=enabled
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
-Dlibjpeg-turbo:simd=disabled
|
||||
-Dbuild-demos=false
|
||||
-Dbuild-examples=false
|
||||
-Dbuild-testsuite=false
|
||||
${BACKEND_FLAGS}
|
||||
${FEATURE_FLAGS}
|
||||
_build
|
||||
- meson compile -C _build
|
||||
artifacts:
|
||||
@@ -429,13 +432,6 @@ asan-build:
|
||||
_build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland gtk
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit:
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
|
||||
reference:
|
||||
image: $FEDORA_IMAGE
|
||||
@@ -485,3 +481,4 @@ publish-docs:
|
||||
- "curl -X POST -F token=${PAGES_TRIGGER_TOKEN} -F ref=docs-gtk-org https://gitlab.gnome.org/api/v4/projects/665/trigger/pipeline"
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_NAME == "main"
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
set -eux -o pipefail
|
||||
|
||||
xcodebuild -version || :
|
||||
xcodebuild -showsdks || :
|
||||
|
||||
if [ -z "$SDKROOT" ]; then
|
||||
xcodebuild -showsdks || :
|
||||
else
|
||||
echo "SDKROOT = $SDKROOT"
|
||||
fi
|
||||
|
||||
system_profiler SPSoftwareDataType || :
|
||||
@@ -1,9 +1,165 @@
|
||||
Overview of Changes in 4.13.7, xx-xx-xxxx
|
||||
Overview of Changes in 4.14.1, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
|
||||
Overview of Changes in 4.14.0, 12-03-2024
|
||||
=========================================
|
||||
|
||||
Note: The new renderers and dmabuf support are using graphics drivers
|
||||
in different ways than the old gl renderer, and trigger new driver bugs,
|
||||
(see for example https://gitlab.gnome.org/GNOME/gtk/-/issues/6418 and
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/issues/6388). Therefore, it is
|
||||
recommended to use the latest mesa release (24.x) with the new renderers.
|
||||
|
||||
* GtkTextView:
|
||||
- Don't snapshot children twice
|
||||
- Don't blink the cursor when hidden
|
||||
|
||||
* GtkEmojiChooser:
|
||||
- Fix presentation selector handling
|
||||
|
||||
* GtkSnapshot:
|
||||
- Fix wrong nodes with transformed shadows
|
||||
|
||||
* GtkIMContext:
|
||||
- Make gtk_im_context_activate_osk public
|
||||
|
||||
* Accessibility:
|
||||
- Implement get_contents_at for all our text widgets
|
||||
- Add GtkAccessibleText.get_default_attributes
|
||||
|
||||
* GSK:
|
||||
- Don't fall back to cairo for software rendering. gl+llvmpipe is better
|
||||
- Round vertical glyph position to a device pixel position if the font is hinted
|
||||
- Fix problems with clip handling
|
||||
- Make vulkan and ngl match their font handling
|
||||
- Fix some corner-cases with offloading and clips
|
||||
- Fix problem with rendering of missing glyphs in hinted fonts
|
||||
|
||||
* MacOs:
|
||||
- Implement cursor-from-texture
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
British English
|
||||
French
|
||||
Indonesian
|
||||
Kazakh
|
||||
Latvian
|
||||
Lithuanian
|
||||
Norwegian Bokmål
|
||||
Slovenian
|
||||
Spanish
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.13.9, 02-03-2024
|
||||
=========================================
|
||||
|
||||
* GtkEditable:
|
||||
- Fix preconditions to be not too strict
|
||||
|
||||
* GtkEmojiChooser:
|
||||
- Support search in the locale as well as in English
|
||||
|
||||
* GtkIconTheme:
|
||||
- Make gtk_icon_paintable_new_for_file support symbolics
|
||||
|
||||
* GtkVideo:
|
||||
- Fix a problem with cursor handling that could lead to crashes
|
||||
|
||||
* Accessibility:
|
||||
- Fix GetCharacterAtOffset implementation
|
||||
- Add a Terminal role
|
||||
- Make TextCaretMoved match gtk3
|
||||
- Support multiple levels of GtkEditable delegates
|
||||
|
||||
* GSK:
|
||||
- Make the node parser more flexible for text nodes
|
||||
- Change the way font scaling is handled to avoid clipping
|
||||
- Fix handling of missing glyphs in the new renderers
|
||||
|
||||
* X11:
|
||||
- Don't claim to support shadows without a compositor
|
||||
|
||||
* Wayland:
|
||||
- Fix handling of output scales
|
||||
|
||||
* Tools:
|
||||
- Add a compare command to gtk4-rendernode-tool
|
||||
|
||||
* Build:
|
||||
- Fix some ubsan complaints
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
British English
|
||||
Catalan
|
||||
Finnish
|
||||
Galician
|
||||
Georgian
|
||||
Hebrew
|
||||
Indonesian
|
||||
Kazakh
|
||||
Latvian
|
||||
Lithuanian
|
||||
Persian
|
||||
Polish
|
||||
Russian
|
||||
Slovenian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.13.8, 20-02-2024
|
||||
=========================================
|
||||
|
||||
* Accessibility:
|
||||
- Add a GtkAccessibleText interface for allowing 3rd party
|
||||
text widgets (notably vte) to be accessible
|
||||
- Avoid duplicate accessible descriptions
|
||||
- Fix GetAccessibleAtPoint
|
||||
|
||||
* GSK:
|
||||
- Avoid offscreens for disjoint containers
|
||||
- Don't use the gpu renderers with llvmpipe
|
||||
- Fix various rendering issues found by tests
|
||||
- Allow unnormalized node bounds again
|
||||
- Fix a broken case of rounded-rect intersection
|
||||
- Fix handling of external textures in gpu renderers
|
||||
- Make gpu renderers work with WGL on Windows
|
||||
|
||||
* build:
|
||||
- Allow building without dmabuf support on (old) Linux
|
||||
|
||||
* X11:
|
||||
- Fix monitor enter/leave signals
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
Brazilian Portuguese
|
||||
Catalan
|
||||
Czech
|
||||
Galician
|
||||
Georgian
|
||||
Hebrew
|
||||
Lithuanian
|
||||
Persian
|
||||
Russian
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.13.7, 11-02-2024
|
||||
=========================================
|
||||
|
||||
* GtkFileChooser:
|
||||
- Speed up opening
|
||||
|
||||
* GtkCalendar:
|
||||
- Add some missing setters and getters
|
||||
|
||||
* Accessibility:
|
||||
- Add socket support for webkit accessibility
|
||||
- Implement AT-SPI text for GtkText
|
||||
@@ -14,22 +170,25 @@ Overview of Changes in 4.13.7, xx-xx-xxxx
|
||||
- Make the ngl renderer work on macOS
|
||||
- Fix a crash in the vulkan renderer
|
||||
- Make nodeparser allow aliases for fonts again
|
||||
- Implement cache eviction for the glyph and
|
||||
texture caches
|
||||
- Fix shaders to work on GL < 4.0
|
||||
- Implement cache eviction for glyph and texture caches
|
||||
- Fix ngl shaders to work on GL < 4.0
|
||||
- Require GL 3.3 for the ngl renderer
|
||||
- Fix problems with scaled shadows
|
||||
- Fix problems with holes for underlaid subsurfaces
|
||||
- Improve handling of scales and glyph cache efficiency
|
||||
|
||||
* media:
|
||||
* Media:
|
||||
- Support dmabufs in the gstreamer backend. This allows
|
||||
zero-copy video playback on Wayland when paired with
|
||||
hardware video decoding
|
||||
- Drop the experimental ffmpeg backend. It hasn't been
|
||||
building for a year
|
||||
|
||||
* Wayland:
|
||||
- Commit empty frames if and double-buffered state
|
||||
is pending
|
||||
- Commit empty frames if and double-buffered state is pending
|
||||
- Fix monitor size information when using mutter without
|
||||
the scale-monitor-framebuffer setting
|
||||
- Clear the current tablet on tab leave, fixing a crash
|
||||
|
||||
* macOS:
|
||||
- Propagate unhandled input events back to the OS
|
||||
@@ -41,6 +200,7 @@ Overview of Changes in 4.13.7, xx-xx-xxxx
|
||||
Galician
|
||||
Georgian
|
||||
Occitan
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.13.6, 25-01-2024
|
||||
|
||||
@@ -600,8 +600,8 @@ update_display (void)
|
||||
if (s->len > 0)
|
||||
{
|
||||
pango_font_description_set_variations (desc, s->str);
|
||||
g_string_free (s, TRUE);
|
||||
}
|
||||
g_string_free (s, TRUE);
|
||||
|
||||
font_desc = pango_font_description_to_string (desc);
|
||||
|
||||
|
||||
@@ -116,7 +116,9 @@ static gboolean gtk_shadertoy_tick (GtkWidget *widget,
|
||||
GtkWidget *
|
||||
gtk_shadertoy_new (void)
|
||||
{
|
||||
return g_object_new (gtk_shadertoy_get_type (), NULL);
|
||||
return g_object_new (gtk_shadertoy_get_type (),
|
||||
"allowed-apis", GDK_GL_API_GL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -354,6 +354,7 @@ do_images (GtkWidget *do_widget)
|
||||
gicon = g_themed_icon_new_with_default_fallbacks ("battery-caution-charging-symbolic");
|
||||
image = gtk_image_new_from_gicon (gicon);
|
||||
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
|
||||
g_object_unref (gicon);
|
||||
|
||||
gtk_frame_set_child (GTK_FRAME (frame), image);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Lists/Selections
|
||||
* #Keywords: suggestion, completion
|
||||
*
|
||||
* The GtkDropDown widget is a modern alternative to GtkComboBox.
|
||||
* It uses list models instead of tree models, and the content is
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">app.help</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Help</attribute>
|
||||
<attribute name="action">app.help</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">_Inspector</attribute>
|
||||
<attribute name="action">app.inspector</attribute>
|
||||
|
||||
@@ -322,12 +322,14 @@ stroke bounds of the path.
|
||||
|
||||
### text
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ------------------- | ------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` `<url>`? | "Cantarell 11" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
| property | syntax | default | printed |
|
||||
| ------------ | ------------------- | ------------------- | ----------- |
|
||||
| color | `<color>` | black | non-default |
|
||||
| font | `<string>` `<url>`? | "Cantarell 15px" | always |
|
||||
| glyphs | `<glyphs>` | "Hello" | always |
|
||||
| offset | `<point>` | 0 0 | non-default |
|
||||
| hint-style | `<hint style>` | slight | non-default |
|
||||
| antialias | `<antialias>` | gray | non-default |
|
||||
|
||||
Creates a node like `gsk_text_node_new()` with the given properties.
|
||||
|
||||
@@ -336,12 +338,15 @@ font that is specified in the string. It can be either a data url containing
|
||||
a base64-encoded font file, or a regular url that points to a font file.
|
||||
|
||||
Glyphs can be specified as an ASCII string, or as a comma-separated list of
|
||||
their glyph ID and advance width. Optionally, x and y offsets and flags can
|
||||
their glyph IDs. Optionally, the advance width, x and y offsets and flags can
|
||||
be specified as well, like this: 40 10 0 0 color.
|
||||
|
||||
If the given font does not exist or the given glyphs are invalid for the given
|
||||
font, an error node will be returned.
|
||||
|
||||
Possible values for hint-style are none, slight or full.
|
||||
Possible value for antialias are none or gray.
|
||||
|
||||
### texture
|
||||
|
||||
| property | syntax | default | printed |
|
||||
|
||||
+3
-3
@@ -69,9 +69,9 @@ Image:
|
||||
4 CARD32 IMAGE_DATA_OFFSET
|
||||
|
||||
ICON_FLAGS
|
||||
HAS_SUFFIX_PNG 1
|
||||
HAS_SUFFIX_XPM 2
|
||||
HAS_SUFFIX_SVG 4
|
||||
HAS_SUFFIX_XPM 1
|
||||
HAS_SUFFIX_SVG 2
|
||||
HAS_SUFFIX_PNG 4
|
||||
HAS_ICON_FILE 8
|
||||
|
||||
ImageData:
|
||||
|
||||
@@ -13,6 +13,7 @@ SYNOPSIS
|
||||
| **gtk4-rendernode-tool** <COMMAND> [OPTIONS...] <FILE>
|
||||
|
|
||||
| **gtk4-rendernode-tool** benchmark [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** compare [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-rendernode-tool** info [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** render [OPTIONS...] <FILE> [<FILE>]
|
||||
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
|
||||
@@ -75,7 +76,21 @@ and prints the runtimes.
|
||||
the execution of the commands on the GPU. It can be useful to use this flag to test
|
||||
command submission performance.
|
||||
|
||||
Compare
|
||||
^^^^^^^
|
||||
|
||||
The ``compare`` command compares the rendering of a node with a reference image,
|
||||
or the renderings of two nodes, or two images. If any differences are found, the
|
||||
exit code is 1. If the images are identical, it is 0.
|
||||
|
||||
``--renderer=RENDERER``
|
||||
|
||||
Use the given renderer.
|
||||
|
||||
``--output=FILE``
|
||||
|
||||
Save the differences as a png image in ``FILE``.
|
||||
|
||||
``--quiet``
|
||||
|
||||
Don't write results to stdout.`
|
||||
|
||||
+4
-1
@@ -2037,9 +2037,12 @@ gdk_display_get_dmabuf_formats (GdkDisplay *display)
|
||||
GdkDebugFlags
|
||||
gdk_display_get_debug_flags (GdkDisplay *display)
|
||||
{
|
||||
if (display == NULL)
|
||||
return _gdk_debug_flags;
|
||||
|
||||
GdkDisplayPrivate *priv = gdk_display_get_instance_private (display);
|
||||
|
||||
return display ? priv->debug_flags : _gdk_debug_flags;
|
||||
return priv->debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+12
-1
@@ -154,6 +154,7 @@ gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
gboolean retval = FALSE;
|
||||
GError *error = NULL;
|
||||
GskRenderer *renderer;
|
||||
GdkGLContext *previous;
|
||||
|
||||
g_assert (display->egl_dmabuf_formats == NULL);
|
||||
g_assert (display->egl_external_formats == NULL);
|
||||
@@ -161,6 +162,7 @@ gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
if (!gdk_display_prepare_gl (display, NULL))
|
||||
return NULL;
|
||||
|
||||
previous = gdk_gl_context_get_current ();
|
||||
formats = gdk_dmabuf_formats_builder_new ();
|
||||
external = gdk_dmabuf_formats_builder_new ();
|
||||
|
||||
@@ -172,7 +174,11 @@ gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
gdk_dmabuf_formats_builder_add_formats (builder, display->egl_dmabuf_formats);
|
||||
|
||||
if (!retval)
|
||||
return NULL;
|
||||
{
|
||||
if (previous)
|
||||
gdk_gl_context_make_current (previous);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderer = gsk_gl_renderer_new ();
|
||||
|
||||
@@ -181,10 +187,15 @@ gdk_dmabuf_get_egl_downloader (GdkDisplay *display,
|
||||
g_warning ("Failed to realize GL renderer: %s", error->message);
|
||||
g_error_free (error);
|
||||
g_object_unref (renderer);
|
||||
if (previous)
|
||||
gdk_gl_context_make_current (previous);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (previous)
|
||||
gdk_gl_context_make_current (previous);
|
||||
|
||||
return GDK_DMABUF_DOWNLOADER (renderer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include "config.h"
|
||||
#ifdef HAVE_DRM_FOURCC_H
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
|
||||
+177
-42
@@ -309,67 +309,202 @@ typedef enum
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_R8G8B8A8_PREMULTIPLIED: 4 bytes; for red, green, blue, alpha
|
||||
* The color values are premultiplied with the alpha value.
|
||||
* @GDK_MEMORY_A8B8G8R8_PREMULTIPLIED: 4 bytes; for alpha, blue, green, red,
|
||||
* The color values are premultiplied with the alpha value. Since 4.14
|
||||
* @GDK_MEMORY_B8G8R8A8: 4 bytes; for blue, green, red, alpha.
|
||||
* @GDK_MEMORY_A8R8G8B8: 4 bytes; for alpha, red, green, blue.
|
||||
* @GDK_MEMORY_R8G8B8A8: 4 bytes; for red, green, blue, alpha.
|
||||
* @GDK_MEMORY_A8B8G8R8: 4 bytes; for alpha, blue, green, red.
|
||||
* @GDK_MEMORY_B8G8R8X8: 4 bytes; for blue, green, red, unused. Since 4.14
|
||||
* @GDK_MEMORY_X8R8G8B8: 4 bytes; for unused, red, green, blue. Since 4.14
|
||||
* @GDK_MEMORY_R8G8B8X8: 4 bytes; for red, green, blue, unused. Since 4.14
|
||||
* @GDK_MEMORY_X8B8G8R8: 4 bytes; for unused, blue, green, red. Since 4.14
|
||||
* @GDK_MEMORY_R8G8B8: 3 bytes; for red, green, blue. The data is opaque.
|
||||
* @GDK_MEMORY_B8G8R8: 3 bytes; for blue, green, red. The data is opaque.
|
||||
* @GDK_MEMORY_R16G16B16: 3 guint16 values; for red, green, blue. Since: 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_PREMULTIPLIED: 4 guint16 values; for red, green,
|
||||
* blue, alpha. The color values are premultiplied with the alpha value.
|
||||
* Since: 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16: 4 guint16 values; for red, green, blue, alpha.
|
||||
* Since: 4.6
|
||||
* @GDK_MEMORY_R16G16B16_FLOAT: 3 half-float values; for red, green, blue.
|
||||
* The data is opaque. Since: 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED: 4 half-float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since: 4.6
|
||||
* @GDK_MEMORY_R16G16B16A16_FLOAT: 4 half-float values; for red, green,
|
||||
* blue and alpha. Since: 4.6
|
||||
* @GDK_MEMORY_B32G32R32_FLOAT: 3 float values; for blue, green, red.
|
||||
* The data is opaque. Since: 4.6
|
||||
* @GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED: 4 float values; for
|
||||
* red, green, blue and alpha. The color values are premultiplied with
|
||||
* the alpha value. Since: 4.6
|
||||
* @GDK_MEMORY_R32G32B32A32_FLOAT: 4 float values; for red, green, blue and
|
||||
* alpha. Since: 4.6
|
||||
* @GDK_MEMORY_G8A8_PREMULTIPLIED: 2 bytes; for grayscale, alpha. The color
|
||||
* values are premultiplied with the alpha value. Since: 4.12
|
||||
* @GDK_MEMORY_G8A8: 2 bytes; for grayscale, alpha. Since: 4.12
|
||||
* @GDK_MEMORY_G8: One byte; for grayscale. The data is opaque.
|
||||
* Since: 4.12
|
||||
* @GDK_MEMORY_G16A16_PREMULTIPLIED: 2 guint16 values; for grayscale, alpha.
|
||||
* The color values are premultiplied with the alpha value. Since: 4.12
|
||||
* @GDK_MEMORY_G16A16: 2 guint16 values; for grayscale, alpha. Since: 4.12
|
||||
* @GDK_MEMORY_G16: One guint16 value; for grayscale. The data is opaque.
|
||||
* Since: 4.12
|
||||
* @GDK_MEMORY_A8: One byte; for alpha.
|
||||
* Since: 4.12
|
||||
* @GDK_MEMORY_A16: One guint16 value; for alpha.
|
||||
* Since: 4.12
|
||||
* @GDK_MEMORY_N_FORMATS: The number of formats. This value will change as
|
||||
* more formats get added, so do not rely on its concrete integer.
|
||||
* @GDK_MEMORY_R32G32B32_FLOAT: 3 float values; for red, green, blue.
|
||||
*
|
||||
* `GdkMemoryFormat` describes formats that image data can have in memory.
|
||||
*
|
||||
* It describes formats by listing the contents of the memory passed to it.
|
||||
* So GDK_MEMORY_A8R8G8B8 will be 1 byte (8 bits) of alpha, followed by a
|
||||
* So `GDK_MEMORY_A8R8G8B8` will be 1 byte (8 bits) of alpha, followed by a
|
||||
* byte each of red, green and blue. It is not endian-dependent, so
|
||||
* CAIRO_FORMAT_ARGB32 is represented by different `GdkMemoryFormats`
|
||||
* `CAIRO_FORMAT_ARGB32` is represented by different `GdkMemoryFormats`
|
||||
* on architectures with different endiannesses.
|
||||
*
|
||||
* Its naming is modelled after
|
||||
* [VkFormat](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VkFormat)
|
||||
* for details).
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_A8B8G8R8_PREMULTIPLIED:
|
||||
*
|
||||
* 4 bytes; for alpha, blue, green, red, The color values are premultiplied with
|
||||
* the alpha value.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_B8G8R8X8:
|
||||
*
|
||||
* 4 bytes; for blue, green, red, unused.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_X8R8G8B8:
|
||||
*
|
||||
* 4 bytes; for unused, red, green, blue.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R8G8B8X8:
|
||||
*
|
||||
* 4 bytes; for red, green, blue, unused.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_X8B8G8R8:
|
||||
*
|
||||
* 4 bytes; for unused, blue, green, red.
|
||||
*
|
||||
* Since: 4.14
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16:
|
||||
*
|
||||
* 3 guint16 values; for red, green, blue.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
|
||||
*
|
||||
* 4 guint16 values; for red, green, blue, alpha. The color values are
|
||||
* premultiplied with the alpha value.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16A16:
|
||||
*
|
||||
* 4 guint16 values; for red, green, blue, alpha.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16_FLOAT:
|
||||
*
|
||||
* 3 half-float values; for red, green, blue. The data is opaque.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED:
|
||||
*
|
||||
* 4 half-float values; for red, green, blue and alpha. The color values are
|
||||
* premultiplied with the alpha value.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R16G16B16A16_FLOAT:
|
||||
*
|
||||
* 4 half-float values; for red, green, blue and alpha.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_B32G32R32_FLOAT:
|
||||
*
|
||||
* 3 float values; for blue, green, red. The data is opaque.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED:
|
||||
*
|
||||
* 4 float values; for red, green, blue and alpha. The color values are
|
||||
* premultiplied with the alpha value.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_R32G32B32A32_FLOAT:
|
||||
*
|
||||
* 4 float values; for red, green, blue and alpha.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G8A8_PREMULTIPLIED:
|
||||
*
|
||||
* 2 bytes; for grayscale, alpha. The color values are premultiplied with the
|
||||
* alpha value.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G8A8:
|
||||
*
|
||||
* 2 bytes; for grayscale, alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G8:
|
||||
*
|
||||
* One byte; for grayscale. The data is opaque.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G16A16_PREMULTIPLIED:
|
||||
*
|
||||
* 2 guint16 values; for grayscale, alpha. The color values are premultiplied
|
||||
* with the alpha value.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G16A16:
|
||||
*
|
||||
* 2 guint16 values; for grayscale, alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_G16:
|
||||
*
|
||||
* One guint16 value; for grayscale. The data is opaque.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_A8:
|
||||
*
|
||||
* One byte; for alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_A16:
|
||||
*
|
||||
* One guint16 value; for alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_A16_FLOAT:
|
||||
*
|
||||
* One half-float value; for alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
/**
|
||||
* GDK_MEMORY_A32_FLOAT:
|
||||
*
|
||||
* One float value; for alpha.
|
||||
*
|
||||
* Since: 4.12
|
||||
*/
|
||||
typedef enum {
|
||||
GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
||||
GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
|
||||
|
||||
+56
-29
@@ -79,14 +79,23 @@ static guint signals[LAST_SIGNAL];
|
||||
|
||||
static guint fps_counter;
|
||||
|
||||
#define FRAME_HISTORY_MAX_LENGTH 128
|
||||
/* 60Hz plus some extra for monotonic time inaccuracy */
|
||||
#define FRAME_HISTORY_DEFAULT_LENGTH 64
|
||||
|
||||
#define frame_timings_unref(x) gdk_frame_timings_unref((GdkFrameTimings *) (x))
|
||||
|
||||
#define GDK_ARRAY_NAME timings
|
||||
#define GDK_ARRAY_TYPE_NAME Timings
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GdkFrameTimings *
|
||||
#define GDK_ARRAY_PREALLOC FRAME_HISTORY_DEFAULT_LENGTH
|
||||
#define GDK_ARRAY_FREE_FUNC frame_timings_unref
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
struct _GdkFrameClockPrivate
|
||||
{
|
||||
gint64 frame_counter;
|
||||
int n_timings;
|
||||
int current;
|
||||
GdkFrameTimings *timings[FRAME_HISTORY_MAX_LENGTH];
|
||||
Timings timings;
|
||||
int n_freeze_inhibitors;
|
||||
};
|
||||
|
||||
@@ -99,11 +108,8 @@ static void
|
||||
gdk_frame_clock_finalize (GObject *object)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FRAME_HISTORY_MAX_LENGTH; i++)
|
||||
if (priv->timings[i] != 0)
|
||||
gdk_frame_timings_unref (priv->timings[i]);
|
||||
timings_clear (&priv->timings);
|
||||
|
||||
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -257,7 +263,8 @@ gdk_frame_clock_init (GdkFrameClock *clock)
|
||||
clock->priv = priv = gdk_frame_clock_get_instance_private (clock);
|
||||
|
||||
priv->frame_counter = -1;
|
||||
priv->current = FRAME_HISTORY_MAX_LENGTH - 1;
|
||||
priv->current = 0;
|
||||
timings_init (&priv->timings);
|
||||
|
||||
if (fps_counter == 0)
|
||||
fps_counter = gdk_profiler_define_counter ("fps", "Frames per Second");
|
||||
@@ -416,7 +423,7 @@ gdk_frame_clock_get_frame_counter (GdkFrameClock *frame_clock)
|
||||
static inline gint64
|
||||
_gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->priv->frame_counter + 1 - frame_clock->priv->n_timings;
|
||||
return frame_clock->priv->frame_counter + 1 - timings_get_size (&frame_clock->priv->timings);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,31 +452,44 @@ gdk_frame_clock_get_history_start (GdkFrameClock *frame_clock)
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock)
|
||||
_gdk_frame_clock_begin_frame (GdkFrameClock *frame_clock,
|
||||
gint64 monotonic_time)
|
||||
{
|
||||
GdkFrameClockPrivate *priv;
|
||||
|
||||
g_return_if_fail (GDK_IS_FRAME_CLOCK (frame_clock));
|
||||
|
||||
priv = frame_clock->priv;
|
||||
|
||||
priv->frame_counter++;
|
||||
priv->current = (priv->current + 1) % FRAME_HISTORY_MAX_LENGTH;
|
||||
|
||||
/* Try to steal the previous frame timing instead of discarding
|
||||
* and allocating a new one.
|
||||
*/
|
||||
if G_LIKELY (priv->n_timings == FRAME_HISTORY_MAX_LENGTH &&
|
||||
_gdk_frame_timings_steal (priv->timings[priv->current],
|
||||
priv->frame_counter))
|
||||
return;
|
||||
|
||||
if (priv->n_timings < FRAME_HISTORY_MAX_LENGTH)
|
||||
priv->n_timings++;
|
||||
if (G_UNLIKELY (timings_get_size (&priv->timings) == 0))
|
||||
timings_append (&priv->timings, _gdk_frame_timings_new (priv->frame_counter));
|
||||
else
|
||||
gdk_frame_timings_unref (priv->timings[priv->current]);
|
||||
{
|
||||
GdkFrameTimings *timings;
|
||||
|
||||
priv->timings[priv->current] = _gdk_frame_timings_new (priv->frame_counter);
|
||||
priv->current = (priv->current + 1) % timings_get_size (&priv->timings);
|
||||
|
||||
timings = timings_get (&priv->timings, priv->current);
|
||||
|
||||
if (timings->frame_time + G_USEC_PER_SEC > monotonic_time)
|
||||
{
|
||||
/* Keep the timings, not a second old yet */
|
||||
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||
timings_splice (&priv->timings, priv->current, 0, FALSE, &timings, 1);
|
||||
}
|
||||
else if (_gdk_frame_timings_steal (timings, priv->frame_counter))
|
||||
{
|
||||
/* Stole the previous frame timing instead of discarding
|
||||
* and allocating a new one, so nothing to do
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
timings = _gdk_frame_timings_new (priv->frame_counter);
|
||||
timings_splice (&priv->timings, priv->current, 1, FALSE, &timings, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline GdkFrameTimings *
|
||||
@@ -477,17 +497,21 @@ _gdk_frame_clock_get_timings (GdkFrameClock *frame_clock,
|
||||
gint64 frame_counter)
|
||||
{
|
||||
GdkFrameClockPrivate *priv = frame_clock->priv;
|
||||
int pos;
|
||||
gsize size, pos;
|
||||
|
||||
if (frame_counter > priv->frame_counter)
|
||||
return NULL;
|
||||
|
||||
if (frame_counter <= priv->frame_counter - priv->n_timings)
|
||||
size = timings_get_size (&priv->timings);
|
||||
if (G_UNLIKELY (size == 0))
|
||||
return NULL;
|
||||
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + FRAME_HISTORY_MAX_LENGTH) % FRAME_HISTORY_MAX_LENGTH;
|
||||
if (priv->frame_counter - frame_counter >= size)
|
||||
return NULL;
|
||||
|
||||
return priv->timings[pos];
|
||||
pos = (priv->current - (priv->frame_counter - frame_counter) + size) % size;
|
||||
|
||||
return timings_get (&priv->timings, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,7 +803,10 @@ gdk_frame_clock_get_fps (GdkFrameClock *frame_clock)
|
||||
|
||||
start_counter = _gdk_frame_clock_get_history_start (frame_clock);
|
||||
end_counter = _gdk_frame_clock_get_frame_counter (frame_clock);
|
||||
start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
|
||||
for (start = _gdk_frame_clock_get_timings (frame_clock, start_counter);
|
||||
end_counter > start_counter && start != NULL && !gdk_frame_timings_get_complete (start);
|
||||
start = _gdk_frame_clock_get_timings (frame_clock, start_counter))
|
||||
start_counter++;
|
||||
for (end = _gdk_frame_clock_get_timings (frame_clock, end_counter);
|
||||
end_counter > start_counter && end != NULL && !gdk_frame_timings_get_complete (end);
|
||||
end = _gdk_frame_clock_get_timings (frame_clock, end_counter))
|
||||
|
||||
@@ -192,6 +192,13 @@ compute_smooth_frame_time (GdkFrameClock *clock,
|
||||
* and new_frame_time >= old_frame_time. */
|
||||
frames_passed = (new_frame_time - smoothed_frame_time_base + frame_interval / 2) / frame_interval;
|
||||
|
||||
if (frames_passed > 1)
|
||||
gdk_profiler_add_markf ((smoothed_frame_time_base - (frame_interval * (frames_passed-1))) * 1000L,
|
||||
frame_interval * (frames_passed-1) * 1000L,
|
||||
"Dropped Frames",
|
||||
"%u frames may have been dropped",
|
||||
frames_passed-1);
|
||||
|
||||
/* We use an approximately whole number of frames in the future from
|
||||
* last smoothed frame time. This way we avoid minor jitter in the
|
||||
* frame times making the animation speed uneven, but still animate
|
||||
@@ -548,7 +555,7 @@ gdk_frame_clock_paint_idle (void *data)
|
||||
priv->smoothed_frame_time_period = frame_interval;
|
||||
priv->smoothed_frame_time_reported = priv->smoothed_frame_time_base;
|
||||
|
||||
_gdk_frame_clock_begin_frame (clock);
|
||||
_gdk_frame_clock_begin_frame (clock, priv->frame_time);
|
||||
/* Note "current" is different now so timings != prev_timings */
|
||||
timings = gdk_frame_clock_get_current_timings (clock);
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ struct _GdkFrameTimings
|
||||
void _gdk_frame_clock_inhibit_freeze (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_uninhibit_freeze (GdkFrameClock *clock);
|
||||
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock);
|
||||
void _gdk_frame_clock_begin_frame (GdkFrameClock *clock,
|
||||
gint64 monotonic_time);
|
||||
void _gdk_frame_clock_debug_print_timings (GdkFrameClock *clock,
|
||||
GdkFrameTimings *timings);
|
||||
void _gdk_frame_clock_add_timings_to_profiler (GdkFrameClock *frame_clock,
|
||||
|
||||
+5
-7
@@ -79,6 +79,7 @@
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkdmabufeglprivate.h"
|
||||
#include "gdkdmabuffourccprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
@@ -98,10 +99,6 @@
|
||||
#include <epoxy/egl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DEFAULT_ALLOWED_APIS GDK_GL_API_GL | GDK_GL_API_GLES
|
||||
@@ -661,6 +658,7 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
EGLSurface egl_surface;
|
||||
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
if (priv->egl_context == NULL)
|
||||
return;
|
||||
@@ -669,8 +667,6 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
egl_surface = gdk_surface_get_egl_surface (surface);
|
||||
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "EGL swap buffers", NULL);
|
||||
|
||||
if (priv->eglSwapBuffersWithDamage)
|
||||
{
|
||||
EGLint stack_rects[4 * 4]; /* 4 rects */
|
||||
@@ -701,6 +697,8 @@ gdk_gl_context_real_end_frame (GdkDrawContext *draw_context,
|
||||
else
|
||||
eglSwapBuffers (gdk_display_get_egl_display (display), egl_surface);
|
||||
#endif
|
||||
|
||||
gdk_profiler_add_mark (begin_time, GDK_PROFILER_CURRENT_TIME - begin_time, "EGL swap buffers", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1718,7 +1716,7 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
|
||||
}
|
||||
|
||||
priv->has_half_float = gdk_gl_context_check_version (context, "3.0", "3.0") ||
|
||||
epoxy_has_gl_extension ("OES_vertex_half_float");
|
||||
epoxy_has_gl_extension ("GL_OES_vertex_half_float");
|
||||
|
||||
priv->has_sync = gdk_gl_context_check_version (context, "3.2", "3.0") ||
|
||||
epoxy_has_gl_extension ("GL_ARB_sync") ||
|
||||
|
||||
+24
-7
@@ -20,6 +20,7 @@
|
||||
#include "gdksubsurfaceprivate.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gsk/gskrectprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GdkSubsurface, gdk_subsurface, G_TYPE_OBJECT)
|
||||
|
||||
@@ -110,7 +111,8 @@ insert_subsurface (GdkSubsurface *subsurface,
|
||||
gboolean
|
||||
gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
@@ -118,7 +120,12 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SUBSURFACE (subsurface), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), FALSE);
|
||||
g_return_val_if_fail (rect != NULL, FALSE);
|
||||
g_return_val_if_fail (source != NULL &&
|
||||
gsk_rect_contains_rect (&GRAPHENE_RECT_INIT (0, 0,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture)),
|
||||
source), FALSE);
|
||||
g_return_val_if_fail (dest != NULL, FALSE);
|
||||
g_return_val_if_fail (sibling != subsurface, FALSE);
|
||||
g_return_val_if_fail (sibling == NULL || GDK_IS_SUBSURFACE (sibling), FALSE);
|
||||
g_return_val_if_fail (sibling == NULL || sibling->parent == subsurface->parent, FALSE);
|
||||
@@ -148,7 +155,7 @@ gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, rect, above, sibling);
|
||||
return GDK_SUBSURFACE_GET_CLASS (subsurface)->attach (subsurface, texture, source, dest, above, sibling);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -170,13 +177,23 @@ gdk_subsurface_get_texture (GdkSubsurface *subsurface)
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_get_rect (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect)
|
||||
gdk_subsurface_get_source (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *source)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
|
||||
g_return_if_fail (rect != NULL);
|
||||
g_return_if_fail (source != NULL);
|
||||
|
||||
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_rect (subsurface, rect);
|
||||
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_source (subsurface, source);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_subsurface_get_dest (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *dest)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_SUBSURFACE (subsurface));
|
||||
g_return_if_fail (dest != NULL);
|
||||
|
||||
GDK_SUBSURFACE_GET_CLASS (subsurface)->get_dest (subsurface, dest);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -54,13 +54,16 @@ struct _GdkSubsurfaceClass
|
||||
|
||||
gboolean (* attach) (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling);
|
||||
void (* detach) (GdkSubsurface *subsurface);
|
||||
GdkTexture * (* get_texture) (GdkSubsurface *subsurface);
|
||||
void (* get_rect) (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect);
|
||||
void (* get_source) (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *source);
|
||||
void (* get_dest) (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *dest);
|
||||
};
|
||||
|
||||
GType gdk_subsurface_get_type (void) G_GNUC_CONST;
|
||||
@@ -68,13 +71,16 @@ GType gdk_subsurface_get_type (void) G_GNUC_CONST;
|
||||
GdkSurface * gdk_subsurface_get_parent (GdkSubsurface *subsurface);
|
||||
gboolean gdk_subsurface_attach (GdkSubsurface *subsurface,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling);
|
||||
void gdk_subsurface_detach (GdkSubsurface *subsurface);
|
||||
GdkTexture * gdk_subsurface_get_texture (GdkSubsurface *subsurface);
|
||||
void gdk_subsurface_get_rect (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *rect);
|
||||
void gdk_subsurface_get_source (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *source);
|
||||
void gdk_subsurface_get_dest (GdkSubsurface *subsurface,
|
||||
graphene_rect_t *dest);
|
||||
gboolean gdk_subsurface_is_above_parent (GdkSubsurface *subsurface);
|
||||
|
||||
|
||||
|
||||
@@ -260,6 +260,11 @@ gdk_vulkan_strerror (VkResult result)
|
||||
case VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:
|
||||
return "The provided binary shader code is not compatible with this device. (VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT)";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION >= 274
|
||||
case VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:
|
||||
return "The specified Video Std parameters do not adhere to the syntactic or semantic requirements of the used video compression standard or implementation";
|
||||
#endif
|
||||
|
||||
case VK_RESULT_MAX_ENUM:
|
||||
default:
|
||||
return "Unknown Vulkan error.";
|
||||
|
||||
@@ -214,22 +214,6 @@ typedef NSString *CALayerContentsGravity;
|
||||
}
|
||||
}
|
||||
|
||||
-(void)setFrame:(NSRect)frame display:(BOOL)display
|
||||
{
|
||||
NSRect contentRect = [self contentRectForFrameRect:frame];
|
||||
GdkSurface *surface = GDK_SURFACE (gdk_surface);
|
||||
gboolean maximized = (surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0;
|
||||
|
||||
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, frame))
|
||||
{
|
||||
gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
|
||||
_gdk_surface_update_size (surface);
|
||||
}
|
||||
|
||||
[super setFrame:frame display:display];
|
||||
[[self contentView] setFrame:NSMakeRect (0, 0, contentRect.size.width, contentRect.size.height)];
|
||||
}
|
||||
|
||||
-(id)initWithContentRect:(NSRect)contentRect
|
||||
styleMask:(NSWindowStyleMask)styleMask
|
||||
backing:(NSBackingStoreType)backingType
|
||||
@@ -387,12 +371,17 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
-(void)windowDidMove:(NSNotification *)notification
|
||||
{
|
||||
if ([self isZoomed])
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
|
||||
else
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_TOPLEVEL_STATE_MAXIMIZED, 0);
|
||||
|
||||
_gdk_macos_surface_configure ([self gdkSurface]);
|
||||
}
|
||||
|
||||
-(void)windowDidResize:(NSNotification *)notification
|
||||
{
|
||||
_gdk_macos_surface_configure (gdk_surface);
|
||||
[self windowDidMove: notification];
|
||||
|
||||
/* If we're using server-side decorations, this notification is coming
|
||||
* in from a display-side change. We need to request a layout in
|
||||
@@ -413,7 +402,6 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
-(void)beginManualMove
|
||||
{
|
||||
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
|
||||
NSPoint initialMoveLocation;
|
||||
GdkPoint point;
|
||||
GdkMonitor *monitor;
|
||||
@@ -432,13 +420,6 @@ typedef NSString *CALayerContentsGravity;
|
||||
|
||||
initialMoveLocation = [NSEvent mouseLocation];
|
||||
|
||||
if (maximized)
|
||||
[self setFrame:NSMakeRect (initialMoveLocation.x - (int)lastUnmaximizedFrame.size.width/2,
|
||||
initialMoveLocation.y,
|
||||
lastUnmaximizedFrame.size.width,
|
||||
lastUnmaximizedFrame.size.height)
|
||||
display:YES];
|
||||
|
||||
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
||||
initialMoveLocation.x,
|
||||
initialMoveLocation.y,
|
||||
@@ -781,43 +762,11 @@ typedef NSString *CALayerContentsGravity;
|
||||
return rect;
|
||||
}
|
||||
|
||||
/* Implementing this method avoids new windows move around the screen. */
|
||||
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
|
||||
defaultFrame:(NSRect)newFrame
|
||||
{
|
||||
NSRect screenFrame = [[self screen] visibleFrame];
|
||||
GdkMacosSurface *surface = gdk_surface;
|
||||
gboolean maximized = GDK_SURFACE (surface)->state & GDK_TOPLEVEL_STATE_MAXIMIZED;
|
||||
|
||||
if (!maximized)
|
||||
return screenFrame;
|
||||
else
|
||||
return lastUnmaximizedFrame;
|
||||
}
|
||||
|
||||
-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
|
||||
toFrame:(NSRect)newFrame
|
||||
{
|
||||
GdkMacosSurface *surface = gdk_surface;
|
||||
GdkToplevelState state = GDK_SURFACE (surface)->state;
|
||||
|
||||
if (state & GDK_TOPLEVEL_STATE_MAXIMIZED)
|
||||
{
|
||||
lastMaximizedFrame = newFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastUnmaximizedFrame = [nsWindow frame];
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_TOPLEVEL_STATE_MAXIMIZED);
|
||||
}
|
||||
|
||||
inMaximizeTransition = YES;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
|
||||
{
|
||||
inMaximizeTransition = NO;
|
||||
return newFrame;
|
||||
}
|
||||
|
||||
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
|
||||
|
||||
@@ -49,10 +49,7 @@
|
||||
|
||||
EdgeSnapping snapping;
|
||||
|
||||
NSRect lastUnmaximizedFrame;
|
||||
NSRect lastMaximizedFrame;
|
||||
NSRect lastUnfullscreenFrame;
|
||||
BOOL inMaximizeTransition;
|
||||
BOOL inFullscreenTransition;
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,57 @@ create_blank_cursor (void)
|
||||
return nscursor;
|
||||
}
|
||||
|
||||
static NSCursor *
|
||||
create_cursor_from_texture (GdkTexture *texture,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
guint32 width;
|
||||
guint32 height;
|
||||
guchar *pixels;
|
||||
gsize stride;
|
||||
GdkTextureDownloader *downloader;
|
||||
NSCursor *nscursor;
|
||||
NSBitmapImageRep *nsbitmap;
|
||||
NSImage *nsimage;
|
||||
|
||||
if (texture == NULL)
|
||||
return create_blank_cursor ();
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
|
||||
nsbitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
|
||||
pixelsWide:width
|
||||
pixelsHigh:height
|
||||
bitsPerSample:8
|
||||
samplesPerPixel:4
|
||||
hasAlpha:YES
|
||||
isPlanar:NO
|
||||
colorSpaceName:NSDeviceRGBColorSpace
|
||||
bytesPerRow:0
|
||||
bitsPerPixel:0];
|
||||
pixels = [nsbitmap bitmapData];
|
||||
stride = [nsbitmap bytesPerRow];
|
||||
|
||||
downloader = gdk_texture_downloader_new (texture);
|
||||
gdk_texture_downloader_set_format (downloader, GDK_MEMORY_R8G8B8A8_PREMULTIPLIED);
|
||||
gdk_texture_downloader_download_into (downloader,
|
||||
pixels,
|
||||
stride);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
nsimage = [[NSImage alloc] init];
|
||||
[nsimage addRepresentation:nsbitmap];
|
||||
[nsimage setSize:NSMakeSize(width, height)];
|
||||
[nsbitmap release];
|
||||
|
||||
nscursor = [[NSCursor alloc] initWithImage:nsimage
|
||||
hotSpot:NSMakePoint(x, y)];
|
||||
[nsimage release];
|
||||
return nscursor;
|
||||
}
|
||||
|
||||
NSCursor *
|
||||
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||
{
|
||||
@@ -161,7 +212,17 @@ _gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
|
||||
|
||||
if (cursor != NULL)
|
||||
name = gdk_cursor_get_name (cursor);
|
||||
{
|
||||
name = gdk_cursor_get_name (cursor);
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
nscursor = create_cursor_from_texture (gdk_cursor_get_texture (cursor),
|
||||
gdk_cursor_get_hotspot_x (cursor),
|
||||
gdk_cursor_get_hotspot_y (cursor));
|
||||
return nscursor;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == NULL)
|
||||
goto load_cursor;
|
||||
|
||||
+110
-171
@@ -96,37 +96,26 @@ _gdk_macos_toplevel_surface_unminimize (GdkMacosToplevelSurface *self)
|
||||
[window deminiaturize:window];
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
GdkToplevelLayout *layout)
|
||||
static gboolean
|
||||
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
|
||||
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkMonitor *monitor;
|
||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
|
||||
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
|
||||
GdkToplevelSize size;
|
||||
GdkDisplay *display;
|
||||
GdkMonitor *monitor;
|
||||
int bounds_width, bounds_height;
|
||||
int width, height;
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
NSWindowStyleMask style_mask;
|
||||
gboolean maximize;
|
||||
gboolean fullscreen;
|
||||
|
||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
|
||||
|
||||
if (layout != self->layout)
|
||||
{
|
||||
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
|
||||
self->layout = gdk_toplevel_layout_copy (layout);
|
||||
}
|
||||
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
|
||||
return FALSE;
|
||||
|
||||
_gdk_macos_toplevel_surface_attach_to_parent (self);
|
||||
|
||||
style_mask = [nswindow styleMask];
|
||||
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
|
||||
if (monitor)
|
||||
@@ -144,58 +133,127 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
}
|
||||
|
||||
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
||||
gdk_toplevel_notify_compute_size (toplevel, &size);
|
||||
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
|
||||
|
||||
g_warn_if_fail (size.width > 0);
|
||||
g_warn_if_fail (size.height > 0);
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
|
||||
if (gdk_toplevel_layout_get_resizable (layout))
|
||||
if (self->layout != NULL &&
|
||||
gdk_toplevel_layout_get_resizable (self->layout))
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
mask = GDK_HINT_MIN_SIZE;
|
||||
|
||||
/* Only set 'Resizable' mask to get native resize zones if the window is
|
||||
* titled, otherwise we do this internally for CSD and do not need
|
||||
* NSWindow to do it for us. Additionally, it can mess things up when
|
||||
* doing a window resize since it can cause mouseDown to get passed
|
||||
* through to the next window.
|
||||
*/
|
||||
if ((style_mask & NSWindowStyleMaskTitled) != 0)
|
||||
style_mask |= NSWindowStyleMaskResizable;
|
||||
else
|
||||
style_mask &= ~NSWindowStyleMaskResizable;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.max_width = geometry.min_width = width;
|
||||
geometry.max_height = geometry.min_height = height;
|
||||
geometry.max_width = geometry.min_width = size.width;
|
||||
geometry.max_height = geometry.min_height = size.height;
|
||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||
|
||||
style_mask &= ~NSWindowStyleMaskResizable;
|
||||
}
|
||||
|
||||
if (style_mask != [nswindow styleMask])
|
||||
[nswindow setStyleMask:style_mask];
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (surface),
|
||||
_gdk_macos_surface_set_shadow (macos_surface,
|
||||
size.shadow.top,
|
||||
size.shadow.right,
|
||||
size.shadow.bottom,
|
||||
size.shadow.left);
|
||||
|
||||
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
|
||||
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
|
||||
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
|
||||
|
||||
GDK_DEBUG (MISC, "Resizing \"%s\" to %dx%d",
|
||||
GDK_MACOS_SURFACE (self)->title ?
|
||||
GDK_MACOS_SURFACE (self)->title :
|
||||
"untitled",
|
||||
width, height);
|
||||
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
|
||||
GDK_TOPLEVEL_STATE_MAXIMIZED |
|
||||
GDK_TOPLEVEL_STATE_TILED |
|
||||
GDK_TOPLEVEL_STATE_TOP_TILED |
|
||||
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
||||
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
||||
GDK_TOPLEVEL_STATE_LEFT_TILED |
|
||||
GDK_TOPLEVEL_STATE_MINIMIZED) ||
|
||||
[macos_surface->window inLiveResize])
|
||||
return FALSE;
|
||||
|
||||
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
|
||||
/* If we delayed a user resize until the beginning of the frame,
|
||||
* apply it now so we can start processing updates for it.
|
||||
*/
|
||||
if (macos_surface->next_layout.width > 0 &&
|
||||
macos_surface->next_layout.height > 0)
|
||||
{
|
||||
int root_x = macos_surface->next_layout.root_x;
|
||||
int root_y = macos_surface->next_layout.root_y;
|
||||
int width = macos_surface->next_layout.width;
|
||||
int height = macos_surface->next_layout.height;
|
||||
|
||||
gdk_surface_constrain_size (&geometry, mask,
|
||||
width, height,
|
||||
&width, &height);
|
||||
|
||||
macos_surface->next_layout.width = 0;
|
||||
macos_surface->next_layout.height = 0;
|
||||
|
||||
_gdk_macos_surface_move_resize (macos_surface,
|
||||
root_x, root_y,
|
||||
width, height);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_surface_constrain_size (&geometry, mask,
|
||||
size.width, size.height,
|
||||
&size.width, &size.height);
|
||||
|
||||
if ((size.width != self->last_computed_width ||
|
||||
size.height != self->last_computed_height) &&
|
||||
(size.width != surface->width ||
|
||||
size.height != surface->height))
|
||||
{
|
||||
self->last_computed_width = size.width;
|
||||
self->last_computed_height = size.height;
|
||||
|
||||
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
GdkToplevelLayout *layout)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
|
||||
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
NSWindowStyleMask style_mask;
|
||||
gboolean maximize;
|
||||
gboolean fullscreen;
|
||||
|
||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
|
||||
|
||||
if (layout != self->layout)
|
||||
{
|
||||
g_clear_pointer (&self->layout, gdk_toplevel_layout_unref);
|
||||
self->layout = gdk_toplevel_layout_copy (layout);
|
||||
}
|
||||
|
||||
_gdk_macos_toplevel_surface_attach_to_parent (self);
|
||||
_gdk_macos_toplevel_surface_compute_size (surface);
|
||||
|
||||
/* Only set 'Resizable' mask to get native resize zones if the window is
|
||||
* titled, otherwise we do this internally for CSD and do not need
|
||||
* NSWindow to do it for us. Additionally, it can mess things up when
|
||||
* doing a window resize since it can cause mouseDown to get passed
|
||||
* through to the next window.
|
||||
*/
|
||||
style_mask = [nswindow styleMask];
|
||||
if (gdk_toplevel_layout_get_resizable (layout) &&
|
||||
(style_mask & NSWindowStyleMaskTitled) != 0)
|
||||
style_mask |= NSWindowStyleMaskResizable;
|
||||
else
|
||||
style_mask &= ~NSWindowStyleMaskResizable;
|
||||
|
||||
if (style_mask != [nswindow styleMask])
|
||||
[nswindow setStyleMask:style_mask];
|
||||
|
||||
/* Maximized state */
|
||||
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
|
||||
@@ -378,125 +436,6 @@ _gdk_macos_toplevel_surface_hide (GdkSurface *surface)
|
||||
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
|
||||
{
|
||||
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
|
||||
GdkMacosSurface *macos_surface = (GdkMacosSurface *)surface;
|
||||
GdkToplevelSize size;
|
||||
GdkDisplay *display;
|
||||
GdkMonitor *monitor;
|
||||
int bounds_width, bounds_height;
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
|
||||
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
|
||||
|
||||
if (!GDK_MACOS_SURFACE (surface)->geometry_dirty)
|
||||
return FALSE;
|
||||
|
||||
GDK_MACOS_SURFACE (surface)->geometry_dirty = FALSE;
|
||||
|
||||
display = gdk_surface_get_display (surface);
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
|
||||
if (monitor)
|
||||
{
|
||||
GdkRectangle workarea;
|
||||
|
||||
gdk_macos_monitor_get_workarea (monitor, &workarea);
|
||||
bounds_width = workarea.width;
|
||||
bounds_height = workarea.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
bounds_width = G_MAXINT;
|
||||
bounds_height = G_MAXINT;
|
||||
}
|
||||
|
||||
gdk_toplevel_size_init (&size, bounds_width, bounds_height);
|
||||
gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
|
||||
|
||||
g_warn_if_fail (size.width > 0);
|
||||
g_warn_if_fail (size.height > 0);
|
||||
|
||||
if (self->layout != NULL &&
|
||||
gdk_toplevel_layout_get_resizable (self->layout))
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
mask = GDK_HINT_MIN_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.max_width = geometry.min_width = size.width;
|
||||
geometry.max_height = geometry.min_height = size.height;
|
||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||
}
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
_gdk_macos_surface_set_shadow (macos_surface,
|
||||
size.shadow.top,
|
||||
size.shadow.right,
|
||||
size.shadow.bottom,
|
||||
size.shadow.left);
|
||||
|
||||
_gdk_macos_surface_set_geometry_hints (macos_surface, &geometry, mask);
|
||||
|
||||
if (surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN |
|
||||
GDK_TOPLEVEL_STATE_MAXIMIZED |
|
||||
GDK_TOPLEVEL_STATE_TILED |
|
||||
GDK_TOPLEVEL_STATE_TOP_TILED |
|
||||
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
||||
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
||||
GDK_TOPLEVEL_STATE_LEFT_TILED |
|
||||
GDK_TOPLEVEL_STATE_MINIMIZED) ||
|
||||
[macos_surface->window inLiveResize])
|
||||
return FALSE;
|
||||
|
||||
/* If we delayed a user resize until the beginning of the frame,
|
||||
* apply it now so we can start processing updates for it.
|
||||
*/
|
||||
if (macos_surface->next_layout.width > 0 &&
|
||||
macos_surface->next_layout.height > 0)
|
||||
{
|
||||
int root_x = macos_surface->next_layout.root_x;
|
||||
int root_y = macos_surface->next_layout.root_y;
|
||||
int width = macos_surface->next_layout.width;
|
||||
int height = macos_surface->next_layout.height;
|
||||
|
||||
gdk_surface_constrain_size (&geometry, mask,
|
||||
width, height,
|
||||
&width, &height);
|
||||
|
||||
macos_surface->next_layout.width = 0;
|
||||
macos_surface->next_layout.height = 0;
|
||||
|
||||
_gdk_macos_surface_move_resize (macos_surface,
|
||||
root_x, root_y,
|
||||
width, height);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdk_surface_constrain_size (&geometry, mask,
|
||||
size.width, size.height,
|
||||
&size.width, &size.height);
|
||||
|
||||
if ((size.width != self->last_computed_width ||
|
||||
size.height != self->last_computed_height) &&
|
||||
(size.width != surface->width ||
|
||||
size.height != surface->height))
|
||||
{
|
||||
self->last_computed_width = size.width;
|
||||
self->last_computed_height = size.height;
|
||||
|
||||
_gdk_macos_surface_resize (macos_surface, size.width, size.height);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
|
||||
{
|
||||
|
||||
+1
-1
@@ -219,7 +219,7 @@ gdk_deps = [
|
||||
platform_gio_dep,
|
||||
pangocairo_dep,
|
||||
vulkan_dep,
|
||||
dmabuf_dep,
|
||||
libdrm_dep,
|
||||
png_dep,
|
||||
tiff_dep,
|
||||
jpeg_dep,
|
||||
|
||||
@@ -266,10 +266,10 @@ _XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
|
||||
|
||||
if ((*file->read) (file, bytes, 4) != 4)
|
||||
return XcursorFalse;
|
||||
*u = ((bytes[0] << 0) |
|
||||
(bytes[1] << 8) |
|
||||
(bytes[2] << 16) |
|
||||
(bytes[3] << 24));
|
||||
*u = ((((unsigned int)(bytes[0])) << 0) |
|
||||
(((unsigned int)(bytes[1])) << 8) |
|
||||
(((unsigned int)(bytes[2])) << 16) |
|
||||
(((unsigned int)(bytes[3])) << 24));
|
||||
return XcursorTrue;
|
||||
}
|
||||
|
||||
|
||||
@@ -2437,12 +2437,13 @@ apply_monitor_change (GdkWaylandMonitor *monitor)
|
||||
gboolean needs_scaling = FALSE;
|
||||
double scale;
|
||||
|
||||
if (monitor->xdg_output_done)
|
||||
if (monitor_has_xdg_output (monitor) &&
|
||||
monitor->xdg_output_geometry.width != 0 &&
|
||||
monitor->xdg_output_geometry.height != 0)
|
||||
{
|
||||
logical_geometry = monitor->xdg_output_geometry;
|
||||
needs_scaling =
|
||||
logical_geometry.width == monitor->output_geometry.width ||
|
||||
logical_geometry.height == monitor->output_geometry.height;
|
||||
needs_scaling = logical_geometry.width == monitor->output_geometry.width &&
|
||||
logical_geometry.height == monitor->output_geometry.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2453,6 +2454,7 @@ apply_monitor_change (GdkWaylandMonitor *monitor)
|
||||
if (needs_scaling)
|
||||
{
|
||||
int scale_factor = gdk_monitor_get_scale_factor (GDK_MONITOR (monitor));
|
||||
|
||||
logical_geometry.y /= scale_factor;
|
||||
logical_geometry.x /= scale_factor;
|
||||
logical_geometry.width /= scale_factor;
|
||||
|
||||
@@ -3629,7 +3629,10 @@ tablet_pad_handle_leave (void *data,
|
||||
wp_tablet_pad, surface);
|
||||
|
||||
if (pad->current_tablet)
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
{
|
||||
pad->current_tablet->pads = g_list_remove (pad->current_tablet->pads, pad);
|
||||
pad->current_tablet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -22,6 +22,7 @@ struct _GdkWaylandSubsurface
|
||||
|
||||
GdkTexture *texture;
|
||||
cairo_rectangle_int_t dest;
|
||||
graphene_rect_t source;
|
||||
|
||||
struct wl_region *opaque_region;
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ get_wl_buffer (GdkWaylandSubsurface *self,
|
||||
static gboolean
|
||||
gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
GdkTexture *texture,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_rect_t *source,
|
||||
const graphene_rect_t *dest,
|
||||
gboolean above,
|
||||
GdkSubsurface *sibling)
|
||||
{
|
||||
@@ -177,30 +178,37 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
self->dest.x = rect->origin.x;
|
||||
self->dest.y = rect->origin.y;
|
||||
self->dest.width = rect->size.width;
|
||||
self->dest.height = rect->size.height;
|
||||
self->dest.x = dest->origin.x;
|
||||
self->dest.y = dest->origin.y;
|
||||
self->dest.width = dest->size.width;
|
||||
self->dest.height = dest->size.height;
|
||||
|
||||
self->source.origin.x = source->origin.x;
|
||||
self->source.origin.y = source->origin.y;
|
||||
self->source.size.width = source->size.width;
|
||||
self->source.size.height = source->size.height;
|
||||
|
||||
scale = gdk_fractional_scale_to_double (&parent->scale);
|
||||
device_rect.origin.x = rect->origin.x * scale;
|
||||
device_rect.origin.y = rect->origin.y * scale;
|
||||
device_rect.size.width = rect->size.width * scale;
|
||||
device_rect.size.height = rect->size.height * scale;
|
||||
|
||||
device_rect.origin.x = dest->origin.x * scale;
|
||||
device_rect.origin.y = dest->origin.y * scale;
|
||||
device_rect.size.width = dest->size.width * scale;
|
||||
device_rect.size.height = dest->size.height * scale;
|
||||
|
||||
device_dest.x = device_rect.origin.x;
|
||||
device_dest.y = device_rect.origin.y;
|
||||
device_dest.width = device_rect.size.width;
|
||||
device_dest.height = device_rect.size.height;
|
||||
|
||||
if (self->dest.x != rect->origin.x ||
|
||||
self->dest.y != rect->origin.y ||
|
||||
self->dest.width != rect->size.width ||
|
||||
self->dest.height != rect->size.height)
|
||||
if (self->dest.x != dest->origin.x ||
|
||||
self->dest.y != dest->origin.y ||
|
||||
self->dest.width != dest->size.width ||
|
||||
self->dest.height != dest->size.height)
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (gdk_surface_get_display (sub->parent), OFFLOAD,
|
||||
"Non-integer coordinates %g %g %g %g for %dx%d texture, hiding subsurface %p",
|
||||
rect->origin.x, rect->origin.y,
|
||||
rect->size.width, rect->size.height,
|
||||
dest->origin.x, dest->origin.y,
|
||||
dest->size.width, dest->size.height,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture),
|
||||
self);
|
||||
@@ -296,6 +304,11 @@ gdk_wayland_subsurface_attach (GdkSubsurface *sub,
|
||||
{
|
||||
wl_subsurface_set_position (self->subsurface, self->dest.x, self->dest.y);
|
||||
wp_viewport_set_destination (self->viewport, self->dest.width, self->dest.height);
|
||||
wp_viewport_set_source (self->viewport,
|
||||
wl_fixed_from_double (self->source.origin.x),
|
||||
wl_fixed_from_double (self->source.origin.y),
|
||||
wl_fixed_from_double (self->source.size.width),
|
||||
wl_fixed_from_double (self->source.size.height));
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
@@ -370,15 +383,27 @@ gdk_wayland_subsurface_get_texture (GdkSubsurface *sub)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_get_rect (GdkSubsurface *sub,
|
||||
graphene_rect_t *rect)
|
||||
gdk_wayland_subsurface_get_dest (GdkSubsurface *sub,
|
||||
graphene_rect_t *dest)
|
||||
{
|
||||
GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub);
|
||||
|
||||
rect->origin.x = self->dest.x;
|
||||
rect->origin.y = self->dest.y;
|
||||
rect->size.width = self->dest.width;
|
||||
rect->size.height = self->dest.height;
|
||||
dest->origin.x = self->dest.x;
|
||||
dest->origin.y = self->dest.y;
|
||||
dest->size.width = self->dest.width;
|
||||
dest->size.height = self->dest.height;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_subsurface_get_source (GdkSubsurface *sub,
|
||||
graphene_rect_t *source)
|
||||
{
|
||||
GdkWaylandSubsurface *self = GDK_WAYLAND_SUBSURFACE (sub);
|
||||
|
||||
source->origin.x = self->source.origin.x;
|
||||
source->origin.y = self->source.origin.y;
|
||||
source->size.width = self->source.size.width;
|
||||
source->size.height = self->source.size.height;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -392,7 +417,8 @@ gdk_wayland_subsurface_class_init (GdkWaylandSubsurfaceClass *class)
|
||||
subsurface_class->attach = gdk_wayland_subsurface_attach;
|
||||
subsurface_class->detach = gdk_wayland_subsurface_detach;
|
||||
subsurface_class->get_texture = gdk_wayland_subsurface_get_texture;
|
||||
subsurface_class->get_rect = gdk_wayland_subsurface_get_rect;
|
||||
subsurface_class->get_source = gdk_wayland_subsurface_get_source;
|
||||
subsurface_class->get_dest = gdk_wayland_subsurface_get_dest;
|
||||
};
|
||||
|
||||
static void
|
||||
|
||||
@@ -201,17 +201,23 @@ get_egl_window_size (GdkSurface *surface,
|
||||
|
||||
if (GDK_DISPLAY_DEBUG_CHECK (display, GL_NO_FRACTIONAL))
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window", gdk_fractional_scale_to_int (&impl->scale));
|
||||
|
||||
*width = surface->width * gdk_fractional_scale_to_int (&impl->scale);
|
||||
*height = surface->height * gdk_fractional_scale_to_int (&impl->scale);
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using integer scale %d for EGL window (%d %d => %d %d)",
|
||||
gdk_fractional_scale_to_int (&impl->scale),
|
||||
surface->width, surface->height,
|
||||
*width, *height);
|
||||
}
|
||||
else
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window", gdk_fractional_scale_to_double (&impl->scale));
|
||||
|
||||
*width = gdk_fractional_scale_scale (&impl->scale, surface->width),
|
||||
*height = gdk_fractional_scale_scale (&impl->scale, surface->height);
|
||||
|
||||
GDK_DISPLAY_DEBUG (display, OPENGL, "Using fractional scale %g for EGL window (%d %d => %d %d)",
|
||||
gdk_fractional_scale_to_double (&impl->scale),
|
||||
surface->width, surface->height,
|
||||
*width, *height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -458,6 +458,49 @@ gdk_wayland_toplevel_compute_size (GdkSurface *surface)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_per_edge_tiling_info (GdkToplevelState state)
|
||||
{
|
||||
return state & (GDK_TOPLEVEL_STATE_TOP_TILED |
|
||||
GDK_TOPLEVEL_STATE_RIGHT_TILED |
|
||||
GDK_TOPLEVEL_STATE_BOTTOM_TILED |
|
||||
GDK_TOPLEVEL_STATE_LEFT_TILED);
|
||||
}
|
||||
|
||||
static GdkToplevelState
|
||||
infer_edge_constraints (GdkToplevelState state)
|
||||
{
|
||||
if (state & (GDK_TOPLEVEL_STATE_MAXIMIZED | GDK_TOPLEVEL_STATE_FULLSCREEN))
|
||||
return state;
|
||||
|
||||
if (!(state & GDK_TOPLEVEL_STATE_TILED) || !has_per_edge_tiling_info (state))
|
||||
return state |
|
||||
GDK_TOPLEVEL_STATE_TOP_RESIZABLE |
|
||||
GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE |
|
||||
GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE |
|
||||
GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
|
||||
|
||||
if (!(state & GDK_TOPLEVEL_STATE_TOP_TILED))
|
||||
state |= GDK_TOPLEVEL_STATE_TOP_RESIZABLE;
|
||||
if (!(state & GDK_TOPLEVEL_STATE_RIGHT_TILED))
|
||||
state |= GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE;
|
||||
if (!(state & GDK_TOPLEVEL_STATE_BOTTOM_TILED))
|
||||
state |= GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE;
|
||||
if (!(state & GDK_TOPLEVEL_STATE_LEFT_TILED))
|
||||
state |= GDK_TOPLEVEL_STATE_LEFT_RESIZABLE;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supports_native_edge_constraints (GdkWaylandToplevel*toplevel)
|
||||
{
|
||||
struct gtk_surface1 *gtk_surface = toplevel->display_server.gtk_surface;
|
||||
if (!gtk_surface)
|
||||
return FALSE;
|
||||
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
||||
{
|
||||
@@ -475,6 +518,9 @@ gdk_wayland_toplevel_handle_configure (GdkWaylandSurface *wayland_surface)
|
||||
new_state = wayland_toplevel->pending.state;
|
||||
wayland_toplevel->pending.state = 0;
|
||||
|
||||
if (!supports_native_edge_constraints (wayland_toplevel))
|
||||
new_state = infer_edge_constraints (new_state);
|
||||
|
||||
is_resizing = wayland_toplevel->pending.is_resizing;
|
||||
wayland_toplevel->pending.is_resizing = FALSE;
|
||||
|
||||
@@ -1990,13 +2036,7 @@ gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel,
|
||||
static gboolean
|
||||
gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
{
|
||||
GdkWaylandToplevel *wayland_toplevel = GDK_WAYLAND_TOPLEVEL (toplevel);
|
||||
struct gtk_surface1 *gtk_surface = wayland_toplevel->display_server.gtk_surface;
|
||||
|
||||
if (!gtk_surface)
|
||||
return FALSE;
|
||||
|
||||
return gtk_surface1_get_version (gtk_surface) >= GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2667,7 +2707,7 @@ gdk_wayland_toplevel_set_transient_for_exported (GdkToplevel *toplevel,
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_WAYLAND_DISPLAY (display), FALSE);
|
||||
|
||||
if (!display_wayland->xdg_importer)
|
||||
if (!display_wayland->xdg_importer && !display_wayland->xdg_importer_v2)
|
||||
{
|
||||
g_warning ("Server is missing xdg_foreign support");
|
||||
return FALSE;
|
||||
|
||||
+21
-10
@@ -892,11 +892,11 @@ pixbuf_to_hicon (GdkPixbuf *pixbuf,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
static GdkWin32HCursor *
|
||||
gdk_win32hcursor_create_for_texture (GdkWin32Display *display,
|
||||
GdkTexture *texture,
|
||||
int x,
|
||||
int y)
|
||||
HICON
|
||||
_gdk_win32_create_hicon_for_texture (GdkTexture *texture,
|
||||
gboolean is_icon,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
GdkPixbuf *pixbuf;
|
||||
@@ -906,13 +906,24 @@ gdk_win32hcursor_create_for_texture (GdkWin32Display *display,
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
width = cairo_image_surface_get_width (surface);
|
||||
height = cairo_image_surface_get_height (surface);
|
||||
|
||||
|
||||
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
|
||||
|
||||
icon = pixbuf_to_hicon (pixbuf, FALSE, x, y);
|
||||
|
||||
|
||||
icon = pixbuf_to_hicon (pixbuf, is_icon, x, y);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
static GdkWin32HCursor *
|
||||
gdk_win32hcursor_create_for_texture (GdkWin32Display *display,
|
||||
GdkTexture *texture,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
HICON icon = _gdk_win32_create_hicon_for_texture (texture, FALSE, x, y);
|
||||
|
||||
return gdk_win32_hcursor_new (display, (HCURSOR) icon, TRUE);
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ gdk_win32_gl_context_wgl_begin_frame (GdkDrawContext *draw_context,
|
||||
GDK_DRAW_CONTEXT_CLASS (gdk_win32_gl_context_wgl_parent_class)->begin_frame (draw_context, depth, update_area);
|
||||
}
|
||||
|
||||
#define PIXEL_ATTRIBUTES 17
|
||||
#define PIXEL_ATTRIBUTES 21
|
||||
|
||||
static int
|
||||
get_wgl_pfd (HDC hdc,
|
||||
@@ -176,10 +176,19 @@ get_wgl_pfd (HDC hdc,
|
||||
pixelAttribs[i++] = WGL_ALPHA_BITS_ARB;
|
||||
pixelAttribs[i++] = 8;
|
||||
|
||||
pixelAttribs[i++] = WGL_DEPTH_BITS_ARB;
|
||||
pixelAttribs[i++] = 0;
|
||||
|
||||
pixelAttribs[i++] = WGL_STENCIL_BITS_ARB;
|
||||
pixelAttribs[i++] = 0;
|
||||
|
||||
pixelAttribs[i++] = WGL_ACCUM_BITS_ARB;
|
||||
pixelAttribs[i++] = 0;
|
||||
|
||||
/* end of "Update PIXEL_ATTRIBUTES above if any groups are added here!" */
|
||||
|
||||
pixelAttribs[i++] = 0; /* end of pixelAttribs */
|
||||
g_assert (i <= PIXEL_ATTRIBUTES);
|
||||
g_assert (i == PIXEL_ATTRIBUTES);
|
||||
|
||||
if (!wglMakeCurrent (display_win32->dummy_context_wgl.hdc,
|
||||
display_win32->dummy_context_wgl.hglrc))
|
||||
@@ -205,7 +214,7 @@ get_wgl_pfd (HDC hdc,
|
||||
pfd->iPixelType = PFD_TYPE_RGBA;
|
||||
pfd->cColorBits = GetDeviceCaps (hdc, BITSPIXEL);
|
||||
pfd->cAlphaBits = 8;
|
||||
pfd->dwLayerMask = PFD_MAIN_PLANE;
|
||||
pfd->iLayerType = PFD_MAIN_PLANE;
|
||||
|
||||
best_pf = ChoosePixelFormat (hdc, pfd);
|
||||
}
|
||||
@@ -604,7 +613,7 @@ set_wgl_pixformat_for_hdc (GdkWin32Display *display_win32,
|
||||
{
|
||||
gboolean skip_acquire = FALSE;
|
||||
gboolean set_pixel_format_result = FALSE;
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
PIXELFORMATDESCRIPTOR pfd = {0};
|
||||
|
||||
/* one is only allowed to call SetPixelFormat(), and so ChoosePixelFormat()
|
||||
* one single time per window HDC
|
||||
|
||||
@@ -211,6 +211,11 @@ Win32Cursor * win32_cursor_theme_get_cursor (Win32CursorTheme *theme,
|
||||
void win32_cursor_theme_destroy (Win32CursorTheme *theme);
|
||||
Win32CursorTheme *_gdk_win32_display_get_cursor_theme (GdkWin32Display *win32_display);
|
||||
|
||||
HICON _gdk_win32_create_hicon_for_texture (GdkTexture *texture,
|
||||
gboolean is_icon,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
gboolean _gdk_win32_display_has_pending (GdkDisplay *display);
|
||||
void _gdk_win32_display_queue_events (GdkDisplay *display);
|
||||
|
||||
|
||||
@@ -4308,6 +4308,82 @@ gdk_win32_surface_set_shadow_width (GdkSurface *window,
|
||||
impl->shadow_y = top + bottom;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_set_icon_list (GdkSurface *surface,
|
||||
GList *textures)
|
||||
{
|
||||
GdkTexture *texture, *big_texture, *small_texture;
|
||||
gint big_diff, small_diff;
|
||||
gint big_w, big_h, small_w, small_h;
|
||||
gint w, h;
|
||||
gint dw, dh, diff;
|
||||
HICON small_hicon, big_hicon;
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (surface))
|
||||
return;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
/* ideal sizes for small and large icons */
|
||||
big_w = GetSystemMetrics (SM_CXICON);
|
||||
big_h = GetSystemMetrics (SM_CYICON);
|
||||
small_w = GetSystemMetrics (SM_CXSMICON);
|
||||
small_h = GetSystemMetrics (SM_CYSMICON);
|
||||
|
||||
/* find closest sized icons in the list */
|
||||
big_texture = NULL;
|
||||
small_texture = NULL;
|
||||
big_diff = 0;
|
||||
small_diff = 0;
|
||||
while (textures)
|
||||
{
|
||||
texture = (GdkTexture*) textures->data;
|
||||
w = gdk_texture_get_width (texture);
|
||||
h = gdk_texture_get_height (texture);
|
||||
|
||||
dw = ABS (w - big_w);
|
||||
dh = ABS (h - big_h);
|
||||
diff = dw*dw + dh*dh;
|
||||
if (big_texture == NULL || diff < big_diff)
|
||||
{
|
||||
big_texture = texture;
|
||||
big_diff = diff;
|
||||
}
|
||||
|
||||
dw = ABS (w - small_w);
|
||||
dh = ABS (h - small_h);
|
||||
diff = dw*dw + dh*dh;
|
||||
if (small_texture == NULL || diff < small_diff)
|
||||
{
|
||||
small_texture = texture;
|
||||
small_diff = diff;
|
||||
}
|
||||
|
||||
textures = textures->next;
|
||||
}
|
||||
|
||||
if (big_texture == NULL || small_texture == NULL)
|
||||
return;
|
||||
|
||||
/* Create the icons */
|
||||
big_hicon = big_texture ? _gdk_win32_create_hicon_for_texture (big_texture, TRUE, 0, 0) : NULL;
|
||||
small_hicon = small_texture ? _gdk_win32_create_hicon_for_texture (small_texture, TRUE, 0, 0) : NULL;
|
||||
|
||||
/* Set the icons */
|
||||
SendMessage (GDK_SURFACE_HWND (surface), WM_SETICON, ICON_BIG,
|
||||
(LPARAM)big_hicon);
|
||||
SendMessage (GDK_SURFACE_HWND (surface), WM_SETICON, ICON_SMALL,
|
||||
(LPARAM)small_hicon);
|
||||
|
||||
/* Store the icons, destroying any previous icons */
|
||||
if (impl->hicon_big)
|
||||
GDI_CALL (DestroyIcon, (impl->hicon_big));
|
||||
impl->hicon_big = big_hicon;
|
||||
if (impl->hicon_small)
|
||||
GDI_CALL (DestroyIcon, (impl->hicon_small));
|
||||
impl->hicon_small = small_hicon;
|
||||
}
|
||||
|
||||
double
|
||||
_gdk_win32_surface_get_scale (GdkSurface *surface)
|
||||
@@ -4738,6 +4814,8 @@ gdk_win32_toplevel_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
|
||||
gdk_win32_surface_set_icon_list (surface, g_value_get_pointer (value));
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
|
||||
|
||||
@@ -1430,6 +1430,8 @@ gdk_x11_display_open (const char *display_name)
|
||||
int maj, min;
|
||||
char *cm_name;
|
||||
gboolean frame_extents;
|
||||
gboolean rgba;
|
||||
gboolean composited;
|
||||
|
||||
XInitThreads ();
|
||||
|
||||
@@ -1646,7 +1648,10 @@ gdk_x11_display_open (const char *display_name)
|
||||
|
||||
frame_extents = gdk_x11_screen_supports_net_wm_hint (gdk_x11_display_get_screen (display),
|
||||
g_intern_static_string ("_GTK_FRAME_EXTENTS"));
|
||||
gdk_display_set_shadow_width (display, frame_extents);
|
||||
rgba = gdk_display_is_rgba (display);
|
||||
composited = gdk_display_is_composited (display);
|
||||
|
||||
gdk_display_set_shadow_width (display, frame_extents && rgba && composited);
|
||||
|
||||
gdk_display_emit_opened (display);
|
||||
|
||||
@@ -3010,6 +3015,8 @@ gdk_x11_display_init_gl_backend (GdkX11Display *self,
|
||||
|
||||
self->egl_version = epoxy_egl_version (egl_display);
|
||||
|
||||
XFree (visinfo);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -2655,6 +2655,7 @@ gdk_x11_surface_get_geometry (GdkSurface *surface,
|
||||
{
|
||||
GdkX11Surface *impl;
|
||||
Window root;
|
||||
Window child;
|
||||
int tx;
|
||||
int ty;
|
||||
guint twidth;
|
||||
@@ -2669,7 +2670,11 @@ gdk_x11_surface_get_geometry (GdkSurface *surface,
|
||||
XGetGeometry (GDK_SURFACE_XDISPLAY (surface),
|
||||
GDK_SURFACE_XID (surface),
|
||||
&root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
|
||||
|
||||
|
||||
XTranslateCoordinates (GDK_SURFACE_XDISPLAY (surface),
|
||||
GDK_SURFACE_XID (surface),
|
||||
root, 0, 0, &tx, &ty, &child);
|
||||
|
||||
if (x)
|
||||
*x = tx / impl->surface_scale;
|
||||
if (y)
|
||||
|
||||
@@ -1066,8 +1066,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
|
||||
gsk_gl_profiler_begin_gpu_region (self->gl_profiler);
|
||||
gsk_profiler_timer_begin (self->profiler, self->metrics.cpu_time);
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glDepthFunc (GL_LEQUAL);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
|
||||
/* Pre-multiplied alpha */
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
@@ -4322,7 +4322,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_push_modelview (job, transform);
|
||||
gsk_transform_unref (transform);
|
||||
gsk_gl_render_job_transform_bounds (job, offscreen->bounds, &viewport);
|
||||
graphene_rect_scale (&viewport, downscale_x, downscale_y, &viewport);
|
||||
gsk_rect_scale (&viewport, downscale_x, downscale_y, &viewport);
|
||||
}
|
||||
|
||||
if (downscale_x == 1)
|
||||
@@ -4416,7 +4416,7 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
|
||||
float scale_x = flipped_x ? - downscale_x : downscale_x;
|
||||
float scale_y = flipped_y ? - downscale_y : downscale_y;
|
||||
|
||||
graphene_rect_scale (&job->current_clip->rect.bounds, scale_x, scale_y, &new_clip.bounds);
|
||||
gsk_rect_scale (&job->current_clip->rect.bounds, scale_x, scale_y, &new_clip.bounds);
|
||||
rounded_rect_scale_corners (&job->current_clip->rect, &new_clip, scale_x, scale_y);
|
||||
gsk_gl_render_job_push_clip (job, &new_clip);
|
||||
reset_clip = TRUE;
|
||||
|
||||
+15
-2
@@ -1,5 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
|
||||
#include "gskglbufferprivate.h"
|
||||
|
||||
struct _GskGLBuffer
|
||||
@@ -14,6 +16,9 @@ struct _GskGLBuffer
|
||||
|
||||
G_DEFINE_TYPE (GskGLBuffer, gsk_gl_buffer, GSK_TYPE_GPU_BUFFER)
|
||||
|
||||
static guint profiler_buffer_uploads_id;
|
||||
static gint64 profiler_buffer_uploads;
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_finalize (GObject *object)
|
||||
{
|
||||
@@ -34,13 +39,19 @@ gsk_gl_buffer_map (GskGpuBuffer *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer)
|
||||
gsk_gl_buffer_unmap (GskGpuBuffer *buffer,
|
||||
gsize used)
|
||||
{
|
||||
GskGLBuffer *self = GSK_GL_BUFFER (buffer);
|
||||
|
||||
if (used == 0)
|
||||
return;
|
||||
|
||||
gsk_gl_buffer_bind (self);
|
||||
|
||||
glBufferSubData (self->target, 0, gsk_gpu_buffer_get_size (buffer), self->data);
|
||||
profiler_buffer_uploads += used;
|
||||
glBufferSubData (self->target, 0, used, self->data);
|
||||
gdk_profiler_set_int_counter (profiler_buffer_uploads_id, profiler_buffer_uploads);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -53,6 +64,8 @@ gsk_gl_buffer_class_init (GskGLBufferClass *klass)
|
||||
buffer_class->unmap = gsk_gl_buffer_unmap;
|
||||
|
||||
gobject_class->finalize = gsk_gl_buffer_finalize;
|
||||
|
||||
profiler_buffer_uploads_id = gdk_profiler_define_int_counter ("ngl-buffer-uploads", "Number of bytes uploaded to GPU");
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
@@ -473,6 +474,7 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
||||
guint n_external_textures,
|
||||
GError **error)
|
||||
{
|
||||
G_GNUC_UNUSED gint64 begin_time = GDK_PROFILER_CURRENT_TIME;
|
||||
GLuint vertex_shader_id, fragment_shader_id, program_id;
|
||||
GLint link_status;
|
||||
|
||||
@@ -527,6 +529,11 @@ gsk_gl_device_load_program (GskGLDevice *self,
|
||||
return 0;
|
||||
}
|
||||
|
||||
gdk_profiler_end_markf (begin_time,
|
||||
"Compile Program",
|
||||
"name=%s id=%u frag=%u vert=%u",
|
||||
op_class->shader_name, program_id, fragment_shader_id, vertex_shader_id);
|
||||
|
||||
return program_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -144,8 +144,7 @@ gsk_gl_frame_submit (GskGpuFrame *frame,
|
||||
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glDepthFunc (GL_LEQUAL);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
if (vertex_buffer)
|
||||
|
||||
@@ -195,6 +195,8 @@ gsk_gl_image_new_for_texture (GskGLDevice *device,
|
||||
if (format != real_format)
|
||||
flags = GSK_GPU_IMAGE_NO_BLIT |
|
||||
(gdk_memory_format_alpha (format) == GDK_MEMORY_ALPHA_STRAIGHT ? GSK_GPU_IMAGE_STRAIGHT_ALPHA : 0);
|
||||
else
|
||||
flags &= ~(GSK_GPU_IMAGE_CAN_MIPMAP | GSK_GPU_IMAGE_MIPMAP);
|
||||
|
||||
gsk_gpu_image_setup (GSK_GPU_IMAGE (self),
|
||||
flags | extra_flags,
|
||||
|
||||
@@ -28,6 +28,7 @@ gsk_gpu_blend_mode_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuBlendmodeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "blend-mode");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->bottom_id);
|
||||
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation);
|
||||
|
||||
@@ -85,7 +85,6 @@ gsk_gpu_blit_op_vk_command (GskGpuOp *op,
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case GSK_GPU_BLIT_LINEAR:
|
||||
filter = VK_FILTER_LINEAR;
|
||||
break;
|
||||
@@ -160,7 +159,6 @@ gsk_gpu_blit_op_gl_command (GskGpuOp *op,
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case GSK_GPU_BLIT_LINEAR:
|
||||
filter = GL_LINEAR;
|
||||
break;
|
||||
|
||||
@@ -31,6 +31,7 @@ gsk_gpu_blur_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuBlurInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "blur");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
g_string_append_printf (string, "%g,%g ", instance->blur_direction[0], instance->blur_direction[1]);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
|
||||
@@ -36,6 +36,7 @@ gsk_gpu_border_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuBorderInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "border");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rounded_rect (string, instance->outline);
|
||||
|
||||
gsk_gpu_print_rgba (string, (const float *) &instance->border_colors[0]);
|
||||
|
||||
@@ -31,6 +31,7 @@ gsk_gpu_box_shadow_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuBoxshadowInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, shader->variation & VARIATION_INSET ? "inset-shadow" : "outset-shadow");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rounded_rect (string, instance->outline);
|
||||
gsk_gpu_print_rgba (string, instance->color);
|
||||
g_string_append_printf (string, "%g %g %g %g ",
|
||||
|
||||
@@ -45,8 +45,9 @@ gsk_gpu_buffer_map (GskGpuBuffer *self)
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_buffer_unmap (GskGpuBuffer *self)
|
||||
gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||
gsize size)
|
||||
{
|
||||
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self);
|
||||
GSK_GPU_BUFFER_GET_CLASS (self)->unmap (self, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ struct _GskGpuBufferClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
guchar * (* map) (GskGpuBuffer *self);
|
||||
void (* unmap) (GskGpuBuffer *self);
|
||||
void (* unmap) (GskGpuBuffer *self,
|
||||
gsize used);
|
||||
};
|
||||
|
||||
GType gsk_gpu_buffer_get_type (void) G_GNUC_CONST;
|
||||
@@ -34,7 +35,8 @@ void gsk_gpu_buffer_setup (GskGpuB
|
||||
gsize gsk_gpu_buffer_get_size (GskGpuBuffer *self);
|
||||
|
||||
guchar * gsk_gpu_buffer_map (GskGpuBuffer *self);
|
||||
void gsk_gpu_buffer_unmap (GskGpuBuffer *self);
|
||||
void gsk_gpu_buffer_unmap (GskGpuBuffer *self,
|
||||
gsize used);
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuBuffer, g_object_unref)
|
||||
|
||||
@@ -30,6 +30,14 @@ gsk_gpu_clip_init_rect (GskGpuClip *clip,
|
||||
gsk_rounded_rect_init_from_rect (&clip->rect, rect, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_clip_init_rounded_rect (GskGpuClip *self,
|
||||
const GskRoundedRect *rect)
|
||||
{
|
||||
self->type = GSK_GPU_CLIP_ROUNDED;
|
||||
gsk_rounded_rect_init_copy (&self->rect, rect);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_clip_init_copy (GskGpuClip *self,
|
||||
const GskGpuClip *src)
|
||||
@@ -129,6 +137,13 @@ gsk_gpu_clip_intersect_rounded_rect (GskGpuClip *dest,
|
||||
break;
|
||||
|
||||
case GSK_GPU_CLIP_NONE:
|
||||
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
||||
if (gsk_gpu_clip_init_after_intersection (dest, res))
|
||||
break;
|
||||
/* XXX: This may grow the bounds quite substantially */
|
||||
gsk_gpu_clip_init_rounded_rect (dest, rounded);
|
||||
break;
|
||||
|
||||
case GSK_GPU_CLIP_CONTAINED:
|
||||
case GSK_GPU_CLIP_RECT:
|
||||
res = gsk_rounded_rect_intersect_with_rect (rounded, &src->rect.bounds, &dest->rect);
|
||||
|
||||
@@ -16,6 +16,7 @@ typedef enum {
|
||||
GSK_GPU_CLIP_ALL_CLIPPED,
|
||||
/* No clipping is necessary, but the clip rect is set
|
||||
* to the actual bounds of the underlying framebuffer
|
||||
* or handled via the scissor.
|
||||
*/
|
||||
GSK_GPU_CLIP_NONE,
|
||||
/* The clip exists outside the rect, so clipping must
|
||||
|
||||
@@ -27,6 +27,7 @@ gsk_gpu_colorize_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuColorizeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "colorize");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
gsk_gpu_print_rgba (string, instance->color);
|
||||
|
||||
@@ -27,6 +27,7 @@ gsk_gpu_color_matrix_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuColormatrixInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "color-matrix");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
@@ -28,6 +28,7 @@ gsk_gpu_color_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuColorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "color");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_rgba (string, instance->color);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
@@ -29,6 +29,7 @@ gsk_gpu_conic_gradient_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuConicgradientInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "conic-gradient");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ gsk_gpu_cross_fade_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuCrossfadeInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "cross-fade");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->start_id);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->end_id);
|
||||
|
||||
+18
-7
@@ -11,6 +11,7 @@
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
#include "gsk/gskdebugprivate.h"
|
||||
#include "gsk/gskprivate.h"
|
||||
|
||||
#define MAX_SLICES_PER_ATLAS 64
|
||||
|
||||
@@ -905,6 +906,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
GskGpuImage *image;
|
||||
gsize atlas_x, atlas_y, padding;
|
||||
float subpixel_x, subpixel_y;
|
||||
PangoFont *scaled_font;
|
||||
|
||||
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
|
||||
if (cache)
|
||||
@@ -916,13 +918,20 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
return cache->image;
|
||||
}
|
||||
|
||||
/* Note: we want to scale the font to the required size *and* ensure that
|
||||
* metrics hinting is off. The latter is necessary since pango lets metrics
|
||||
* hinting influence the rendering of hexboxes, and we get bad outcomes if
|
||||
* that happens.
|
||||
*/
|
||||
scaled_font = gsk_reload_font (font, scale, CAIRO_HINT_METRICS_OFF, CAIRO_HINT_STYLE_DEFAULT, CAIRO_ANTIALIAS_DEFAULT);
|
||||
|
||||
subpixel_x = (flags & 3) / 4.f;
|
||||
subpixel_y = ((flags >> 2) & 3) / 4.f;
|
||||
pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
|
||||
origin.x = floor (ink_rect.x * scale / PANGO_SCALE + subpixel_x);
|
||||
origin.y = floor (ink_rect.y * scale / PANGO_SCALE + subpixel_y);
|
||||
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * scale / PANGO_SCALE + subpixel_x) - origin.x;
|
||||
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * scale / PANGO_SCALE + subpixel_y) - origin.y;
|
||||
pango_font_get_glyph_extents (scaled_font, glyph, &ink_rect, NULL);
|
||||
origin.x = floor (ink_rect.x * 1.0 / PANGO_SCALE + subpixel_x);
|
||||
origin.y = floor (ink_rect.y * 1.0 / PANGO_SCALE + subpixel_y);
|
||||
rect.size.width = ceil ((ink_rect.x + ink_rect.width) * 1.0 / PANGO_SCALE + subpixel_x) - origin.x;
|
||||
rect.size.height = ceil ((ink_rect.y + ink_rect.height) * 1.0 / PANGO_SCALE + subpixel_y) - origin.y;
|
||||
padding = 1;
|
||||
|
||||
image = gsk_gpu_device_add_atlas_image (self,
|
||||
@@ -956,7 +965,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
|
||||
gsk_gpu_upload_glyph_op (frame,
|
||||
cache->image,
|
||||
font,
|
||||
scaled_font,
|
||||
glyph,
|
||||
&(cairo_rectangle_int_t) {
|
||||
.x = rect.origin.x - padding,
|
||||
@@ -964,7 +973,6 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
.width = rect.size.width + 2 * padding,
|
||||
.height = rect.size.height + 2 * padding,
|
||||
},
|
||||
scale,
|
||||
&GRAPHENE_POINT_INIT (cache->origin.x + padding,
|
||||
cache->origin.y + padding));
|
||||
|
||||
@@ -973,6 +981,9 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
|
||||
|
||||
*out_bounds = cache->bounds;
|
||||
*out_origin = cache->origin;
|
||||
|
||||
g_object_unref (scaled_font);
|
||||
|
||||
return cache->image;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ gsk_gpu_download_op_vk_create (GskGpuDownloadOp *self)
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
gsk_gpu_buffer_unmap (self->buffer);
|
||||
gsk_gpu_buffer_unmap (self->buffer, 0);
|
||||
}
|
||||
|
||||
static GskGpuOp *
|
||||
|
||||
@@ -426,7 +426,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
||||
if (priv->vertex_buffer_data)
|
||||
{
|
||||
memcpy (new_data, priv->vertex_buffer_data, old_size);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer, old_size);
|
||||
}
|
||||
g_object_unref (priv->vertex_buffer);
|
||||
priv->vertex_buffer = new_buffer;
|
||||
@@ -434,7 +434,7 @@ gsk_gpu_frame_reserve_vertex_data (GskGpuFrame *self,
|
||||
}
|
||||
|
||||
priv->vertex_buffer_used = size_needed;
|
||||
|
||||
|
||||
return size_needed - size;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ gsk_gpu_frame_write_storage_buffer (GskGpuFrame *self,
|
||||
{
|
||||
g_assert (offset > 0);
|
||||
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer, 0);
|
||||
g_clear_object (&priv->storage_buffer);
|
||||
priv->storage_buffer_data = 0;
|
||||
priv->storage_buffer_used = 0;
|
||||
@@ -591,14 +591,14 @@ gsk_gpu_frame_submit (GskGpuFrame *self)
|
||||
|
||||
if (priv->vertex_buffer)
|
||||
{
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer);
|
||||
gsk_gpu_buffer_unmap (priv->vertex_buffer, priv->vertex_buffer_used);
|
||||
priv->vertex_buffer_data = NULL;
|
||||
priv->vertex_buffer_used = 0;
|
||||
}
|
||||
|
||||
if (priv->storage_buffer_data)
|
||||
{
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer);
|
||||
gsk_gpu_buffer_unmap (priv->storage_buffer, priv->storage_buffer_used);
|
||||
priv->storage_buffer_data = NULL;
|
||||
priv->storage_buffer_used = 0;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,13 @@ gsk_gpu_globals_op_print (GskGpuOp *op,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuGlobalsOp *globals = (GskGpuGlobalsOp *) op;
|
||||
GskGpuGlobalsInstance *instance = &globals->instance;
|
||||
|
||||
gsk_gpu_print_op (string, indent, "globals");
|
||||
g_string_append_printf (string, "scale %g %g ", instance->scale[0], instance->scale[1]);
|
||||
g_string_append (string, "clip ");
|
||||
gsk_gpu_print_rounded_rect (string, instance->clip);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ gsk_gpu_linear_gradient_op_print (GskGpuOp *op,
|
||||
gsk_gpu_print_op (string, indent, "repeating-linear-gradient");
|
||||
else
|
||||
gsk_gpu_print_op (string, indent, "linear-gradient");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ gsk_gpu_mask_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuMaskInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "mask");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->source_id);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->mask_id);
|
||||
|
||||
+196
-115
@@ -36,12 +36,20 @@
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskpath.h"
|
||||
#include "gskrectprivate.h"
|
||||
#include "gskvec2private.h"
|
||||
#include "gskrendernodeprivate.h"
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdksubsurfaceprivate.h"
|
||||
|
||||
/* the epsilon we allow pixels to be off due to rounding errors.
|
||||
* Chosen rather randomly.
|
||||
*/
|
||||
#define EPSILON 0.001
|
||||
|
||||
/* A note about coordinate systems
|
||||
*
|
||||
@@ -177,20 +185,20 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
||||
{
|
||||
float scale_x = viewport->size.width / width;
|
||||
float scale_y = viewport->size.height / height;
|
||||
gsk_gpu_clip_init_rect (&self->clip,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
scale_x * clip->x,
|
||||
scale_y * clip->y,
|
||||
scale_x * clip->width,
|
||||
scale_y * clip->height
|
||||
));
|
||||
gsk_gpu_clip_init_empty (&self->clip,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
scale_x * clip->x,
|
||||
scale_y * clip->y,
|
||||
scale_x * clip->width,
|
||||
scale_y * clip->height
|
||||
));
|
||||
}
|
||||
|
||||
self->modelview = NULL;
|
||||
gsk_gpu_image_get_projection_matrix (target, &self->projection);
|
||||
graphene_vec2_init (&self->scale,
|
||||
width / viewport->size.width,
|
||||
height / viewport->size.height);
|
||||
gsk_vec2_init (&self->scale,
|
||||
width / viewport->size.width,
|
||||
height / viewport->size.height);
|
||||
self->offset = GRAPHENE_POINT_INIT (-viewport->origin.x,
|
||||
-viewport->origin.y);
|
||||
self->opacity = 1.0;
|
||||
@@ -312,8 +320,8 @@ rect_round_to_pixels (const graphene_rect_t *src,
|
||||
{
|
||||
float x, y, xscale, yscale, inv_xscale, inv_yscale;
|
||||
|
||||
xscale = graphene_vec2_get_x (pixel_scale);
|
||||
yscale = graphene_vec2_get_y (pixel_scale);
|
||||
xscale = gsk_vec2_get_x (pixel_scale);
|
||||
yscale = gsk_vec2_get_y (pixel_scale);
|
||||
inv_xscale = 1.0f / xscale;
|
||||
inv_yscale = 1.0f / yscale;
|
||||
|
||||
@@ -338,8 +346,8 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
|
||||
|
||||
area.x = 0;
|
||||
area.y = 0;
|
||||
area.width = ceilf (graphene_vec2_get_x (scale) * viewport->size.width);
|
||||
area.height = ceilf (graphene_vec2_get_y (scale) * viewport->size.height);
|
||||
area.width = ceilf (gsk_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
||||
area.height = ceilf (gsk_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
||||
|
||||
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
@@ -353,10 +361,7 @@ gsk_gpu_node_processor_init_draw (GskGpuNodeProcessor *self,
|
||||
NULL,
|
||||
image,
|
||||
&area,
|
||||
&GRAPHENE_RECT_INIT (viewport->origin.x,
|
||||
viewport->origin.y,
|
||||
area.width / graphene_vec2_get_x (scale),
|
||||
area.height / graphene_vec2_get_y (scale)));
|
||||
viewport);
|
||||
|
||||
gsk_gpu_render_pass_begin_op (frame,
|
||||
image,
|
||||
@@ -565,7 +570,6 @@ extract_scale_from_transform (GskTransform *transform,
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case GSK_TRANSFORM_CATEGORY_IDENTITY:
|
||||
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
|
||||
*out_scale_x = 1.0f;
|
||||
@@ -626,8 +630,8 @@ gsk_gpu_node_processor_rect_is_integer (GskGpuNodeProcessor *self,
|
||||
cairo_rectangle_int_t *int_rect)
|
||||
{
|
||||
graphene_rect_t transformed_rect;
|
||||
float scale_x = graphene_vec2_get_x (&self->scale);
|
||||
float scale_y = graphene_vec2_get_y (&self->scale);
|
||||
float scale_x = gsk_vec2_get_x (&self->scale);
|
||||
float scale_y = gsk_vec2_get_y (&self->scale);
|
||||
|
||||
switch (gsk_transform_get_category (self->modelview))
|
||||
{
|
||||
@@ -736,6 +740,30 @@ gsk_gpu_node_processor_image_op (GskGpuNodeProcessor *self,
|
||||
}
|
||||
}
|
||||
|
||||
static GskGpuImage *
|
||||
gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_rect_t *viewport,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskGpuNodeProcessor self;
|
||||
GskGpuImage *image;
|
||||
|
||||
image = gsk_gpu_node_processor_init_draw (&self,
|
||||
frame,
|
||||
gsk_render_node_get_preferred_depth (node),
|
||||
scale,
|
||||
viewport);
|
||||
if (image == NULL)
|
||||
return NULL;
|
||||
|
||||
gsk_gpu_node_processor_add_node (&self, node);
|
||||
|
||||
gsk_gpu_node_processor_finish_draw (&self, image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
* gsk_gpu_get_node_as_image:
|
||||
* @frame: frame to render in
|
||||
@@ -765,7 +793,6 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
|
||||
GskRenderNode *node,
|
||||
graphene_rect_t *out_bounds)
|
||||
{
|
||||
graphene_rect_t clipped;
|
||||
GskGpuImage *result;
|
||||
|
||||
switch ((guint) gsk_render_node_get_node_type (node))
|
||||
@@ -788,37 +815,29 @@ gsk_gpu_get_node_as_image (GskGpuFrame *frame,
|
||||
}
|
||||
|
||||
case GSK_CAIRO_NODE:
|
||||
gsk_rect_intersection (clip_bounds, &node->bounds, &clipped);
|
||||
if (gsk_rect_is_empty (&clipped))
|
||||
return NULL;
|
||||
|
||||
result = gsk_gpu_upload_cairo_op (frame,
|
||||
scale,
|
||||
&clipped,
|
||||
clip_bounds,
|
||||
(GskGpuCairoFunc) gsk_render_node_draw_fallback,
|
||||
gsk_render_node_ref (node),
|
||||
(GDestroyNotify) gsk_render_node_unref);
|
||||
|
||||
g_object_ref (result);
|
||||
|
||||
*out_bounds = clipped;
|
||||
*out_bounds = *clip_bounds;
|
||||
return result;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gsk_rect_intersection (clip_bounds, &node->bounds, &clipped);
|
||||
if (gsk_rect_is_empty (&clipped))
|
||||
return NULL;
|
||||
|
||||
GSK_DEBUG (FALLBACK, "Offscreening node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
|
||||
result = gsk_gpu_render_pass_op_offscreen (frame,
|
||||
scale,
|
||||
&clipped,
|
||||
node);
|
||||
result = gsk_gpu_node_processor_create_offscreen (frame,
|
||||
scale,
|
||||
clip_bounds,
|
||||
node);
|
||||
|
||||
*out_bounds = clipped;
|
||||
*out_bounds = *clip_bounds;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -939,9 +958,13 @@ gsk_gpu_node_processor_get_node_as_image (GskGpuNodeProcessor *self,
|
||||
{
|
||||
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip))
|
||||
return NULL;
|
||||
clip_bounds = &clip;
|
||||
}
|
||||
rect_round_to_pixels (clip_bounds, &self->scale, &self->offset, &clip);
|
||||
else
|
||||
{
|
||||
if (!gsk_rect_intersection (clip_bounds, &node->bounds, &clip))
|
||||
return NULL;
|
||||
}
|
||||
rect_round_to_pixels (&clip, &self->scale, &self->offset, &clip);
|
||||
|
||||
image = gsk_gpu_get_node_as_image (self->frame,
|
||||
&clip,
|
||||
@@ -986,43 +1009,29 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
||||
graphene_vec2_t direction;
|
||||
graphene_rect_t clip_rect, intermediate_rect;
|
||||
graphene_point_t real_offset;
|
||||
int width, height;
|
||||
float clip_radius;
|
||||
|
||||
clip_radius = gsk_cairo_blur_compute_pixels (blur_radius / 2.0);
|
||||
|
||||
/* FIXME: Handle clip radius growing the clip too much */
|
||||
gsk_gpu_node_processor_get_clip_bounds (self, &clip_rect);
|
||||
clip_rect.origin.x -= shadow_offset->x;
|
||||
clip_rect.origin.y -= shadow_offset->y;
|
||||
graphene_rect_inset (&clip_rect, 0.f, -clip_radius);
|
||||
if (!gsk_rect_intersection (rect, &clip_rect, &intermediate_rect))
|
||||
return;
|
||||
|
||||
width = ceilf (graphene_vec2_get_x (&self->scale) * intermediate_rect.size.width);
|
||||
height = ceilf (graphene_vec2_get_y (&self->scale) * intermediate_rect.size.height);
|
||||
rect_round_to_pixels (&intermediate_rect, &self->scale, &self->offset, &intermediate_rect);
|
||||
|
||||
intermediate = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (self->frame),
|
||||
FALSE,
|
||||
source_depth,
|
||||
width, height);
|
||||
|
||||
gsk_gpu_node_processor_init (&other,
|
||||
self->frame,
|
||||
source_desc,
|
||||
intermediate,
|
||||
&(cairo_rectangle_int_t) { 0, 0, width, height },
|
||||
&GRAPHENE_RECT_INIT (intermediate_rect.origin.x,
|
||||
intermediate_rect.origin.y,
|
||||
width / graphene_vec2_get_x (&self->scale),
|
||||
height / graphene_vec2_get_y (&self->scale)));
|
||||
|
||||
gsk_gpu_render_pass_begin_op (other.frame,
|
||||
intermediate,
|
||||
&(cairo_rectangle_int_t) { 0, 0, width, height },
|
||||
GSK_RENDER_PASS_OFFSCREEN);
|
||||
intermediate = gsk_gpu_node_processor_init_draw (&other,
|
||||
self->frame,
|
||||
source_depth,
|
||||
&self->scale,
|
||||
&intermediate_rect);
|
||||
|
||||
gsk_gpu_node_processor_sync_globals (&other, 0);
|
||||
|
||||
graphene_vec2_init (&direction, blur_radius, 0.0f);
|
||||
gsk_vec2_init (&direction, blur_radius, 0.0f);
|
||||
gsk_gpu_blur_op (other.frame,
|
||||
gsk_gpu_clip_get_shader_clip (&other.clip, &other.offset, &intermediate_rect),
|
||||
source_desc,
|
||||
@@ -1032,15 +1041,11 @@ gsk_gpu_node_processor_blur_op (GskGpuNodeProcessor *self,
|
||||
source_rect,
|
||||
&direction);
|
||||
|
||||
gsk_gpu_render_pass_end_op (other.frame,
|
||||
intermediate,
|
||||
GSK_RENDER_PASS_OFFSCREEN);
|
||||
|
||||
gsk_gpu_node_processor_finish (&other);
|
||||
gsk_gpu_node_processor_finish_draw (&other, intermediate);
|
||||
|
||||
real_offset = GRAPHENE_POINT_INIT (self->offset.x + shadow_offset->x,
|
||||
self->offset.y + shadow_offset->y);
|
||||
graphene_vec2_init (&direction, 0.0f, blur_radius);
|
||||
gsk_vec2_init (&direction, 0.0f, blur_radius);
|
||||
intermediate_descriptor = gsk_gpu_node_processor_add_image (self, intermediate, GSK_GPU_SAMPLER_TRANSPARENT);
|
||||
if (shadow_color)
|
||||
{
|
||||
@@ -1324,7 +1329,7 @@ gsk_gpu_node_processor_add_node_clipped (GskGpuNodeProcessor *self,
|
||||
gsk_gpu_clip_init_copy (&self->clip, &old_clip);
|
||||
return;
|
||||
}
|
||||
else if (self->clip.type == GSK_GPU_CLIP_RECT &&
|
||||
else if ((self->clip.type == GSK_GPU_CLIP_RECT || self->clip.type == GSK_GPU_CLIP_CONTAINED) &&
|
||||
gsk_rect_contains_rect (&self->clip.rect.bounds, &clip))
|
||||
{
|
||||
self->clip.type = GSK_GPU_CLIP_NONE;
|
||||
@@ -1577,8 +1582,8 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
gsk_gpu_clip_scale (&self->clip, &old_clip, scale_x, scale_y);
|
||||
self->offset.x = (self->offset.x + dx) / scale_x;
|
||||
self->offset.y = (self->offset.y + dy) / scale_y;
|
||||
graphene_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
gsk_vec2_init (&self->scale, fabs (scale_x), fabs (scale_y));
|
||||
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
self->modelview = gsk_transform_scale (self->modelview,
|
||||
scale_x / fabs (scale_x),
|
||||
scale_y / fabs (scale_y));
|
||||
@@ -1607,7 +1612,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
inverse = gsk_transform_invert (gsk_transform_ref (clip_transform));
|
||||
gsk_transform_transform_bounds (inverse, &old_clip.rect.bounds, &new_bounds);
|
||||
gsk_transform_unref (inverse);
|
||||
gsk_gpu_clip_init_contained (&self->clip, &new_bounds);
|
||||
gsk_gpu_clip_init_empty (&self->clip, &new_bounds);
|
||||
}
|
||||
else if (!gsk_gpu_clip_transform (&self->clip, &old_clip, clip_transform, &child->bounds))
|
||||
{
|
||||
@@ -1638,17 +1643,20 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
old_modelview = gsk_transform_ref (self->modelview);
|
||||
|
||||
self->modelview = gsk_transform_scale (self->modelview,
|
||||
graphene_vec2_get_x (&self->scale),
|
||||
graphene_vec2_get_y (&self->scale));
|
||||
gsk_vec2_get_x (&self->scale),
|
||||
gsk_vec2_get_y (&self->scale));
|
||||
self->modelview = gsk_transform_transform (self->modelview, clip_transform);
|
||||
gsk_transform_unref (clip_transform);
|
||||
|
||||
extract_scale_from_transform (self->modelview, &scale_x, &scale_y);
|
||||
|
||||
old_pixels = graphene_vec2_get_x (&old_scale) * graphene_vec2_get_y (&old_scale) *
|
||||
old_clip.rect.bounds.size.width * old_clip.rect.bounds.size.height;
|
||||
new_pixels = scale_x * scale_y * self->clip.rect.bounds.size.width * self->clip.rect.bounds.size.height;
|
||||
if (new_pixels > 2 * old_pixels)
|
||||
old_pixels = MAX (gsk_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||
gsk_vec2_get_y (&old_scale) * old_clip.rect.bounds.size.height);
|
||||
new_pixels = MAX (scale_x * self->clip.rect.bounds.size.width,
|
||||
scale_y * self->clip.rect.bounds.size.height);
|
||||
|
||||
/* Check that our offscreen doesn't get too big. 1.5 ~ sqrt(2) */
|
||||
if (new_pixels > 1.5 * old_pixels)
|
||||
{
|
||||
float forced_downscale = 2 * old_pixels / new_pixels;
|
||||
scale_x *= forced_downscale;
|
||||
@@ -1656,7 +1664,7 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
}
|
||||
|
||||
self->modelview = gsk_transform_scale (self->modelview, 1 / scale_x, 1 / scale_y);
|
||||
graphene_vec2_init (&self->scale, scale_x, scale_y);
|
||||
gsk_vec2_init (&self->scale, scale_x, scale_y);
|
||||
self->offset = *graphene_point_zero ();
|
||||
}
|
||||
break;
|
||||
@@ -1728,8 +1736,8 @@ gsk_gpu_node_processor_create_transform_pattern (GskGpuPatternWriter *self,
|
||||
self->bounds.size.width *= inv_sx;
|
||||
self->bounds.size.height *= inv_sy;
|
||||
self->offset = GRAPHENE_POINT_INIT (0, 0);
|
||||
graphene_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
||||
graphene_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
gsk_vec2_init (&self->scale, fabs (sx), fabs (sy));
|
||||
gsk_vec2_multiply (&self->scale, &old_scale, &self->scale);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1813,8 +1821,8 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
scale_x = graphene_vec2_get_x (&self->scale);
|
||||
scale_y = graphene_vec2_get_y (&self->scale);
|
||||
scale_x = gsk_vec2_get_x (&self->scale);
|
||||
scale_y = gsk_vec2_get_y (&self->scale);
|
||||
clipped = GRAPHENE_RECT_INIT (int_clipped.x / scale_x, int_clipped.y / scale_y,
|
||||
int_clipped.width / scale_x, int_clipped.height / scale_y);
|
||||
shader_clip = gsk_gpu_clip_get_shader_clip (&self->clip, graphene_point_zero(), &clipped);
|
||||
@@ -1941,8 +1949,8 @@ gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||
}
|
||||
|
||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||
{
|
||||
guint32 descriptor;
|
||||
|
||||
@@ -2008,8 +2016,8 @@ gsk_gpu_node_processor_create_texture_pattern (GskGpuPatternWriter *self,
|
||||
}
|
||||
|
||||
if (gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_MIPMAP) &&
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * graphene_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * graphene_vec2_get_y (&self->scale)))
|
||||
(gdk_texture_get_width (texture) > 2 * node->bounds.size.width * gsk_vec2_get_x (&self->scale) ||
|
||||
gdk_texture_get_height (texture) > 2 * node->bounds.size.height * gsk_vec2_get_y (&self->scale)))
|
||||
{
|
||||
image = gsk_gpu_node_processor_ensure_image (self->frame,
|
||||
image,
|
||||
@@ -2052,20 +2060,28 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
guint32 descriptor;
|
||||
gboolean need_mipmap, need_offscreen;
|
||||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
!graphene_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
gsk_vec2_equal (&self->scale, graphene_vec2_one ());
|
||||
if (need_offscreen)
|
||||
{
|
||||
GskGpuImage *offscreen;
|
||||
graphene_rect_t clip_bounds;
|
||||
|
||||
if (!gsk_gpu_node_processor_clip_node_bounds (self, node, &clip_bounds))
|
||||
return;
|
||||
gsk_gpu_node_processor_get_clip_bounds (self, &clip_bounds);
|
||||
/* first round to pixel boundaries, so we make sure the full pixels are covered */
|
||||
rect_round_to_pixels (&clip_bounds, &self->scale, &self->offset, &clip_bounds);
|
||||
/* then expand by half a pixel so that pixels needed for eventual linear
|
||||
* filtering are available */
|
||||
graphene_rect_inset (&clip_bounds, -0.5, -0.5);
|
||||
/* finally, round to full pixels */
|
||||
gsk_rect_round_larger (&clip_bounds);
|
||||
offscreen = gsk_gpu_render_pass_op_offscreen (self->frame,
|
||||
graphene_vec2_one (),
|
||||
&clip_bounds,
|
||||
node);
|
||||
/* now intersect with actual node bounds */
|
||||
if (!gsk_rect_intersection (&clip_bounds, &node->bounds, &clip_bounds))
|
||||
return;
|
||||
offscreen = gsk_gpu_node_processor_create_offscreen (self->frame,
|
||||
graphene_vec2_one (),
|
||||
&clip_bounds,
|
||||
node);
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, offscreen, GSK_GPU_SAMPLER_DEFAULT);
|
||||
gsk_gpu_texture_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
@@ -2986,6 +3002,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
float scale, inv_scale;
|
||||
GdkRGBA color;
|
||||
gboolean glyph_align;
|
||||
gboolean hinting;
|
||||
|
||||
if (self->opacity < 1.0 &&
|
||||
gsk_text_node_has_color_glyphs (node))
|
||||
@@ -2994,9 +3011,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN) &&
|
||||
gsk_transform_get_category (self->modelview) >= GSK_TRANSFORM_CATEGORY_2D;
|
||||
device = gsk_gpu_frame_get_device (self->frame);
|
||||
|
||||
color = *gsk_text_node_get_color (node);
|
||||
color.alpha *= self->opacity;
|
||||
num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||
@@ -3006,9 +3022,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
offset.x += self->offset.x;
|
||||
offset.y += self->offset.y;
|
||||
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
@@ -3019,10 +3038,21 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
if (glyph_align)
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
|
||||
/* Force glyph_origin.y to be device pixel aligned.
|
||||
* The hinter expects that.
|
||||
*/
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale * 4 + .5);
|
||||
glyph_origin.y = floor (glyph_origin.y * scale * 4 + .5);
|
||||
flags = ((int) glyph_origin.x & 3) |
|
||||
(((int) glyph_origin.y & 3) << 2);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
@@ -3030,6 +3060,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_origin.x = floor (glyph_origin.x * scale + .5) * inv_scale;
|
||||
glyph_origin.y = floor (glyph_origin.y * scale + .5) * inv_scale;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
@@ -3042,11 +3074,19 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
|
||||
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
|
||||
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
|
||||
glyph_tex_rect = GRAPHENE_RECT_INIT (-glyph_bounds.origin.x * inv_scale,
|
||||
-glyph_bounds.origin.y * inv_scale,
|
||||
gsk_gpu_image_get_width (image) * inv_scale,
|
||||
gsk_gpu_image_get_height (image) * inv_scale);
|
||||
glyph_bounds = GRAPHENE_RECT_INIT (0,
|
||||
0,
|
||||
glyph_bounds.size.width * inv_scale,
|
||||
glyph_bounds.size.height * inv_scale);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
|
||||
if (glyphs[i].attr.is_color)
|
||||
gsk_gpu_texture_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
|
||||
@@ -3082,6 +3122,8 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
guint32 tex_id;
|
||||
GskGpuImage *last_image;
|
||||
graphene_point_t offset;
|
||||
gboolean glyph_align;
|
||||
gboolean hinting;
|
||||
|
||||
if (gsk_text_node_has_color_glyphs (node))
|
||||
return FALSE;
|
||||
@@ -3094,25 +3136,58 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
offset.x += self->offset.x;
|
||||
offset.y += self->offset.y;
|
||||
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
scale = MAX (gsk_vec2_get_x (&self->scale), gsk_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
gsk_gpu_pattern_writer_append_uint (self, GSK_GPU_PATTERN_GLYPHS);
|
||||
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
||||
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
||||
|
||||
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN);
|
||||
hinting = gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE;
|
||||
|
||||
last_image = NULL;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
graphene_rect_t glyph_bounds;
|
||||
graphene_point_t glyph_offset;
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
GskGpuGlyphLookupFlags flags;
|
||||
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
|
||||
if (hinting && glyph_align)
|
||||
{
|
||||
/* Force glyph_origin.y to be device pixel aligned.
|
||||
* The hinter expects that.
|
||||
*/
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||
flags = ((int) glyph_origin.x & 3);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||
}
|
||||
else if (glyph_align)
|
||||
{
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale * 4);
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale * 4);
|
||||
flags = ((int) glyph_origin.x & 3) |
|
||||
(((int) glyph_origin.y & 3) << 2);
|
||||
glyph_origin.x = 0.25 * inv_scale * glyph_origin.x;
|
||||
glyph_origin.y = 0.25 * inv_scale * glyph_origin.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph_origin.x = roundf (glyph_origin.x * scale) * inv_scale;
|
||||
glyph_origin.y = roundf (glyph_origin.y * scale) * inv_scale;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
font,
|
||||
glyphs[i].glyph,
|
||||
0,
|
||||
flags,
|
||||
scale,
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
@@ -3125,8 +3200,8 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
last_image = image;
|
||||
}
|
||||
|
||||
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
|
||||
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
|
||||
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
|
||||
glyph_origin.y - glyph_offset.y * inv_scale);
|
||||
|
||||
gsk_gpu_pattern_writer_append_uint (self, tex_id);
|
||||
gsk_gpu_pattern_writer_append_rect (self,
|
||||
@@ -3136,7 +3211,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
glyph_bounds.size.width * inv_scale,
|
||||
glyph_bounds.size.height * inv_scale
|
||||
),
|
||||
&glyph_offset);
|
||||
&glyph_origin);
|
||||
gsk_gpu_pattern_writer_append_rect (self,
|
||||
&GRAPHENE_RECT_INIT (
|
||||
- glyph_bounds.origin.x * inv_scale,
|
||||
@@ -3144,7 +3219,7 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
gsk_gpu_image_get_width (image) * inv_scale,
|
||||
gsk_gpu_image_get_height (image) * inv_scale
|
||||
),
|
||||
&glyph_offset);
|
||||
&glyph_origin);
|
||||
|
||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||
}
|
||||
@@ -3258,10 +3333,10 @@ gsk_gpu_node_processor_repeat_tile (GskGpuNodeProcessor *self,
|
||||
}
|
||||
|
||||
GSK_DEBUG (FALLBACK, "Offscreening node '%s' for tiling", g_type_name_from_instance ((GTypeInstance *) child));
|
||||
image = gsk_gpu_render_pass_op_offscreen (self->frame,
|
||||
&self->scale,
|
||||
&clipped_child_bounds,
|
||||
child);
|
||||
image = gsk_gpu_node_processor_create_offscreen (self->frame,
|
||||
&self->scale,
|
||||
&clipped_child_bounds,
|
||||
child);
|
||||
|
||||
g_return_if_fail (image);
|
||||
|
||||
@@ -3734,6 +3809,12 @@ static void
|
||||
gsk_gpu_node_processor_add_container_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
if (self->opacity < 1.0 && !gsk_container_node_is_disjoint (node))
|
||||
{
|
||||
gsk_gpu_node_processor_add_without_opacity (self, node);
|
||||
return;
|
||||
}
|
||||
|
||||
for (guint i = 0; i < gsk_container_node_get_n_children (node); i++)
|
||||
gsk_gpu_node_processor_add_node (self, gsk_container_node_get_child (node, i));
|
||||
}
|
||||
@@ -3773,7 +3854,7 @@ static const struct
|
||||
},
|
||||
[GSK_CONTAINER_NODE] = {
|
||||
GSK_GPU_GLOBAL_MATRIX | GSK_GPU_GLOBAL_SCALE | GSK_GPU_GLOBAL_CLIP | GSK_GPU_GLOBAL_SCISSOR,
|
||||
0,
|
||||
GSK_GPU_HANDLE_OPACITY,
|
||||
gsk_gpu_node_processor_add_container_node,
|
||||
NULL,
|
||||
},
|
||||
|
||||
@@ -12,6 +12,27 @@ gsk_gpu_print_indent (GString *string,
|
||||
g_string_append_printf (string, "%*s", 2 * indent, "");
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_print_shader_info (GString *string,
|
||||
GskGpuShaderClip clip)
|
||||
{
|
||||
switch (clip)
|
||||
{
|
||||
case GSK_GPU_SHADER_CLIP_NONE:
|
||||
g_string_append (string, "🞨 ");
|
||||
break;
|
||||
case GSK_GPU_SHADER_CLIP_RECT:
|
||||
g_string_append (string, "□ ");
|
||||
break;
|
||||
case GSK_GPU_SHADER_CLIP_ROUNDED:
|
||||
g_string_append (string, "▢ ");
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_print_op (GString *string,
|
||||
guint indent,
|
||||
|
||||
@@ -17,6 +17,8 @@ void gsk_gpu_print_newline (GString
|
||||
|
||||
void gsk_gpu_print_string (GString *string,
|
||||
const char *s);
|
||||
void gsk_gpu_print_shader_info (GString *string,
|
||||
GskGpuShaderClip clip);
|
||||
void gsk_gpu_print_enum (GString *string,
|
||||
GType type,
|
||||
int value);
|
||||
|
||||
@@ -33,6 +33,7 @@ gsk_gpu_radial_gradient_op_print (GskGpuOp *op,
|
||||
gsk_gpu_print_op (string, indent, "repeating-radial-gradient");
|
||||
else
|
||||
gsk_gpu_print_op (string, indent, "radial-gradient");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ gsk_gpu_render_pass_type_to_vk_image_layout (GskRenderPassType type)
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case GSK_RENDER_PASS_PRESENT:
|
||||
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
case GSK_RENDER_PASS_OFFSCREEN:
|
||||
@@ -333,41 +332,3 @@ gsk_gpu_render_pass_end_op (GskGpuFrame *frame,
|
||||
self->target = g_object_ref (image);
|
||||
self->pass_type = pass_type;
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_rect_t *viewport,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
int width, height;
|
||||
|
||||
width = ceil (graphene_vec2_get_x (scale) * viewport->size.width);
|
||||
height = ceil (graphene_vec2_get_y (scale) * viewport->size.height);
|
||||
|
||||
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
gsk_render_node_get_preferred_depth (node),
|
||||
width, height);
|
||||
|
||||
gsk_gpu_render_pass_begin_op (frame,
|
||||
image,
|
||||
&(cairo_rectangle_int_t) { 0, 0, width, height },
|
||||
GSK_RENDER_PASS_OFFSCREEN);
|
||||
|
||||
gsk_gpu_node_processor_process (frame,
|
||||
image,
|
||||
&(cairo_rectangle_int_t) { 0, 0, width, height },
|
||||
node,
|
||||
&GRAPHENE_RECT_INIT (viewport->origin.x,
|
||||
viewport->origin.y,
|
||||
width / graphene_vec2_get_x (scale),
|
||||
height / graphene_vec2_get_y (scale)));
|
||||
|
||||
gsk_gpu_render_pass_end_op (frame,
|
||||
image,
|
||||
GSK_RENDER_PASS_OFFSCREEN);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -23,10 +23,5 @@ void gsk_gpu_render_pass_end_op (GskGpuF
|
||||
GskGpuImage *image,
|
||||
GskRenderPassType pass_type);
|
||||
|
||||
GskGpuImage * gsk_gpu_render_pass_op_offscreen (GskGpuFrame *frame,
|
||||
const graphene_vec2_t *scale,
|
||||
const graphene_rect_t *viewport,
|
||||
GskRenderNode *node);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ gsk_gpu_rounded_color_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuRoundedcolorInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "rounded-color");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rounded_rect (string, instance->outline);
|
||||
gsk_gpu_print_rgba (string, instance->color);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
@@ -30,6 +30,7 @@ gsk_gpu_straight_alpha_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuStraightalphaInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "straight-alpha");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
@@ -27,6 +27,7 @@ gsk_gpu_texture_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuTextureInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "texture");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
@@ -28,6 +28,7 @@ gsk_gpu_uber_op_print (GskGpuOp *op,
|
||||
instance = (GskGpuUberInstance *) gsk_gpu_frame_get_vertex_data (frame, shader->vertex_offset);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "uber");
|
||||
gsk_gpu_print_shader_info (string, shader->clip);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
+23
-10
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
#include "gsk/gskdebugprivate.h"
|
||||
#include "gskvec2private.h"
|
||||
|
||||
static GskGpuOp *
|
||||
gsk_gpu_upload_op_gl_command_with_area (GskGpuOp *op,
|
||||
@@ -110,8 +111,8 @@ gsk_gpu_upload_op_vk_command_with_area (GskGpuOp *op,
|
||||
data = gsk_gpu_buffer_map (*buffer);
|
||||
|
||||
draw_func (op, data, stride);
|
||||
|
||||
gsk_gpu_buffer_unmap (*buffer);
|
||||
|
||||
gsk_gpu_buffer_unmap (*buffer, area->height * stride);
|
||||
|
||||
vkCmdPipelineBarrier (state->vk_command_buffer,
|
||||
VK_PIPELINE_STAGE_HOST_BIT,
|
||||
@@ -465,8 +466,8 @@ gsk_gpu_upload_cairo_op (GskGpuFrame *frame,
|
||||
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
ceil (graphene_vec2_get_x (scale) * viewport->size.width),
|
||||
ceil (graphene_vec2_get_y (scale) * viewport->size.height));
|
||||
ceil (gsk_vec2_get_x (scale) * viewport->size.width),
|
||||
ceil (gsk_vec2_get_y (scale) * viewport->size.height));
|
||||
self->viewport = *viewport;
|
||||
self->func = func;
|
||||
self->user_data = user_data;
|
||||
@@ -485,7 +486,6 @@ struct _GskGpuUploadGlyphOp
|
||||
cairo_rectangle_int_t area;
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
float scale;
|
||||
graphene_point_t origin;
|
||||
|
||||
GskGpuBuffer *buffer;
|
||||
@@ -509,11 +509,19 @@ gsk_gpu_upload_glyph_op_print (GskGpuOp *op,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuUploadGlyphOp *self = (GskGpuUploadGlyphOp *) op;
|
||||
PangoFontDescription *desc;
|
||||
char *str;
|
||||
|
||||
desc = pango_font_describe_with_absolute_size (self->font);
|
||||
str = pango_font_description_to_string (desc);
|
||||
|
||||
gsk_gpu_print_op (string, indent, "upload-glyph");
|
||||
gsk_gpu_print_int_rect (string, &self->area);
|
||||
g_string_append_printf (string, "glyph %u @ %g ", self->glyph, self->scale);
|
||||
g_string_append_printf (string, "glyph %u font %s ", self->glyph, str);
|
||||
gsk_gpu_print_newline (string);
|
||||
|
||||
g_free (str);
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -524,6 +532,7 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
||||
GskGpuUploadGlyphOp *self = (GskGpuUploadGlyphOp *) op;
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
PangoRectangle ink_rect = { 0, };
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
@@ -531,7 +540,6 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
||||
self->area.height,
|
||||
stride);
|
||||
cairo_surface_set_device_offset (surface, self->origin.x, self->origin.y);
|
||||
cairo_surface_set_device_scale (surface, self->scale, self->scale);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
|
||||
@@ -546,12 +554,19 @@ gsk_gpu_upload_glyph_op_draw (GskGpuOp *op,
|
||||
/* Draw glyph */
|
||||
cairo_set_source_rgba (cr, 1, 1, 1, 1);
|
||||
|
||||
/* The pango code for drawing hex boxes uses the glyph width */
|
||||
if (self->glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||
pango_font_get_glyph_extents (self->font, self->glyph, &ink_rect, NULL);
|
||||
|
||||
pango_cairo_show_glyph_string (cr,
|
||||
self->font,
|
||||
&(PangoGlyphString) {
|
||||
.num_glyphs = 1,
|
||||
.glyphs = (PangoGlyphInfo[1]) { {
|
||||
.glyph = self->glyph
|
||||
.glyph = self->glyph,
|
||||
.geometry = {
|
||||
.width = ink_rect.width,
|
||||
}
|
||||
} }
|
||||
});
|
||||
|
||||
@@ -610,7 +625,6 @@ gsk_gpu_upload_glyph_op (GskGpuFrame *frame,
|
||||
PangoFont *font,
|
||||
const PangoGlyph glyph,
|
||||
const cairo_rectangle_int_t *area,
|
||||
float scale,
|
||||
const graphene_point_t *origin)
|
||||
{
|
||||
GskGpuUploadGlyphOp *self;
|
||||
@@ -621,6 +635,5 @@ gsk_gpu_upload_glyph_op (GskGpuFrame *frame,
|
||||
self->area = *area;
|
||||
self->font = g_object_ref (font);
|
||||
self->glyph = glyph;
|
||||
self->scale = scale;
|
||||
self->origin = *origin;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ void gsk_gpu_upload_glyph_op (GskGpuF
|
||||
PangoFont *font,
|
||||
PangoGlyph glyph,
|
||||
const cairo_rectangle_int_t *area,
|
||||
float scale,
|
||||
const graphene_point_t *origin);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkglcontextprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
struct _GskNglRenderer
|
||||
{
|
||||
GskGpuRenderer parent_instance;
|
||||
@@ -53,6 +55,15 @@ gsk_ngl_renderer_create_context (GskGpuRenderer *renderer,
|
||||
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
if (!gdk_gl_context_check_version (context, "3.3", "0.0"))
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_NOT_AVAILABLE,
|
||||
_("OpenGL 3.3 required"));
|
||||
g_object_unref (context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*supported = -1;
|
||||
|
||||
/* Shader compilation takes too long when texture() and get_float() calls
|
||||
|
||||
@@ -45,7 +45,8 @@ gsk_vulkan_buffer_map (GskGpuBuffer *buffer)
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer)
|
||||
gsk_vulkan_buffer_unmap (GskGpuBuffer *buffer,
|
||||
gsize size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+101
-10
@@ -58,8 +58,12 @@ struct _GskOffload
|
||||
static GdkTexture *
|
||||
find_texture_to_attach (GskOffload *self,
|
||||
GdkSubsurface *subsurface,
|
||||
const GskRenderNode *node)
|
||||
const GskRenderNode *node,
|
||||
graphene_rect_t *out_clip)
|
||||
{
|
||||
gboolean has_clip = FALSE;
|
||||
graphene_rect_t clip;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch ((int)GSK_RENDER_NODE_TYPE (node))
|
||||
@@ -82,6 +86,7 @@ find_texture_to_attach (GskOffload *self,
|
||||
case GSK_TRANSFORM_NODE:
|
||||
{
|
||||
GskTransform *t = gsk_transform_node_get_transform (node);
|
||||
|
||||
if (gsk_transform_get_category (t) < GSK_TRANSFORM_CATEGORY_2D_AFFINE)
|
||||
{
|
||||
char *s = gsk_transform_to_string (t);
|
||||
@@ -91,12 +96,69 @@ find_texture_to_attach (GskOffload *self,
|
||||
g_free (s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (has_clip)
|
||||
{
|
||||
GskTransform *inv = gsk_transform_invert (gsk_transform_ref (t));
|
||||
gsk_transform_transform_bounds (inv, &clip, &clip);
|
||||
gsk_transform_unref (inv);
|
||||
}
|
||||
|
||||
node = gsk_transform_node_get_child (node);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case GSK_CLIP_NODE:
|
||||
{
|
||||
const graphene_rect_t *c = gsk_clip_node_get_clip (node);
|
||||
|
||||
if (has_clip)
|
||||
{
|
||||
if (!gsk_rect_intersection (c, &clip, &clip))
|
||||
{
|
||||
GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD,
|
||||
"Can't offload subsurface %p: empty clip", subsurface);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clip = *c;
|
||||
has_clip = TRUE;
|
||||
}
|
||||
|
||||
node = gsk_clip_node_get_child (node);
|
||||
}
|
||||
break;
|
||||
|
||||
case GSK_TEXTURE_NODE:
|
||||
return gsk_texture_node_get_texture (node);
|
||||
{
|
||||
GdkTexture *texture = gsk_texture_node_get_texture (node);
|
||||
|
||||
if (has_clip)
|
||||
{
|
||||
float dx = node->bounds.origin.x;
|
||||
float dy = node->bounds.origin.y;
|
||||
float sx = gdk_texture_get_width (texture) / node->bounds.size.width;
|
||||
float sy = gdk_texture_get_height (texture) / node->bounds.size.height;
|
||||
|
||||
gsk_rect_intersection (&node->bounds, &clip, &clip);
|
||||
|
||||
out_clip->origin.x = (clip.origin.x - dx) * sx;
|
||||
out_clip->origin.y = (clip.origin.y - dy) * sy;
|
||||
out_clip->size.width = clip.size.width * sx;
|
||||
out_clip->size.height = clip.size.height * sy;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_clip->origin.x = 0;
|
||||
out_clip->origin.y = 0;
|
||||
out_clip->size.width = gdk_texture_get_width (texture);
|
||||
out_clip->size.height = gdk_texture_get_height (texture);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
default:
|
||||
GDK_DISPLAY_DEBUG (gdk_surface_get_display (self->surface), OFFLOAD,
|
||||
@@ -344,7 +406,7 @@ visit_node (GskOffload *self,
|
||||
|
||||
if (info->can_raise)
|
||||
{
|
||||
if (gsk_rect_intersects (&transformed_bounds, &info->rect))
|
||||
if (gsk_rect_intersects (&transformed_bounds, &info->dest))
|
||||
{
|
||||
GskRenderNodeType type = GSK_RENDER_NODE_TYPE (node);
|
||||
|
||||
@@ -513,12 +575,15 @@ complex_clip:
|
||||
}
|
||||
else
|
||||
{
|
||||
info->texture = find_texture_to_attach (self, subsurface, gsk_subsurface_node_get_child (node));
|
||||
graphene_rect_t clip;
|
||||
|
||||
info->texture = find_texture_to_attach (self, subsurface, gsk_subsurface_node_get_child (node), &clip);
|
||||
if (info->texture)
|
||||
{
|
||||
info->can_offload = TRUE;
|
||||
info->can_raise = TRUE;
|
||||
transform_bounds (self, &node->bounds, &info->rect);
|
||||
info->source = clip;
|
||||
transform_bounds (self, &node->bounds, &info->dest);
|
||||
info->place_above = self->last_info ? self->last_info->subsurface : NULL;
|
||||
self->last_info = info;
|
||||
}
|
||||
@@ -537,8 +602,9 @@ complex_clip:
|
||||
}
|
||||
|
||||
GskOffload *
|
||||
gsk_offload_new (GdkSurface *surface,
|
||||
GskRenderNode *root)
|
||||
gsk_offload_new (GdkSurface *surface,
|
||||
GskRenderNode *root,
|
||||
cairo_region_t *diff)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GskOffload *self;
|
||||
@@ -576,18 +642,23 @@ gsk_offload_new (GdkSurface *surface,
|
||||
for (gsize i = 0; i < self->n_subsurfaces; i++)
|
||||
{
|
||||
GskOffloadInfo *info = &self->subsurfaces[i];
|
||||
graphene_rect_t old_dest;
|
||||
|
||||
gdk_subsurface_get_dest (info->subsurface, &old_dest);
|
||||
|
||||
if (info->can_offload)
|
||||
{
|
||||
if (info->can_raise)
|
||||
info->is_offloaded = gdk_subsurface_attach (info->subsurface,
|
||||
info->texture,
|
||||
&info->rect,
|
||||
&info->source,
|
||||
&info->dest,
|
||||
TRUE, NULL);
|
||||
else
|
||||
info->is_offloaded = gdk_subsurface_attach (info->subsurface,
|
||||
info->texture,
|
||||
&info->rect,
|
||||
&info->source,
|
||||
&info->dest,
|
||||
info->place_above != NULL,
|
||||
info->place_above);
|
||||
}
|
||||
@@ -606,6 +677,26 @@ gsk_offload_new (GdkSurface *surface,
|
||||
GDK_DISPLAY_DEBUG (display, OFFLOAD, "Raising subsurface %p", info->subsurface);
|
||||
info->is_above = TRUE;
|
||||
}
|
||||
|
||||
if (info->is_offloaded != info->was_offloaded ||
|
||||
info->is_above != info->was_above ||
|
||||
(info->is_offloaded && !gsk_rect_equal (&info->dest, &old_dest)))
|
||||
{
|
||||
/* We changed things, need to invalidate everything */
|
||||
cairo_rectangle_int_t int_dest;
|
||||
|
||||
if (info->is_offloaded)
|
||||
{
|
||||
gsk_rect_to_cairo_grow (&info->dest, &int_dest);
|
||||
cairo_region_union_rectangle (diff, &int_dest);
|
||||
}
|
||||
if (info->was_offloaded)
|
||||
{
|
||||
gsk_rect_to_cairo_grow (&old_dest, &int_dest);
|
||||
cairo_region_union_rectangle (diff, &int_dest);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -31,7 +31,8 @@ typedef struct
|
||||
GdkSubsurface *subsurface;
|
||||
GdkTexture *texture;
|
||||
GdkSubsurface *place_above;
|
||||
graphene_rect_t rect;
|
||||
graphene_rect_t dest;
|
||||
graphene_rect_t source;
|
||||
|
||||
guint was_offloaded : 1;
|
||||
guint can_offload : 1;
|
||||
@@ -42,9 +43,10 @@ typedef struct
|
||||
guint is_above : 1;
|
||||
} GskOffloadInfo;
|
||||
|
||||
GskOffload * gsk_offload_new (GdkSurface *surface,
|
||||
GskRenderNode *root);
|
||||
void gsk_offload_free (GskOffload *self);
|
||||
GskOffload * gsk_offload_new (GdkSurface *surface,
|
||||
GskRenderNode *root,
|
||||
cairo_region_t *diff);
|
||||
void gsk_offload_free (GskOffload *self);
|
||||
|
||||
GskOffloadInfo * gsk_offload_get_subsurface_info (GskOffload *self,
|
||||
GdkSubsurface *subsurface);
|
||||
GskOffloadInfo * gsk_offload_get_subsurface_info (GskOffload *self,
|
||||
GdkSubsurface *subsurface);
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#include "gskresources.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include <cairo.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <pango/pangoft2.h>
|
||||
#include <math.h>
|
||||
|
||||
static gpointer
|
||||
register_resources (gpointer data)
|
||||
{
|
||||
@@ -15,3 +20,173 @@ gsk_ensure_resources (void)
|
||||
|
||||
g_once (®ister_resources_once, register_resources, NULL);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_reload_font:
|
||||
* @font: a `PangoFont`
|
||||
* @scale: the scale to apply
|
||||
* @hint_metris: hint metrics to use or `CAIRO_HINT_METRICS_DEFAILT` to keep the
|
||||
* hint metrics of the font unchanged
|
||||
* @hint_style: hint style to use or `CAIRO_HINT_STYLE_DEFAULT` to keep the
|
||||
* hint style of @font unchanged
|
||||
* @antialias: antialiasing to use, or `CAIRO_ANTIALIAS_DEFAULT` to keep the
|
||||
* antialias option of @font unchanged
|
||||
*
|
||||
* Returns a font that is just like @font, but uses the
|
||||
* given scale and hinting options for its glyphs and metrics.
|
||||
*
|
||||
* Returns: (transfer full): the modified `PangoFont`
|
||||
*/
|
||||
PangoFont *
|
||||
gsk_reload_font (PangoFont *font,
|
||||
float scale,
|
||||
cairo_hint_metrics_t hint_metrics,
|
||||
cairo_hint_style_t hint_style,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_font_options_t *options;
|
||||
cairo_scaled_font_t *sf;
|
||||
static PangoContext *context = NULL;
|
||||
#if !PANGO_VERSION_CHECK (1, 52, 0)
|
||||
PangoFontDescription *desc;
|
||||
FcPattern *pattern;
|
||||
double dpi;
|
||||
int size;
|
||||
#endif
|
||||
|
||||
/* These requests often come in sequentially so keep the result
|
||||
* around and re-use it if everything matches.
|
||||
*/
|
||||
static PangoFont *last_font;
|
||||
static float last_scale;
|
||||
static cairo_hint_metrics_t last_hint_metrics;
|
||||
static cairo_hint_style_t last_hint_style;
|
||||
static cairo_antialias_t last_antialias;
|
||||
static PangoFont *last_result;
|
||||
|
||||
if (last_result != NULL &&
|
||||
last_font == font &&
|
||||
last_scale == scale &&
|
||||
last_hint_metrics == hint_metrics &&
|
||||
last_hint_style == hint_style &&
|
||||
last_antialias == antialias)
|
||||
return g_object_ref (last_result);
|
||||
|
||||
last_scale = scale;
|
||||
last_hint_metrics = hint_metrics;
|
||||
last_hint_style = hint_style;
|
||||
last_antialias = antialias;
|
||||
|
||||
g_set_object (&last_font, font);
|
||||
g_clear_object (&last_result);
|
||||
|
||||
options = cairo_font_options_create ();
|
||||
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||
cairo_scaled_font_get_font_options (sf, options);
|
||||
|
||||
if (hint_metrics == CAIRO_HINT_METRICS_DEFAULT)
|
||||
hint_metrics = cairo_font_options_get_hint_metrics (options);
|
||||
|
||||
if (hint_style == CAIRO_HINT_STYLE_DEFAULT)
|
||||
hint_style = cairo_font_options_get_hint_style (options);
|
||||
|
||||
if (antialias == CAIRO_ANTIALIAS_DEFAULT)
|
||||
antialias = cairo_font_options_get_antialias (options);
|
||||
|
||||
if (1.0 == scale &&
|
||||
cairo_font_options_get_hint_metrics (options) == hint_metrics &&
|
||||
cairo_font_options_get_hint_style (options) == hint_style &&
|
||||
cairo_font_options_get_antialias (options) == antialias &&
|
||||
cairo_font_options_get_subpixel_order (options) == CAIRO_SUBPIXEL_ORDER_DEFAULT)
|
||||
{
|
||||
last_result = g_object_ref (font);
|
||||
cairo_font_options_destroy (options);
|
||||
return g_object_ref (font);
|
||||
}
|
||||
|
||||
cairo_font_options_set_hint_metrics (options, hint_metrics);
|
||||
cairo_font_options_set_hint_style (options, hint_style);
|
||||
cairo_font_options_set_antialias (options, antialias);
|
||||
cairo_font_options_set_subpixel_order (options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
|
||||
|
||||
if (!context)
|
||||
context = pango_context_new ();
|
||||
|
||||
pango_cairo_context_set_font_options (context, options);
|
||||
cairo_font_options_destroy (options);
|
||||
|
||||
#if PANGO_VERSION_CHECK (1, 52, 0)
|
||||
last_result = pango_font_map_reload_font (pango_font_get_font_map (font), font, scale, context, NULL);
|
||||
#else
|
||||
|
||||
pattern = pango_fc_font_get_pattern (PANGO_FC_FONT (font));
|
||||
if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) == FcResultMatch)
|
||||
pango_cairo_context_set_resolution (context, dpi);
|
||||
|
||||
desc = pango_font_describe (font);
|
||||
size = pango_font_description_get_size (desc);
|
||||
|
||||
if (pango_font_description_get_size_is_absolute (desc))
|
||||
pango_font_description_set_absolute_size (desc, size * scale);
|
||||
else
|
||||
pango_font_description_set_size (desc, (int) floor (size * scale + .5));
|
||||
|
||||
last_result = pango_font_map_load_font (pango_font_get_font_map (font), context, desc);
|
||||
pango_font_description_free (desc);
|
||||
#endif
|
||||
|
||||
return g_object_ref (last_result);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_get_unhinted_glyph_string_extents:
|
||||
* @glyphs: a `PangoGlyphString`
|
||||
* @font: a `PangoFont`
|
||||
* @ink_rect: (out): rectangle used to store the extents of the glyph string as drawn
|
||||
*
|
||||
* Compute the ink extents of a glyph string.
|
||||
*
|
||||
* This is like [method@Pango.GlyphString.extents], but it
|
||||
* ignores hinting of the font.
|
||||
*/
|
||||
void
|
||||
gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
|
||||
PangoFont *font,
|
||||
PangoRectangle *ink_rect)
|
||||
{
|
||||
PangoFont *unhinted;
|
||||
|
||||
unhinted = gsk_reload_font (font,
|
||||
1.0,
|
||||
CAIRO_HINT_METRICS_OFF,
|
||||
CAIRO_HINT_STYLE_NONE,
|
||||
CAIRO_ANTIALIAS_DEFAULT);
|
||||
|
||||
pango_glyph_string_extents (glyphs, unhinted, ink_rect, NULL);
|
||||
|
||||
g_object_unref (unhinted);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gsk_font_get_hint_style:
|
||||
* @font: a `PangoFont`
|
||||
*
|
||||
* Get the hint style from the cairo font options.
|
||||
*
|
||||
* Returns: the hint style
|
||||
*/
|
||||
cairo_hint_style_t
|
||||
gsk_font_get_hint_style (PangoFont *font)
|
||||
{
|
||||
cairo_scaled_font_t *sf;
|
||||
cairo_font_options_t *options;
|
||||
cairo_hint_style_t style;
|
||||
|
||||
sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||
options = cairo_font_options_create ();
|
||||
cairo_scaled_font_get_font_options (sf, options);
|
||||
style = cairo_font_options_get_hint_style (options);
|
||||
cairo_font_options_destroy (options);
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
+14
-1
@@ -2,10 +2,23 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <pango/pango.h>
|
||||
#include <cairo.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_ensure_resources (void);
|
||||
void gsk_ensure_resources (void);
|
||||
|
||||
PangoFont *gsk_reload_font (PangoFont *font,
|
||||
float scale,
|
||||
cairo_hint_metrics_t hint_metrics,
|
||||
cairo_hint_style_t hint_style,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
void gsk_get_unhinted_glyph_string_extents (PangoGlyphString *glyphs,
|
||||
PangoFont *font,
|
||||
PangoRectangle *ink_rect);
|
||||
|
||||
cairo_hint_style_t gsk_font_get_hint_style (PangoFont *font);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -101,6 +101,16 @@ gsk_rect_to_float (const graphene_rect_t *rect,
|
||||
values[3] = rect->size.height;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_rect_to_cairo_grow (const graphene_rect_t *graphene,
|
||||
cairo_rectangle_int_t *cairo)
|
||||
{
|
||||
cairo->x = floorf (graphene->origin.x);
|
||||
cairo->y = floorf (graphene->origin.y);
|
||||
cairo->width = ceilf (graphene->origin.x + graphene->size.width) - cairo->x;
|
||||
cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
gsk_rect_equal (const graphene_rect_t *r1,
|
||||
const graphene_rect_t *r2)
|
||||
@@ -149,3 +159,23 @@ gsk_rect_scale (const graphene_rect_t *r,
|
||||
res->size.width = r->size.width * sx;
|
||||
res->size.height = r->size.height * sy;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_rect_normalize (graphene_rect_t *r)
|
||||
{
|
||||
if (r->size.width < 0.f)
|
||||
{
|
||||
float size = fabsf (r->size.width);
|
||||
|
||||
r->origin.x -= size;
|
||||
r->size.width = size;
|
||||
}
|
||||
|
||||
if (r->size.height < 0.f)
|
||||
{
|
||||
float size = fabsf (r->size.height);
|
||||
|
||||
r->origin.y -= size;
|
||||
r->size.height = size;
|
||||
}
|
||||
}
|
||||
|
||||
+57
-10
@@ -46,6 +46,8 @@
|
||||
|
||||
#include "gl/gskglrenderer.h"
|
||||
#include "gpu/gskvulkanrenderer.h"
|
||||
#include "gdk/gdkvulkancontextprivate.h"
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
|
||||
#include <graphene-gobject.h>
|
||||
#include <cairo-gobject.h>
|
||||
@@ -484,25 +486,26 @@ gsk_renderer_render (GskRenderer *renderer,
|
||||
|
||||
renderer_class = GSK_RENDERER_GET_CLASS (renderer);
|
||||
|
||||
clip = cairo_region_copy (region);
|
||||
|
||||
if (renderer_class->supports_offload &&
|
||||
!GSK_RENDERER_DEBUG_CHECK (renderer, OFFLOAD_DISABLE))
|
||||
offload = gsk_offload_new (priv->surface, root);
|
||||
offload = gsk_offload_new (priv->surface, root, clip);
|
||||
else
|
||||
offload = NULL;
|
||||
|
||||
if (region == NULL || priv->prev_node == NULL || GSK_RENDERER_DEBUG_CHECK (renderer, FULL_REDRAW))
|
||||
{
|
||||
clip = cairo_region_create_rectangle (&(GdkRectangle) {
|
||||
0, 0,
|
||||
gdk_surface_get_width (priv->surface),
|
||||
gdk_surface_get_height (priv->surface)
|
||||
});
|
||||
cairo_region_union_rectangle (clip,
|
||||
&(GdkRectangle) {
|
||||
0, 0,
|
||||
gdk_surface_get_width (priv->surface),
|
||||
gdk_surface_get_height (priv->surface)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
clip = cairo_region_copy (region);
|
||||
|
||||
gsk_render_node_diff (priv->prev_node, root, clip, offload);
|
||||
gsk_render_node_diff (priv->prev_node, root, &(GskDiffData) { clip, priv->surface });
|
||||
}
|
||||
|
||||
renderer_class->render (renderer, root, clip);
|
||||
@@ -629,22 +632,65 @@ get_renderer_for_backend (GdkSurface *surface)
|
||||
return G_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gl_software_rendering (GdkSurface *surface)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkGLContext *context;
|
||||
|
||||
if (!gdk_display_prepare_gl (display, NULL))
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
context = gdk_display_get_gl_context (display);
|
||||
gdk_gl_context_make_current (context);
|
||||
|
||||
return strstr ((const char *) glGetString (GL_RENDERER), "llvmpipe") != NULL;
|
||||
}
|
||||
|
||||
static GType
|
||||
get_renderer_for_gl (GdkSurface *surface)
|
||||
{
|
||||
return GSK_TYPE_GL_RENDERER;
|
||||
if (gl_software_rendering (surface))
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
return gsk_ngl_renderer_get_type ();
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static gboolean
|
||||
vulkan_software_rendering (GdkSurface *surface)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
VkPhysicalDeviceProperties props;
|
||||
|
||||
if (!gdk_display_init_vulkan (display, NULL))
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
vkGetPhysicalDeviceProperties (display->vk_physical_device, &props);
|
||||
|
||||
return props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU;
|
||||
}
|
||||
#endif
|
||||
|
||||
static GType
|
||||
get_renderer_for_vulkan (GdkSurface *surface)
|
||||
{
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
if (vulkan_software_rendering (surface))
|
||||
return G_TYPE_INVALID;
|
||||
|
||||
return GSK_TYPE_VULKAN_RENDERER;
|
||||
#else
|
||||
return G_TYPE_INVALID;
|
||||
#endif
|
||||
}
|
||||
|
||||
static GType
|
||||
get_renderer_for_gles2 (GdkSurface *surface)
|
||||
{
|
||||
return GSK_TYPE_GL_RENDERER;
|
||||
}
|
||||
|
||||
static GType
|
||||
get_renderer_fallback (GdkSurface *surface)
|
||||
{
|
||||
@@ -658,6 +704,7 @@ static struct {
|
||||
{ get_renderer_for_env_var },
|
||||
{ get_renderer_for_backend },
|
||||
{ get_renderer_for_gl },
|
||||
{ get_renderer_for_gles2 },
|
||||
{ get_renderer_for_vulkan },
|
||||
{ get_renderer_fallback },
|
||||
};
|
||||
|
||||
+2
-20
@@ -519,8 +519,7 @@ gsk_render_node_diff_impossible (GskRenderNode *node1,
|
||||
* gsk_render_node_diff:
|
||||
* @node1: a `GskRenderNode`
|
||||
* @node2: the `GskRenderNode` to compare with
|
||||
* @region: a `cairo_region_t` to add the differences to
|
||||
* @subsurfaces: (nullable): array to add offload info to
|
||||
* @data: the diff data to use
|
||||
*
|
||||
* Compares @node1 and @node2 trying to compute the minimal region of changes.
|
||||
*
|
||||
@@ -533,28 +532,11 @@ gsk_render_node_diff_impossible (GskRenderNode *node1,
|
||||
*
|
||||
* Note that the passed in @region may already contain previous results from
|
||||
* previous node comparisons, so this function call will only add to it.
|
||||
*
|
||||
* If @subsurface_nodes is not `NULL`, then we treat subsurface nodes as
|
||||
* identical if they refer to the same subsurface and have the same bounds.
|
||||
* In this case, we collect subsurface nodes we see in @subsurface_nodes,
|
||||
* for later updating of the attached textures.
|
||||
*
|
||||
* If @subsurface_area is not `NULL`, it will collect the full area of all
|
||||
* subsurface nodes we meet.
|
||||
*/
|
||||
void
|
||||
gsk_render_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region,
|
||||
GskOffload *offload)
|
||||
{
|
||||
gsk_render_node_data_diff (node1, node2, &(GskDiffData) { region, offload });
|
||||
}
|
||||
|
||||
void
|
||||
gsk_render_node_data_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
GskDiffData *data)
|
||||
{
|
||||
if (node1 == node2)
|
||||
return;
|
||||
|
||||
+164
-163
@@ -31,7 +31,7 @@
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskoffloadprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
#include "gdk/gdkprivate.h"
|
||||
@@ -109,16 +109,6 @@ gsk_cairo_rectangle_pixel_aligned (cairo_t *cr,
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
rectangle_init_from_graphene (cairo_rectangle_int_t *cairo,
|
||||
const graphene_rect_t *graphene)
|
||||
{
|
||||
cairo->x = floorf (graphene->origin.x);
|
||||
cairo->y = floorf (graphene->origin.y);
|
||||
cairo->width = ceilf (graphene->origin.x + graphene->size.width) - cairo->x;
|
||||
cairo->height = ceilf (graphene->origin.y + graphene->size.height) - cairo->y;
|
||||
}
|
||||
|
||||
static void
|
||||
_graphene_rect_init_from_clip_extents (graphene_rect_t *rect,
|
||||
cairo_t *cr)
|
||||
@@ -175,9 +165,9 @@ gsk_color_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_color_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_color_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskColorNode *self1 = (GskColorNode *) node1;
|
||||
GskColorNode *self2 = (GskColorNode *) node2;
|
||||
@@ -245,6 +235,7 @@ gsk_color_node_new (const GdkRGBA *rgba,
|
||||
|
||||
self->color = *rgba;
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -331,9 +322,9 @@ gsk_linear_gradient_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_linear_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_linear_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskLinearGradientNode *self1 = (GskLinearGradientNode *) node1;
|
||||
GskLinearGradientNode *self2 = (GskLinearGradientNode *) node2;
|
||||
@@ -431,6 +422,7 @@ gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
graphene_point_init_from_point (&self->start, start);
|
||||
graphene_point_init_from_point (&self->end, end);
|
||||
|
||||
@@ -484,6 +476,7 @@ gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
graphene_point_init_from_point (&self->start, start);
|
||||
graphene_point_init_from_point (&self->end, end);
|
||||
|
||||
@@ -660,9 +653,9 @@ gsk_radial_gradient_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_radial_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_radial_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskRadialGradientNode *self1 = (GskRadialGradientNode *) node1;
|
||||
GskRadialGradientNode *self2 = (GskRadialGradientNode *) node2;
|
||||
@@ -776,6 +769,7 @@ gsk_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
graphene_point_init_from_point (&self->center, center);
|
||||
|
||||
self->hradius = hradius;
|
||||
@@ -845,6 +839,7 @@ gsk_repeating_radial_gradient_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
graphene_point_init_from_point (&self->center, center);
|
||||
|
||||
self->hradius = hradius;
|
||||
@@ -1151,9 +1146,9 @@ gsk_conic_gradient_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_conic_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_conic_gradient_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskConicGradientNode *self1 = (GskConicGradientNode *) node1;
|
||||
GskConicGradientNode *self2 = (GskConicGradientNode *) node2;
|
||||
@@ -1238,6 +1233,7 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
graphene_point_init_from_point (&self->center, center);
|
||||
|
||||
self->rotation = rotation;
|
||||
@@ -1503,9 +1499,9 @@ gsk_border_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_border_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_border_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskBorderNode *self1 = (GskBorderNode *) node1;
|
||||
GskBorderNode *self2 = (GskBorderNode *) node2;
|
||||
@@ -1794,9 +1790,9 @@ gsk_texture_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_texture_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskTextureNode *self1 = (GskTextureNode *) node1;
|
||||
GskTextureNode *self2 = (GskTextureNode *) node2;
|
||||
@@ -1883,6 +1879,7 @@ gsk_texture_node_new (GdkTexture *texture,
|
||||
|
||||
self->texture = g_object_ref (texture);
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
|
||||
node->preferred_depth = gdk_memory_format_get_depth (gdk_texture_get_format (texture));
|
||||
|
||||
@@ -1980,9 +1977,9 @@ gsk_texture_scale_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_texture_scale_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_texture_scale_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskTextureScaleNode *self1 = (GskTextureScaleNode *) node1;
|
||||
GskTextureScaleNode *self2 = (GskTextureScaleNode *) node2;
|
||||
@@ -2100,6 +2097,7 @@ gsk_texture_scale_node_new (GdkTexture *texture,
|
||||
|
||||
self->texture = g_object_ref (texture);
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
self->filter = filter;
|
||||
|
||||
node->preferred_depth = gdk_memory_format_get_depth (gdk_texture_get_format (texture));
|
||||
@@ -2457,7 +2455,7 @@ gsk_inset_shadow_node_draw (GskRenderNode *node,
|
||||
* We could remove the part of "box" where the blur doesn't
|
||||
* reach, but computing that is a bit tricky since the
|
||||
* rounded corners are on the "inside" of it. */
|
||||
rectangle_init_from_graphene (&r, &clip_box.bounds);
|
||||
gsk_rect_to_cairo_grow (&clip_box.bounds, &r);
|
||||
remaining = cairo_region_create_rectangle (&r);
|
||||
|
||||
/* First do the corners of box */
|
||||
@@ -2503,9 +2501,9 @@ gsk_inset_shadow_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_inset_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_inset_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskInsetShadowNode *self1 = (GskInsetShadowNode *) node1;
|
||||
GskInsetShadowNode *self2 = (GskInsetShadowNode *) node2;
|
||||
@@ -2816,9 +2814,9 @@ gsk_outset_shadow_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_outset_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_outset_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskOutsetShadowNode *self1 = (GskOutsetShadowNode *) node1;
|
||||
GskOutsetShadowNode *self2 = (GskOutsetShadowNode *) node2;
|
||||
@@ -3088,6 +3086,7 @@ gsk_cairo_node_new (const graphene_rect_t *bounds)
|
||||
node->offscreen_for_opacity = FALSE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -3196,27 +3195,26 @@ gsk_container_node_compare_func (gconstpointer elem1, gconstpointer elem2, gpoin
|
||||
}
|
||||
|
||||
static GskDiffResult
|
||||
gsk_container_node_keep_func (gconstpointer elem1, gconstpointer elem2, gpointer data)
|
||||
gsk_container_node_keep_func (gconstpointer elem1, gconstpointer elem2, gpointer user_data)
|
||||
{
|
||||
GskDiffData *gd = data;
|
||||
|
||||
gsk_render_node_data_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2, gd);
|
||||
if (cairo_region_num_rectangles (gd->region) > MAX_RECTS_IN_DIFF)
|
||||
GskDiffData *data = user_data;
|
||||
gsk_render_node_diff ((GskRenderNode *) elem1, (GskRenderNode *) elem2, data);
|
||||
if (cairo_region_num_rectangles (data->region) > MAX_RECTS_IN_DIFF)
|
||||
return GSK_DIFF_ABORTED;
|
||||
|
||||
return GSK_DIFF_OK;
|
||||
}
|
||||
|
||||
static GskDiffResult
|
||||
gsk_container_node_change_func (gconstpointer elem, gsize idx, gpointer data)
|
||||
gsk_container_node_change_func (gconstpointer elem, gsize idx, gpointer user_data)
|
||||
{
|
||||
const GskRenderNode *node = elem;
|
||||
GskDiffData *gd = data;
|
||||
GskDiffData *data = user_data;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
rectangle_init_from_graphene (&rect, &node->bounds);
|
||||
cairo_region_union_rectangle (gd->region, &rect);
|
||||
if (cairo_region_num_rectangles (gd->region) > MAX_RECTS_IN_DIFF)
|
||||
gsk_rect_to_cairo_grow (&node->bounds, &rect);
|
||||
cairo_region_union_rectangle (data->region, &rect);
|
||||
if (cairo_region_num_rectangles (data->region) > MAX_RECTS_IN_DIFF)
|
||||
return GSK_DIFF_ABORTED;
|
||||
|
||||
return GSK_DIFF_OK;
|
||||
@@ -3253,9 +3251,9 @@ gsk_render_node_diff_multiple (GskRenderNode **nodes1,
|
||||
}
|
||||
|
||||
void
|
||||
gsk_container_node_diff_with (GskRenderNode *container,
|
||||
GskRenderNode *other,
|
||||
GskDiffData *data)
|
||||
gsk_container_node_diff_with (GskRenderNode *container,
|
||||
GskRenderNode *other,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskContainerNode *self = (GskContainerNode *) container;
|
||||
|
||||
@@ -3270,9 +3268,9 @@ gsk_container_node_diff_with (GskRenderNode *container,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_container_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_container_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskContainerNode *self1 = (GskContainerNode *) node1;
|
||||
GskContainerNode *self2 = (GskContainerNode *) node2;
|
||||
@@ -3476,7 +3474,7 @@ gsk_transform_node_draw (GskRenderNode *node,
|
||||
* (like when flipping an axis at the point where scale == 0)
|
||||
* and just means that nothing should be drawn.
|
||||
* But Cairo throws lots of ugly errors instead of silently
|
||||
* going on. So We silently go on.
|
||||
* going on. So we silently go on.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
@@ -3499,9 +3497,9 @@ gsk_transform_node_can_diff (const GskRenderNode *node1,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_transform_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_transform_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskTransformNode *self1 = (GskTransformNode *) node1;
|
||||
GskTransformNode *self2 = (GskTransformNode *) node2;
|
||||
@@ -3518,7 +3516,7 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
switch (gsk_transform_get_category (self1->transform))
|
||||
{
|
||||
case GSK_TRANSFORM_CATEGORY_IDENTITY:
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
break;
|
||||
|
||||
case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE:
|
||||
@@ -3527,7 +3525,7 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
float dx, dy;
|
||||
gsk_transform_to_translate (self1->transform, &dx, &dy);
|
||||
sub = cairo_region_create ();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload });
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
cairo_region_translate (sub, floorf (dx), floorf (dy));
|
||||
if (floorf (dx) != dx)
|
||||
{
|
||||
@@ -3554,7 +3552,7 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
float scale_x, scale_y, dx, dy;
|
||||
gsk_transform_to_affine (self1->transform, &scale_x, &scale_y, &dx, &dy);
|
||||
sub = cairo_region_create ();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload });
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
region_union_region_affine (data->region, sub, scale_x, scale_y, dx, dy);
|
||||
cairo_region_destroy (sub);
|
||||
}
|
||||
@@ -3717,15 +3715,15 @@ gsk_opacity_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_opacity_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_opacity_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskOpacityNode *self1 = (GskOpacityNode *) node1;
|
||||
GskOpacityNode *self2 = (GskOpacityNode *) node2;
|
||||
|
||||
if (self1->opacity == self2->opacity)
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
else
|
||||
gsk_render_node_diff_impossible (node1, node2, data);
|
||||
}
|
||||
@@ -3931,9 +3929,9 @@ gsk_color_matrix_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_color_matrix_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_color_matrix_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskColorMatrixNode *self1 = (GskColorMatrixNode *) node1;
|
||||
GskColorMatrixNode *self2 = (GskColorMatrixNode *) node2;
|
||||
@@ -3944,7 +3942,7 @@ gsk_color_matrix_node_diff (GskRenderNode *node1,
|
||||
if (!graphene_matrix_equal_fast (&self1->color_matrix, &self2->color_matrix))
|
||||
goto nope;
|
||||
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
return;
|
||||
|
||||
nope:
|
||||
@@ -4225,9 +4223,9 @@ gsk_repeat_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_repeat_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_repeat_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskRepeatNode *self1 = (GskRepeatNode *) node1;
|
||||
GskRepeatNode *self2 = (GskRepeatNode *) node2;
|
||||
@@ -4238,7 +4236,7 @@ gsk_repeat_node_diff (GskRenderNode *node1,
|
||||
cairo_region_t *sub;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload });
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
if (cairo_region_is_empty (sub))
|
||||
{
|
||||
cairo_region_destroy (sub);
|
||||
@@ -4291,13 +4289,19 @@ gsk_repeat_node_new (const graphene_rect_t *bounds,
|
||||
node->offscreen_for_opacity = TRUE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
|
||||
self->child = gsk_render_node_ref (child);
|
||||
|
||||
if (child_bounds)
|
||||
gsk_rect_init_from_rect (&self->child_bounds, child_bounds);
|
||||
{
|
||||
gsk_rect_init_from_rect (&self->child_bounds, child_bounds);
|
||||
gsk_rect_normalize (&self->child_bounds);
|
||||
}
|
||||
else
|
||||
gsk_rect_init_from_rect (&self->child_bounds, &child->bounds);
|
||||
{
|
||||
gsk_rect_init_from_rect (&self->child_bounds, &child->bounds);
|
||||
}
|
||||
|
||||
node->preferred_depth = gsk_render_node_get_preferred_depth (child);
|
||||
|
||||
@@ -4380,9 +4384,9 @@ gsk_clip_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_clip_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_clip_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskClipNode *self1 = (GskClipNode *) node1;
|
||||
GskClipNode *self2 = (GskClipNode *) node2;
|
||||
@@ -4393,8 +4397,8 @@ gsk_clip_node_diff (GskRenderNode *node1,
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload });
|
||||
rectangle_init_from_graphene (&clip_rect, &self1->clip);
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
gsk_rect_to_cairo_grow (&self1->clip, &clip_rect);
|
||||
cairo_region_intersect_rectangle (sub, &clip_rect);
|
||||
cairo_region_union (data->region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
@@ -4443,7 +4447,8 @@ gsk_clip_node_new (GskRenderNode *child,
|
||||
node->offscreen_for_opacity = child->offscreen_for_opacity;
|
||||
|
||||
self->child = gsk_render_node_ref (child);
|
||||
graphene_rect_normalize_r (clip, &self->clip);
|
||||
gsk_rect_init_from_rect (&self->clip, clip);
|
||||
gsk_rect_normalize (&self->clip);
|
||||
|
||||
gsk_rect_intersection (&self->clip, &child->bounds, &node->bounds);
|
||||
|
||||
@@ -4528,9 +4533,9 @@ gsk_rounded_clip_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_rounded_clip_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_rounded_clip_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskRoundedClipNode *self1 = (GskRoundedClipNode *) node1;
|
||||
GskRoundedClipNode *self2 = (GskRoundedClipNode *) node2;
|
||||
@@ -4541,8 +4546,8 @@ gsk_rounded_clip_node_diff (GskRenderNode *node1,
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload });
|
||||
rectangle_init_from_graphene (&clip_rect, &self1->clip.bounds);
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
gsk_rect_to_cairo_grow (&self1->clip.bounds, &clip_rect);
|
||||
cairo_region_intersect_rectangle (sub, &clip_rect);
|
||||
cairo_region_union (data->region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
@@ -4698,9 +4703,9 @@ gsk_fill_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_fill_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_fill_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskFillNode *self1 = (GskFillNode *) node1;
|
||||
GskFillNode *self2 = (GskFillNode *) node2;
|
||||
@@ -4711,8 +4716,8 @@ gsk_fill_node_diff (GskRenderNode *node1,
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload });
|
||||
rectangle_init_from_graphene (&clip_rect, &node1->bounds);
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
gsk_rect_to_cairo_grow (&node1->bounds, &clip_rect);
|
||||
cairo_region_intersect_rectangle (sub, &clip_rect);
|
||||
cairo_region_union (data->region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
@@ -4901,9 +4906,9 @@ gsk_stroke_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_stroke_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_stroke_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskStrokeNode *self1 = (GskStrokeNode *) node1;
|
||||
GskStrokeNode *self2 = (GskStrokeNode *) node2;
|
||||
@@ -4915,8 +4920,8 @@ gsk_stroke_node_diff (GskRenderNode *node1,
|
||||
cairo_rectangle_int_t clip_rect;
|
||||
|
||||
sub = cairo_region_create();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload });
|
||||
rectangle_init_from_graphene (&clip_rect, &node1->bounds);
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
gsk_rect_to_cairo_grow (&node1->bounds, &clip_rect);
|
||||
cairo_region_intersect_rectangle (sub, &clip_rect);
|
||||
cairo_region_union (data->region, sub);
|
||||
cairo_region_destroy (sub);
|
||||
@@ -5118,9 +5123,9 @@ gsk_shadow_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_shadow_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskShadowNode *self1 = (GskShadowNode *) node1;
|
||||
GskShadowNode *self2 = (GskShadowNode *) node2;
|
||||
@@ -5158,7 +5163,7 @@ gsk_shadow_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
sub = cairo_region_create ();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) { sub, data->offload });
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
|
||||
n = cairo_region_num_rectangles (sub);
|
||||
for (i = 0; i < n; i++)
|
||||
@@ -5394,17 +5399,17 @@ gsk_blend_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_blend_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_blend_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskBlendNode *self1 = (GskBlendNode *) node1;
|
||||
GskBlendNode *self2 = (GskBlendNode *) node2;
|
||||
|
||||
if (self1->blend_mode == self2->blend_mode)
|
||||
{
|
||||
gsk_render_node_data_diff (self1->top, self2->top, data);
|
||||
gsk_render_node_data_diff (self1->bottom, self2->bottom, data);
|
||||
gsk_render_node_diff (self1->top, self2->top, data);
|
||||
gsk_render_node_diff (self1->bottom, self2->bottom, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5564,17 +5569,17 @@ gsk_cross_fade_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_cross_fade_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_cross_fade_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskCrossFadeNode *self1 = (GskCrossFadeNode *) node1;
|
||||
GskCrossFadeNode *self2 = (GskCrossFadeNode *) node2;
|
||||
|
||||
if (self1->progress == self2->progress)
|
||||
{
|
||||
gsk_render_node_data_diff (self1->start, self2->start, data);
|
||||
gsk_render_node_data_diff (self1->end, self2->end, data);
|
||||
gsk_render_node_diff (self1->start, self2->start, data);
|
||||
gsk_render_node_diff (self1->end, self2->end, data);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5737,9 +5742,9 @@ gsk_text_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_text_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_text_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskTextNode *self1 = (GskTextNode *) node1;
|
||||
GskTextNode *self2 = (GskTextNode *) node2;
|
||||
@@ -5787,6 +5792,12 @@ gsk_text_node_class_init (gpointer g_class,
|
||||
node_class->diff = gsk_text_node_diff;
|
||||
}
|
||||
|
||||
static inline float
|
||||
pango_units_to_float (int i)
|
||||
{
|
||||
return (float) i / PANGO_SCALE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_text_node_new:
|
||||
* @font: the `PangoFont` containing the glyphs
|
||||
@@ -5813,8 +5824,7 @@ gsk_text_node_new (PangoFont *font,
|
||||
PangoGlyphInfo *glyph_infos;
|
||||
int n;
|
||||
|
||||
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
gsk_get_unhinted_glyph_string_extents (glyphs, font, &ink_rect);
|
||||
|
||||
/* Don't create nodes with empty bounds */
|
||||
if (ink_rect.width == 0 || ink_rect.height == 0)
|
||||
@@ -5851,10 +5861,10 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->num_glyphs = n;
|
||||
|
||||
gsk_rect_init (&node->bounds,
|
||||
offset->x + ink_rect.x - 1,
|
||||
offset->y + ink_rect.y - 1,
|
||||
ink_rect.width + 2,
|
||||
ink_rect.height + 2);
|
||||
offset->x + pango_units_to_float (ink_rect.x),
|
||||
offset->y + pango_units_to_float (ink_rect.y),
|
||||
pango_units_to_float (ink_rect.width),
|
||||
pango_units_to_float (ink_rect.height));
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -6183,9 +6193,9 @@ gsk_blur_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_blur_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_blur_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskBlurNode *self1 = (GskBlurNode *) node1;
|
||||
GskBlurNode *self2 = (GskBlurNode *) node2;
|
||||
@@ -6198,7 +6208,7 @@ gsk_blur_node_diff (GskRenderNode *node1,
|
||||
|
||||
clip_radius = ceil (gsk_cairo_blur_compute_pixels (self1->radius / 2.0));
|
||||
sub = cairo_region_create ();
|
||||
gsk_render_node_data_diff (self1->child, self2->child, &(GskDiffData) {sub, data->offload });
|
||||
gsk_render_node_diff (self1->child, self2->child, &(GskDiffData) { sub, data->surface });
|
||||
|
||||
n = cairo_region_num_rectangles (sub);
|
||||
for (i = 0; i < n; i++)
|
||||
@@ -6428,9 +6438,9 @@ gsk_mask_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_mask_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_mask_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskMaskNode *self1 = (GskMaskNode *) node1;
|
||||
GskMaskNode *self2 = (GskMaskNode *) node2;
|
||||
@@ -6441,8 +6451,8 @@ gsk_mask_node_diff (GskRenderNode *node1,
|
||||
return;
|
||||
}
|
||||
|
||||
gsk_render_node_data_diff (self1->source, self2->source, data);
|
||||
gsk_render_node_data_diff (self1->mask, self2->mask, data);
|
||||
gsk_render_node_diff (self1->source, self2->source, data);
|
||||
gsk_render_node_diff (self1->mask, self2->mask, data);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6606,14 +6616,14 @@ gsk_debug_node_can_diff (const GskRenderNode *node1,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_debug_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_debug_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskDebugNode *self1 = (GskDebugNode *) node1;
|
||||
GskDebugNode *self2 = (GskDebugNode *) node2;
|
||||
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6742,9 +6752,9 @@ gsk_gl_shader_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_shader_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_gl_shader_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskGLShaderNode *self1 = (GskGLShaderNode *) node1;
|
||||
GskGLShaderNode *self2 = (GskGLShaderNode *) node2;
|
||||
@@ -6756,7 +6766,7 @@ gsk_gl_shader_node_diff (GskRenderNode *node1,
|
||||
{
|
||||
cairo_region_t *child_region = cairo_region_create();
|
||||
for (guint i = 0; i < self1->n_children; i++)
|
||||
gsk_render_node_data_diff (self1->children[i], self2->children[i], &(GskDiffData) {child_region, data->offload });
|
||||
gsk_render_node_diff (self1->children[i], self2->children[i], &(GskDiffData) { child_region, data->surface });
|
||||
if (!cairo_region_is_empty (child_region))
|
||||
gsk_render_node_diff_impossible (node1, node2, data);
|
||||
cairo_region_destroy (child_region);
|
||||
@@ -6832,6 +6842,8 @@ gsk_gl_shader_node_new (GskGLShader *shader,
|
||||
node->offscreen_for_opacity = TRUE;
|
||||
|
||||
gsk_rect_init_from_rect (&node->bounds, bounds);
|
||||
gsk_rect_normalize (&node->bounds);
|
||||
|
||||
self->shader = g_object_ref (shader);
|
||||
|
||||
self->args = g_bytes_ref (args);
|
||||
@@ -6967,42 +6979,31 @@ gsk_subsurface_node_can_diff (const GskRenderNode *node1,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_subsurface_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
gsk_subsurface_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data)
|
||||
{
|
||||
GskSubsurfaceNode *self1 = (GskSubsurfaceNode *) node1;
|
||||
GskSubsurfaceNode *self2 = (GskSubsurfaceNode *) node2;
|
||||
GskOffloadInfo *info1, *info2;
|
||||
|
||||
if (!data->offload)
|
||||
{
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
return;
|
||||
}
|
||||
|
||||
info1 = gsk_offload_get_subsurface_info (data->offload, self1->subsurface);
|
||||
info2 = gsk_offload_get_subsurface_info (data->offload, self2->subsurface);
|
||||
|
||||
if (!info1 || !info2)
|
||||
{
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info1->is_offloaded != info2->is_offloaded ||
|
||||
info1->is_above != info2->is_above)
|
||||
if (self1->subsurface != self2->subsurface)
|
||||
{
|
||||
/* Shouldn't happen, can_diff() avoids this, but to be sure */
|
||||
gsk_render_node_diff_impossible (node1, node2, data);
|
||||
}
|
||||
else if (info1->is_offloaded && !info1->is_above &&
|
||||
!gsk_rect_equal (&info1->rect, &info2->rect))
|
||||
else if (self1->subsurface->parent != data->surface)
|
||||
{
|
||||
gsk_render_node_diff_impossible (node1, node2, data);
|
||||
/* The inspector case */
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
}
|
||||
else if (!info1->is_offloaded)
|
||||
else if (self1->subsurface && gdk_subsurface_get_texture (self1->subsurface) != NULL)
|
||||
{
|
||||
gsk_render_node_data_diff (self1->child, self2->child, data);
|
||||
/* offloaded, no contents to compare */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not offloaded, diff the children */
|
||||
gsk_render_node_diff (self1->child, self2->child, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+188
-77
@@ -30,6 +30,7 @@
|
||||
#include "gskstroke.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskenumtypes.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkrgbaprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
@@ -46,7 +47,9 @@
|
||||
#include <cairo-script-interpreter.h>
|
||||
#endif
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
#ifdef HAVE_PANGOFT
|
||||
#include <pango/pangofc-fontmap.h>
|
||||
#endif
|
||||
@@ -86,6 +89,39 @@ context_finish (Context *context)
|
||||
g_clear_object (&context->fontmap);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_enum (GtkCssParser *parser,
|
||||
GType type,
|
||||
gpointer out_value)
|
||||
{
|
||||
GEnumClass *class;
|
||||
GEnumValue *v;
|
||||
char *enum_name;
|
||||
|
||||
enum_name = gtk_css_parser_consume_ident (parser);
|
||||
if (enum_name == NULL)
|
||||
return FALSE;
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
|
||||
v = g_enum_get_value_by_nick (class, enum_name);
|
||||
if (v == NULL)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Unknown value \"%s\" for enum \"%s\"",
|
||||
enum_name, g_type_name (type));
|
||||
g_free (enum_name);
|
||||
g_type_class_unref (class);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(int*)out_value = v->value;
|
||||
|
||||
g_free (enum_name);
|
||||
g_type_class_unref (class);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_rect (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -1182,6 +1218,8 @@ clear_font (gpointer inout_font)
|
||||
g_clear_object ((PangoFont **) inout_font);
|
||||
}
|
||||
|
||||
#define GLYPH_NEEDS_WIDTH (1 << 15)
|
||||
|
||||
static gboolean
|
||||
parse_glyphs (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -1208,6 +1246,7 @@ parse_glyphs (GtkCssParser *parser,
|
||||
gtk_css_parser_error_value (parser, "Unsupported character %d in string", i);
|
||||
}
|
||||
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + s[i];
|
||||
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||
pango_glyph_string_set_size (glyph_string, glyph_string->num_glyphs + 1);
|
||||
glyph_string->glyphs[glyph_string->num_glyphs - 1] = gi;
|
||||
}
|
||||
@@ -1216,14 +1255,22 @@ parse_glyphs (GtkCssParser *parser,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gtk_css_parser_consume_integer (parser, &i) ||
|
||||
!gtk_css_parser_consume_number (parser, &d))
|
||||
if (!gtk_css_parser_consume_integer (parser, &i))
|
||||
{
|
||||
pango_glyph_string_free (glyph_string);
|
||||
return FALSE;
|
||||
}
|
||||
gi.glyph = i;
|
||||
gi.geometry.width = (int) (d * PANGO_SCALE);
|
||||
|
||||
if (gtk_css_parser_has_number (parser))
|
||||
{
|
||||
gtk_css_parser_consume_number (parser, &d);
|
||||
gi.geometry.width = (int) (d * PANGO_SCALE);
|
||||
}
|
||||
else
|
||||
{
|
||||
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||
}
|
||||
|
||||
if (gtk_css_parser_has_number (parser))
|
||||
{
|
||||
@@ -2193,23 +2240,36 @@ unpack_glyphs (PangoFont *font,
|
||||
|
||||
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||
{
|
||||
PangoGlyph glyph = glyphs->glyphs[i].glyph;
|
||||
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
||||
|
||||
if (glyph < PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH ||
|
||||
glyph >= PANGO_GLYPH_INVALID_INPUT)
|
||||
if (((*(unsigned int *) &gi->attr) & GLYPH_NEEDS_WIDTH) == 0)
|
||||
continue;
|
||||
|
||||
glyph = glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
||||
*(unsigned int *) &gi->attr &= ~GLYPH_NEEDS_WIDTH;
|
||||
|
||||
if (ascii == NULL)
|
||||
if (gi->glyph >= PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH &&
|
||||
gi->glyph < PANGO_GLYPH_INVALID_INPUT)
|
||||
{
|
||||
ascii = create_ascii_glyphs (font);
|
||||
if (ascii == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
PangoGlyph idx = gi->glyph - (PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH) - MIN_ASCII_GLYPH;
|
||||
|
||||
glyphs->glyphs[i].glyph = ascii->glyphs[glyph].glyph;
|
||||
glyphs->glyphs[i].geometry.width = ascii->glyphs[glyph].geometry.width;
|
||||
if (ascii == NULL)
|
||||
{
|
||||
ascii = create_ascii_glyphs (font);
|
||||
if (ascii == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gi->glyph = ascii->glyphs[idx].glyph;
|
||||
gi->geometry.width = ascii->glyphs[idx].geometry.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
PangoRectangle ink_rect;
|
||||
|
||||
pango_font_get_glyph_extents (font, gi->glyph, &ink_rect, NULL);
|
||||
|
||||
gi->geometry.width = ink_rect.width;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_pointer (&ascii, pango_glyph_string_free);
|
||||
@@ -2217,6 +2277,45 @@ unpack_glyphs (PangoFont *font,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_hint_style (GtkCssParser *parser,
|
||||
Context *context,
|
||||
gpointer out)
|
||||
{
|
||||
if (!parse_enum (parser, CAIRO_GOBJECT_TYPE_HINT_STYLE, out))
|
||||
return FALSE;
|
||||
|
||||
if (*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_NONE &&
|
||||
*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_SLIGHT &&
|
||||
*(cairo_hint_style_t *) out != CAIRO_HINT_STYLE_FULL)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Unsupported value for enum \"%s\"",
|
||||
g_type_name (CAIRO_GOBJECT_TYPE_HINT_STYLE));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_antialias (GtkCssParser *parser,
|
||||
Context *context,
|
||||
gpointer out)
|
||||
{
|
||||
if (!parse_enum (parser, CAIRO_GOBJECT_TYPE_ANTIALIAS, out))
|
||||
return FALSE;
|
||||
|
||||
if (*(cairo_antialias_t *) out != CAIRO_ANTIALIAS_NONE &&
|
||||
*(cairo_antialias_t *) out != CAIRO_ANTIALIAS_GRAY)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Unsupported value for enum \"%s\"",
|
||||
g_type_name (CAIRO_GOBJECT_TYPE_ANTIALIAS));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
parse_text_node (GtkCssParser *parser,
|
||||
Context *context)
|
||||
@@ -2225,11 +2324,16 @@ parse_text_node (GtkCssParser *parser,
|
||||
graphene_point_t offset = GRAPHENE_POINT_INIT (0, 0);
|
||||
GdkRGBA color = GDK_RGBA("000000");
|
||||
PangoGlyphString *glyphs = NULL;
|
||||
cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
||||
cairo_antialias_t antialias = CAIRO_ANTIALIAS_GRAY;
|
||||
PangoFont *hinted;
|
||||
const Declaration declarations[] = {
|
||||
{ "font", parse_font, clear_font, &font },
|
||||
{ "offset", parse_point, NULL, &offset },
|
||||
{ "color", parse_color, NULL, &color },
|
||||
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs }
|
||||
{ "glyphs", parse_glyphs, clear_glyphs, &glyphs },
|
||||
{ "hint-style", parse_hint_style, NULL, &hint_style },
|
||||
{ "antialias", parse_antialias, NULL, &antialias },
|
||||
};
|
||||
GskRenderNode *result;
|
||||
|
||||
@@ -2237,10 +2341,14 @@ parse_text_node (GtkCssParser *parser,
|
||||
|
||||
if (font == NULL)
|
||||
{
|
||||
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 11", TRUE);
|
||||
font = font_from_string (pango_cairo_font_map_get_default (), "Cantarell 15px", TRUE);
|
||||
g_assert (font);
|
||||
}
|
||||
|
||||
hinted = gsk_reload_font (font, 1.0, CAIRO_HINT_METRICS_OFF, hint_style, antialias);
|
||||
g_object_unref (font);
|
||||
font = hinted;
|
||||
|
||||
if (!glyphs)
|
||||
{
|
||||
const char *text = "Hello";
|
||||
@@ -2252,6 +2360,7 @@ parse_text_node (GtkCssParser *parser,
|
||||
for (i = 0; i < strlen (text); i++)
|
||||
{
|
||||
gi.glyph = PANGO_GLYPH_INVALID_INPUT - MAX_ASCII_GLYPH + text[i];
|
||||
*(unsigned int *) &gi.attr |= GLYPH_NEEDS_WIDTH;
|
||||
glyphs->glyphs[i] = gi;
|
||||
}
|
||||
}
|
||||
@@ -2429,39 +2538,6 @@ clear_dash (gpointer inout_array)
|
||||
g_clear_pointer ((GArray **) inout_array, g_array_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_enum (GtkCssParser *parser,
|
||||
GType type,
|
||||
gpointer out_value)
|
||||
{
|
||||
GEnumClass *class;
|
||||
GEnumValue *v;
|
||||
char *enum_name;
|
||||
|
||||
enum_name = gtk_css_parser_consume_ident (parser);
|
||||
if (enum_name == NULL)
|
||||
return FALSE;
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
|
||||
v = g_enum_get_value_by_nick (class, enum_name);
|
||||
if (v == NULL)
|
||||
{
|
||||
gtk_css_parser_error_value (parser, "Unknown value \"%s\" for enum \"%s\"",
|
||||
enum_name, g_type_name (type));
|
||||
g_free (enum_name);
|
||||
g_type_class_unref (class);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(int*)out_value = v->value;
|
||||
|
||||
g_free (enum_name);
|
||||
g_type_class_unref (class);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_fill_rule (GtkCssParser *parser,
|
||||
Context *context,
|
||||
@@ -3248,6 +3324,33 @@ append_string_param (Printer *p,
|
||||
g_string_append_c (p->str, '\n');
|
||||
}
|
||||
|
||||
static const char *
|
||||
enum_to_nick (GType type,
|
||||
int value)
|
||||
{
|
||||
GEnumClass *class;
|
||||
GEnumValue *v;
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
v = g_enum_get_value (class, value);
|
||||
g_type_class_unref (class);
|
||||
|
||||
return v->value_nick;
|
||||
}
|
||||
|
||||
static void
|
||||
append_enum_param (Printer *p,
|
||||
const char *param_name,
|
||||
GType type,
|
||||
int value)
|
||||
{
|
||||
_indent (p);
|
||||
g_string_append_printf (p->str, "%s: ", param_name);
|
||||
g_string_append (p->str, enum_to_nick (type, value));
|
||||
g_string_append_c (p->str, ';');
|
||||
g_string_append_c (p->str, '\n');
|
||||
}
|
||||
|
||||
static void
|
||||
append_vec4_param (Printer *p,
|
||||
const char *param_name,
|
||||
@@ -3471,7 +3574,7 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
||||
PangoFontDescription *desc;
|
||||
char *s;
|
||||
|
||||
desc = pango_font_describe (font);
|
||||
desc = pango_font_describe_with_absolute_size (font);
|
||||
s = pango_font_description_to_string (desc);
|
||||
g_string_append_printf (p->str, "\"%s\"", s);
|
||||
g_free (s);
|
||||
@@ -3515,6 +3618,37 @@ gsk_text_node_serialize_font (GskRenderNode *node,
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_text_node_serialize_font_options (GskRenderNode *node,
|
||||
Printer *p)
|
||||
{
|
||||
PangoFont *font = gsk_text_node_get_font (node);
|
||||
cairo_scaled_font_t *sf = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
|
||||
cairo_font_options_t *options;
|
||||
cairo_hint_style_t hint_style;
|
||||
cairo_antialias_t antialias;
|
||||
|
||||
options = cairo_font_options_create ();
|
||||
cairo_scaled_font_get_font_options (sf, options);
|
||||
hint_style = cairo_font_options_get_hint_style (options);
|
||||
antialias = cairo_font_options_get_antialias (options);
|
||||
cairo_font_options_destroy (options);
|
||||
|
||||
/* medium and full are identical in the absence of subpixel modes */
|
||||
if (hint_style == CAIRO_HINT_STYLE_MEDIUM)
|
||||
hint_style = CAIRO_HINT_STYLE_FULL;
|
||||
|
||||
if (hint_style == CAIRO_HINT_STYLE_NONE ||
|
||||
hint_style == CAIRO_HINT_STYLE_FULL)
|
||||
append_enum_param (p, "hint-style", CAIRO_GOBJECT_TYPE_HINT_STYLE, hint_style);
|
||||
|
||||
/* CAIRO_ANTIALIAS_NONE is the only value we ever emit here, since gray is the default,
|
||||
* and we don't accept any other values.
|
||||
*/
|
||||
if (antialias == CAIRO_ANTIALIAS_NONE)
|
||||
append_enum_param (p, "antialias", CAIRO_GOBJECT_TYPE_ANTIALIAS, antialias);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
GString *p)
|
||||
@@ -3596,33 +3730,6 @@ gsk_text_node_serialize_glyphs (GskRenderNode *node,
|
||||
pango_glyph_string_free (ascii);
|
||||
}
|
||||
|
||||
static const char *
|
||||
enum_to_nick (GType type,
|
||||
int value)
|
||||
{
|
||||
GEnumClass *class;
|
||||
GEnumValue *v;
|
||||
|
||||
class = g_type_class_ref (type);
|
||||
v = g_enum_get_value (class, value);
|
||||
g_type_class_unref (class);
|
||||
|
||||
return v->value_nick;
|
||||
}
|
||||
|
||||
static void
|
||||
append_enum_param (Printer *p,
|
||||
const char *param_name,
|
||||
GType type,
|
||||
int value)
|
||||
{
|
||||
_indent (p);
|
||||
g_string_append_printf (p->str, "%s: ", param_name);
|
||||
g_string_append (p->str, enum_to_nick (type, value));
|
||||
g_string_append_c (p->str, ';');
|
||||
g_string_append_c (p->str, '\n');
|
||||
}
|
||||
|
||||
static void
|
||||
append_path_param (Printer *p,
|
||||
const char *param_name,
|
||||
@@ -4087,6 +4194,8 @@ render_node_print (Printer *p,
|
||||
if (!graphene_point_equal (offset, graphene_point_zero ()))
|
||||
append_point_param (p, "offset", offset);
|
||||
|
||||
gsk_text_node_serialize_font_options (node, p);
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
@@ -4357,6 +4466,8 @@ render_node_print (Printer *p,
|
||||
start_node (p, "subsurface", node_name);
|
||||
|
||||
append_node_param (p, "child", gsk_subsurface_node_get_child (node));
|
||||
|
||||
end_node (p);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskrendernode.h"
|
||||
#include "gskoffloadprivate.h"
|
||||
#include <cairo.h>
|
||||
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
@@ -40,7 +39,7 @@ struct _GskRenderNode
|
||||
typedef struct
|
||||
{
|
||||
cairo_region_t *region;
|
||||
GskOffload *offload;
|
||||
GdkSurface *surface;
|
||||
} GskDiffData;
|
||||
|
||||
struct _GskRenderNodeClass
|
||||
@@ -72,10 +71,6 @@ void _gsk_render_node_unref (GskRenderNode
|
||||
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
|
||||
const GskRenderNode *node2) G_GNUC_PURE;
|
||||
void gsk_render_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
cairo_region_t *region,
|
||||
GskOffload *offload);
|
||||
void gsk_render_node_data_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
GskDiffData *data);
|
||||
void gsk_render_node_diff_impossible (GskRenderNode *node1,
|
||||
|
||||
+23
-6
@@ -308,7 +308,7 @@ gsk_rounded_rect_scale_affine (GskRoundedRect *dest,
|
||||
|
||||
g_assert (dest != src);
|
||||
|
||||
graphene_rect_scale (&src->bounds, scale_x, scale_y, &dest->bounds);
|
||||
gsk_rect_scale (&src->bounds, scale_x, scale_y, &dest->bounds);
|
||||
graphene_rect_offset (&dest->bounds, dx, dy);
|
||||
|
||||
scale_x = fabsf (scale_x);
|
||||
@@ -584,7 +584,7 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
const graphene_rect_t *rect,
|
||||
GskRoundedRect *result)
|
||||
{
|
||||
int px, py, qx, qy;
|
||||
int px, py, qx, qy, rx, ry;
|
||||
|
||||
if (!gsk_rect_intersection (&self->bounds, rect, &result->bounds))
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
@@ -599,7 +599,11 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point2 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
{
|
||||
classify_point (&rect_point2 (rect), &rounded_rect_corner2 (self), &rx, &ry);
|
||||
if (rx == BELOW || ry == BELOW)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
}
|
||||
else if (qx == ABOVE && qy == ABOVE)
|
||||
result->corner[0] = self->corner[0];
|
||||
else
|
||||
@@ -626,7 +630,11 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point3 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
{
|
||||
classify_point (&rect_point3 (rect), &rounded_rect_corner3 (self), &rx, &ry);
|
||||
if (rx == ABOVE || ry == BELOW)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
}
|
||||
else if (qx == BELOW && qy == ABOVE)
|
||||
result->corner[1] = self->corner[1];
|
||||
else
|
||||
@@ -653,7 +661,12 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point0 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
{
|
||||
|
||||
classify_point (&rect_point2 (rect), &rounded_rect_corner0 (self), &rx, &ry);
|
||||
if (rx == ABOVE || ry == ABOVE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
}
|
||||
else if (qx == BELOW && qy == BELOW)
|
||||
result->corner[2] = self->corner[2];
|
||||
else
|
||||
@@ -680,7 +693,11 @@ gsk_rounded_rect_intersect_with_rect (const GskRoundedRect *self,
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
else if (qx == INNER && qy == INNER &&
|
||||
gsk_rounded_rect_locate_point (self, &rect_point1 (rect)) != INSIDE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
{
|
||||
classify_point (&rect_point1 (rect), &rounded_rect_corner1 (self), &rx, &ry);
|
||||
if (rx == BELOW || ry == ABOVE)
|
||||
return GSK_INTERSECTION_EMPTY;
|
||||
}
|
||||
else if (qx == ABOVE && qy == BELOW)
|
||||
result->corner[3] = self->corner[3];
|
||||
else
|
||||
|
||||
+27
-7
@@ -382,15 +382,35 @@ gsk_matrix_transform_print (GskTransform *transform,
|
||||
guint i;
|
||||
float f[16];
|
||||
|
||||
g_string_append (string, "matrix3d(");
|
||||
graphene_matrix_to_float (&self->matrix, f);
|
||||
for (i = 0; i < 16; i++)
|
||||
if (transform->category >= GSK_TRANSFORM_CATEGORY_2D)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[i]);
|
||||
g_string_append (string, "matrix(");
|
||||
graphene_matrix_to_float (&self->matrix, f);
|
||||
string_append_double (string, f[0]);
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[1]);
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[4]);
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[5]);
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[12]);
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[13]);
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append (string, "matrix3d(");
|
||||
graphene_matrix_to_float (&self->matrix, f);
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
g_string_append (string, ", ");
|
||||
string_append_double (string, f[i]);
|
||||
}
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
g_string_append (string, ")");
|
||||
}
|
||||
|
||||
static GskTransform *
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
#include <math.h>
|
||||
|
||||
static inline float
|
||||
gsk_vec2_get_x (const graphene_vec2_t *v)
|
||||
{
|
||||
return graphene_simd4f_get_x (v->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline float
|
||||
gsk_vec2_get_y (const graphene_vec2_t *v)
|
||||
{
|
||||
return graphene_simd4f_get_y (v->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline graphene_vec2_t *
|
||||
gsk_vec2_init (graphene_vec2_t *v,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
v->__graphene_private_value = graphene_simd4f_init (x, y, 0.f, 0.f);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gsk_vec2_multiply (const graphene_vec2_t *a,
|
||||
const graphene_vec2_t *b,
|
||||
graphene_vec2_t *res)
|
||||
{
|
||||
res->__graphene_private_value = graphene_simd4f_mul (a->__graphene_private_value,
|
||||
b->__graphene_private_value);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
gsk_vec2_equal (const graphene_vec2_t *v1,
|
||||
const graphene_vec2_t *v2)
|
||||
{
|
||||
return graphene_simd4f_cmp_eq (v1->__graphene_private_value, v2->__graphene_private_value);
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ accessible_at_point (GtkAccessible *parent,
|
||||
if (!gtk_accessible_get_bounds (parent, &px, &py, &width, &height))
|
||||
return NULL;
|
||||
|
||||
if (!children_only && x >= 0 && x <= width && y >= 0 && y <= height)
|
||||
if (!children_only && x >= px && x <= px + width && y >= py && y <= py + height)
|
||||
result = parent;
|
||||
|
||||
for (GtkAccessible *child = gtk_accessible_get_first_accessible_child (parent);
|
||||
@@ -233,6 +233,9 @@ component_handle_method (GDBusConnection *connection,
|
||||
GtkATContext *context = gtk_accessible_get_at_context (child);
|
||||
GtkAtSpiContext *ctx = GTK_AT_SPI_CONTEXT (context);
|
||||
|
||||
/* Realize the ATContext in order to get its ref */
|
||||
gtk_at_context_realize (context);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(@(so))", gtk_at_spi_context_to_ref (ctx)));
|
||||
|
||||
g_object_unref (context);
|
||||
|
||||
+118
-3
@@ -23,6 +23,7 @@
|
||||
#include "gtkatspicontextprivate.h"
|
||||
|
||||
#include "gtkaccessibleprivate.h"
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
|
||||
#include "gtkatspiactionprivate.h"
|
||||
#include "gtkatspieditabletextprivate.h"
|
||||
@@ -770,7 +771,7 @@ emit_text_selection_changed (GtkAtSpiContext *self,
|
||||
"org.a11y.atspi.Event.Object",
|
||||
"TextCaretMoved",
|
||||
g_variant_new ("(siiva{sv})",
|
||||
"", cursor_position, 0, g_variant_new_string (""), NULL),
|
||||
"", cursor_position, 0, g_variant_new_int32 (0), NULL),
|
||||
NULL);
|
||||
else
|
||||
g_dbus_connection_emit_signal (self->connection,
|
||||
@@ -1154,8 +1155,8 @@ gtk_at_spi_context_state_change (GtkATContext *ctx,
|
||||
|
||||
if (changed_properties & GTK_ACCESSIBLE_PROPERTY_CHANGE_DESCRIPTION)
|
||||
{
|
||||
char *label = gtk_at_context_get_description (GTK_AT_CONTEXT (self));
|
||||
GVariant *v = g_variant_new_take_string (label);
|
||||
char *label = gtk_at_context_get_description (GTK_AT_CONTEXT (self));
|
||||
GVariant *v = g_variant_new_take_string (label);
|
||||
emit_property_changed (self, "accessible-description", v);
|
||||
}
|
||||
|
||||
@@ -1567,6 +1568,117 @@ gtk_at_spi_context_announce (GtkATContext *context,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_at_spi_context_update_caret_position (GtkATContext *context)
|
||||
{
|
||||
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (context);
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
|
||||
GtkAccessibleText *accessible_text = GTK_ACCESSIBLE_TEXT (accessible);
|
||||
guint offset;
|
||||
|
||||
if (self->connection == NULL)
|
||||
return;
|
||||
|
||||
offset = gtk_accessible_text_get_caret_position (accessible_text);
|
||||
|
||||
g_dbus_connection_emit_signal (self->connection,
|
||||
NULL,
|
||||
self->context_path,
|
||||
"org.a11y.atspi.Event.Object",
|
||||
"TextCaretMoved",
|
||||
g_variant_new ("(siiva{sv})",
|
||||
"",
|
||||
(int) offset,
|
||||
0,
|
||||
g_variant_new_int32 (0),
|
||||
NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_at_spi_context_update_selection_bound (GtkATContext *context)
|
||||
{
|
||||
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (context);
|
||||
|
||||
if (self->connection == NULL)
|
||||
return;
|
||||
|
||||
g_dbus_connection_emit_signal (self->connection,
|
||||
NULL,
|
||||
self->context_path,
|
||||
"org.a11y.atspi.Event.Object",
|
||||
"TextSelectionChanged",
|
||||
g_variant_new ("(siiva{sv})",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
g_variant_new_string (""),
|
||||
NULL),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_at_spi_context_update_text_contents (GtkATContext *context,
|
||||
GtkAccessibleTextContentChange change,
|
||||
unsigned int start,
|
||||
unsigned int end)
|
||||
{
|
||||
GtkAtSpiContext *self = GTK_AT_SPI_CONTEXT (context);
|
||||
|
||||
if (self->connection == NULL)
|
||||
return;
|
||||
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (context);
|
||||
if (!GTK_IS_ACCESSIBLE_TEXT (accessible))
|
||||
return;
|
||||
|
||||
const char *kind = "";
|
||||
|
||||
switch (change)
|
||||
{
|
||||
case GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_INSERT:
|
||||
kind = "insert";
|
||||
break;
|
||||
|
||||
case GTK_ACCESSIBLE_TEXT_CONTENT_CHANGE_REMOVE:
|
||||
kind = "delete";
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
/* Retrieve the text using the given range */
|
||||
GBytes *contents = gtk_accessible_text_get_contents (GTK_ACCESSIBLE_TEXT (accessible),
|
||||
start, end);
|
||||
if (contents == NULL)
|
||||
goto out;
|
||||
|
||||
const char *text = g_bytes_get_data (contents, NULL);
|
||||
if (text == NULL)
|
||||
goto out;
|
||||
|
||||
/* Using G_MAXUINT in GTK maps to the text length */
|
||||
if (end == G_MAXUINT)
|
||||
end = g_utf8_strlen (text, -1);
|
||||
|
||||
g_dbus_connection_emit_signal (self->connection,
|
||||
NULL,
|
||||
self->context_path,
|
||||
"org.a11y.atspi.Event.Object",
|
||||
"TextChanged",
|
||||
g_variant_new ("(siiva{sv})",
|
||||
kind,
|
||||
start,
|
||||
end - start,
|
||||
g_variant_new_string (text),
|
||||
NULL),
|
||||
NULL);
|
||||
|
||||
out:
|
||||
g_clear_pointer (&contents, g_bytes_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_at_spi_context_class_init (GtkAtSpiContextClass *klass)
|
||||
{
|
||||
@@ -1582,6 +1694,9 @@ gtk_at_spi_context_class_init (GtkAtSpiContextClass *klass)
|
||||
context_class->bounds_change = gtk_at_spi_context_bounds_change;
|
||||
context_class->child_change = gtk_at_spi_context_child_change;
|
||||
context_class->announce = gtk_at_spi_context_announce;
|
||||
context_class->update_caret_position = gtk_at_spi_context_update_caret_position;
|
||||
context_class->update_selection_bound = gtk_at_spi_context_update_selection_bound;
|
||||
context_class->update_text_contents = gtk_at_spi_context_update_text_contents;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -20,266 +20,6 @@
|
||||
#include "gtkatspipangoprivate.h"
|
||||
#include "gtkpangoprivate.h"
|
||||
|
||||
void
|
||||
gtk_pango_get_font_attributes (PangoFontDescription *font,
|
||||
GVariantBuilder *builder)
|
||||
{
|
||||
char buf[60];
|
||||
|
||||
g_variant_builder_add (builder, "{ss}", "style",
|
||||
pango_style_to_string (pango_font_description_get_style (font)));
|
||||
g_variant_builder_add (builder, "{ss}", "variant",
|
||||
pango_variant_to_string (pango_font_description_get_variant (font)));
|
||||
g_variant_builder_add (builder, "{ss}", "stretch",
|
||||
pango_stretch_to_string (pango_font_description_get_stretch (font)));
|
||||
g_variant_builder_add (builder, "{ss}", "family-name",
|
||||
pango_font_description_get_family (font));
|
||||
|
||||
g_snprintf (buf, 60, "%d", pango_font_description_get_weight (font));
|
||||
g_variant_builder_add (builder, "{ss}", "weight", buf);
|
||||
g_snprintf (buf, 60, "%i", pango_font_description_get_size (font) / PANGO_SCALE);
|
||||
g_variant_builder_add (builder, "{ss}", "size", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_pango_get_default_attributes:
|
||||
* @layout: the `PangoLayout` from which to get attributes
|
||||
* @builder: a `GVariantBuilder` to add to
|
||||
*
|
||||
* Adds the default text attributes from @layout to @builder,
|
||||
* after translating them from Pango attributes to atspi
|
||||
* attributes.
|
||||
*
|
||||
* This is a convenience function that can be used to implement
|
||||
* support for the `AtkText` interface in widgets using Pango
|
||||
* layouts.
|
||||
*
|
||||
* Returns: the modified @attributes
|
||||
*/
|
||||
void
|
||||
gtk_pango_get_default_attributes (PangoLayout *layout,
|
||||
GVariantBuilder *builder)
|
||||
{
|
||||
PangoContext *context;
|
||||
|
||||
context = pango_layout_get_context (layout);
|
||||
if (context)
|
||||
{
|
||||
PangoLanguage *language;
|
||||
PangoFontDescription *font;
|
||||
|
||||
language = pango_context_get_language (context);
|
||||
if (language)
|
||||
g_variant_builder_add (builder, "{ss}", "language",
|
||||
pango_language_to_string (language));
|
||||
|
||||
font = pango_context_get_font_description (context);
|
||||
if (font)
|
||||
gtk_pango_get_font_attributes (font, builder);
|
||||
}
|
||||
|
||||
g_variant_builder_add (builder, "{ss}", "justification",
|
||||
pango_align_to_string (pango_layout_get_alignment (layout)));
|
||||
|
||||
g_variant_builder_add (builder, "{ss}", "wrap-mode",
|
||||
pango_wrap_mode_to_string (pango_layout_get_wrap (layout)));
|
||||
g_variant_builder_add (builder, "{ss}", "strikethrough", "false");
|
||||
g_variant_builder_add (builder, "{ss}", "underline", "false");
|
||||
g_variant_builder_add (builder, "{ss}", "rise", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "scale", "1");
|
||||
g_variant_builder_add (builder, "{ss}", "bg-full-height", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "editable", "false");
|
||||
g_variant_builder_add (builder, "{ss}", "invisible", "false");
|
||||
g_variant_builder_add (builder, "{ss}", "indent", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "right-margin", "0");
|
||||
g_variant_builder_add (builder, "{ss}", "left-margin", "0");
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_pango_get_run_attributes:
|
||||
* @layout: the `PangoLayout` to get the attributes from
|
||||
* @builder: `GVariantBuilder` to add to
|
||||
* @offset: the offset at which the attributes are wanted
|
||||
* @start_offset: return location for the starting offset
|
||||
* of the current run
|
||||
* @end_offset: return location for the ending offset of the
|
||||
* current run
|
||||
*
|
||||
* Finds the “run” around index (i.e. the maximal range of characters
|
||||
* where the set of applicable attributes remains constant) and
|
||||
* returns the starting and ending offsets for it.
|
||||
*
|
||||
* The attributes for the run are added to @attributes, after
|
||||
* translating them from Pango attributes to atspi attributes.
|
||||
*
|
||||
* This is a convenience function that can be used to implement
|
||||
* support for the #AtkText interface in widgets using Pango
|
||||
* layouts.
|
||||
*/
|
||||
void
|
||||
gtk_pango_get_run_attributes (PangoLayout *layout,
|
||||
GVariantBuilder *builder,
|
||||
int offset,
|
||||
int *start_offset,
|
||||
int *end_offset)
|
||||
{
|
||||
PangoAttrIterator *iter;
|
||||
PangoAttrList *attr;
|
||||
PangoAttrString *pango_string;
|
||||
PangoAttrInt *pango_int;
|
||||
PangoAttrColor *pango_color;
|
||||
PangoAttrLanguage *pango_lang;
|
||||
PangoAttrFloat *pango_float;
|
||||
int index, start_index, end_index;
|
||||
gboolean is_next;
|
||||
glong len;
|
||||
const char *text;
|
||||
char *value;
|
||||
const char *val;
|
||||
|
||||
text = pango_layout_get_text (layout);
|
||||
len = g_utf8_strlen (text, -1);
|
||||
|
||||
/* Grab the attributes of the PangoLayout, if any */
|
||||
attr = pango_layout_get_attributes (layout);
|
||||
|
||||
if (attr == NULL)
|
||||
{
|
||||
*start_offset = 0;
|
||||
*end_offset = len;
|
||||
return;
|
||||
}
|
||||
|
||||
iter = pango_attr_list_get_iterator (attr);
|
||||
/* Get invariant range offsets */
|
||||
/* If offset out of range, set offset in range */
|
||||
if (offset > len)
|
||||
offset = len;
|
||||
else if (offset < 0)
|
||||
offset = 0;
|
||||
|
||||
index = g_utf8_offset_to_pointer (text, offset) - text;
|
||||
pango_attr_iterator_range (iter, &start_index, &end_index);
|
||||
is_next = TRUE;
|
||||
while (is_next)
|
||||
{
|
||||
if (index >= start_index && index < end_index)
|
||||
{
|
||||
*start_offset = g_utf8_pointer_to_offset (text, text + start_index);
|
||||
if (end_index == G_MAXINT) /* Last iterator */
|
||||
end_index = len;
|
||||
|
||||
*end_offset = g_utf8_pointer_to_offset (text, text + end_index);
|
||||
break;
|
||||
}
|
||||
is_next = pango_attr_iterator_next (iter);
|
||||
pango_attr_iterator_range (iter, &start_index, &end_index);
|
||||
}
|
||||
|
||||
/* Get attributes */
|
||||
pango_string = (PangoAttrString *) pango_attr_iterator_get (iter, PANGO_ATTR_FAMILY);
|
||||
if (pango_string != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%s", pango_string->value);
|
||||
g_variant_builder_add (builder, "{ss}", "family-name", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_STYLE);
|
||||
if (pango_int != NULL)
|
||||
g_variant_builder_add (builder, "{ss}", "style", pango_style_to_string (pango_int->value));
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_WEIGHT);
|
||||
if (pango_int != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%i", pango_int->value);
|
||||
g_variant_builder_add (builder, "{ss}", "weight", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_VARIANT);
|
||||
if (pango_int != NULL)
|
||||
g_variant_builder_add (builder, "{ss}", "variant",
|
||||
pango_variant_to_string (pango_int->value));
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_STRETCH);
|
||||
if (pango_int != NULL)
|
||||
g_variant_builder_add (builder, "{ss}", "stretch",
|
||||
pango_stretch_to_string (pango_int->value));
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_SIZE);
|
||||
if (pango_int != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%i", pango_int->value / PANGO_SCALE);
|
||||
g_variant_builder_add (builder, "{ss}", "size", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_UNDERLINE);
|
||||
if (pango_int != NULL)
|
||||
g_variant_builder_add (builder, "{ss}", "underline",
|
||||
pango_underline_to_string (pango_int->value));
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_STRIKETHROUGH);
|
||||
if (pango_int != NULL)
|
||||
{
|
||||
if (pango_int->value)
|
||||
val = "true";
|
||||
else
|
||||
val = "false";
|
||||
g_variant_builder_add (builder, "{ss}", "strikethrough", val);
|
||||
}
|
||||
|
||||
pango_int = (PangoAttrInt *) pango_attr_iterator_get (iter, PANGO_ATTR_RISE);
|
||||
if (pango_int != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%i", pango_int->value);
|
||||
g_variant_builder_add (builder, "{ss}", "rise", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_lang = (PangoAttrLanguage *) pango_attr_iterator_get (iter, PANGO_ATTR_LANGUAGE);
|
||||
if (pango_lang != NULL)
|
||||
{
|
||||
g_variant_builder_add (builder, "{ss}", "language",
|
||||
pango_language_to_string (pango_lang->value));
|
||||
}
|
||||
|
||||
pango_float = (PangoAttrFloat *) pango_attr_iterator_get (iter, PANGO_ATTR_SCALE);
|
||||
if (pango_float != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%g", pango_float->value);
|
||||
g_variant_builder_add (builder, "{ss}", "scale", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_color = (PangoAttrColor *) pango_attr_iterator_get (iter, PANGO_ATTR_FOREGROUND);
|
||||
if (pango_color != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%u,%u,%u",
|
||||
pango_color->color.red,
|
||||
pango_color->color.green,
|
||||
pango_color->color.blue);
|
||||
g_variant_builder_add (builder, "{ss}", "fg-color", value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
pango_color = (PangoAttrColor *) pango_attr_iterator_get (iter, PANGO_ATTR_BACKGROUND);
|
||||
if (pango_color != NULL)
|
||||
{
|
||||
value = g_strdup_printf ("%u,%u,%u",
|
||||
pango_color->color.red,
|
||||
pango_color->color.green,
|
||||
pango_color->color.blue);
|
||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
||||
g_free (value);
|
||||
}
|
||||
pango_attr_iterator_destroy (iter);
|
||||
}
|
||||
|
||||
/*
|
||||
* gtk_pango_move_chars:
|
||||
* @layout: a `PangoLayout`
|
||||
@@ -1080,75 +820,3 @@ gtk_pango_get_text_at (PangoLayout *layout,
|
||||
|
||||
return g_utf8_substring (text, start, end);
|
||||
}
|
||||
|
||||
char *gtk_pango_get_string_at (PangoLayout *layout,
|
||||
int offset,
|
||||
AtspiTextGranularity granularity,
|
||||
int *start_offset,
|
||||
int *end_offset)
|
||||
{
|
||||
const char *text;
|
||||
int start, end;
|
||||
const PangoLogAttr *attrs;
|
||||
int n_attrs;
|
||||
|
||||
text = pango_layout_get_text (layout);
|
||||
|
||||
if (text[0] == 0)
|
||||
{
|
||||
*start_offset = 0;
|
||||
*end_offset = 0;
|
||||
return g_strdup ("");
|
||||
}
|
||||
|
||||
attrs = pango_layout_get_log_attrs_readonly (layout, &n_attrs);
|
||||
|
||||
start = offset;
|
||||
end = start;
|
||||
|
||||
switch (granularity)
|
||||
{
|
||||
case ATSPI_TEXT_GRANULARITY_CHAR:
|
||||
end = gtk_pango_move_chars (layout, end, 1);
|
||||
break;
|
||||
|
||||
case ATSPI_TEXT_GRANULARITY_WORD:
|
||||
if (!attrs[start].is_word_start)
|
||||
start = gtk_pango_move_words (layout, start, -1);
|
||||
if (gtk_pango_is_inside_word (layout, end))
|
||||
end = gtk_pango_move_words (layout, end, 1);
|
||||
while (!attrs[end].is_word_start && end < n_attrs - 1)
|
||||
end = gtk_pango_move_chars (layout, end, 1);
|
||||
break;
|
||||
|
||||
case ATSPI_TEXT_GRANULARITY_SENTENCE:
|
||||
if (!attrs[start].is_sentence_start)
|
||||
start = gtk_pango_move_sentences (layout, start, -1);
|
||||
if (gtk_pango_is_inside_sentence (layout, end))
|
||||
end = gtk_pango_move_sentences (layout, end, 1);
|
||||
while (!attrs[end].is_sentence_start && end < n_attrs - 1)
|
||||
end = gtk_pango_move_chars (layout, end, 1);
|
||||
break;
|
||||
|
||||
case ATSPI_TEXT_GRANULARITY_LINE:
|
||||
pango_layout_get_line_at (layout, offset, ATSPI_TEXT_BOUNDARY_LINE_START, &start, &end);
|
||||
break;
|
||||
|
||||
case ATSPI_TEXT_GRANULARITY_PARAGRAPH:
|
||||
/* FIXME: In theory, a layout can hold more than one paragraph */
|
||||
start = 0;
|
||||
end = g_utf8_strlen (text, -1);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
*start_offset = start;
|
||||
*end_offset = end;
|
||||
|
||||
g_assert (start <= end);
|
||||
|
||||
return g_utf8_substring (text, start, end);
|
||||
}
|
||||
|
||||
@@ -19,19 +19,10 @@
|
||||
|
||||
#include <pango/pangocairo.h>
|
||||
#include "gtkatspiprivate.h"
|
||||
#include "gtkpangoprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_pango_get_font_attributes (PangoFontDescription *font,
|
||||
GVariantBuilder *builder);
|
||||
void gtk_pango_get_default_attributes (PangoLayout *layout,
|
||||
GVariantBuilder *builder);
|
||||
void gtk_pango_get_run_attributes (PangoLayout *layout,
|
||||
GVariantBuilder *builder,
|
||||
int offset,
|
||||
int *start_offset,
|
||||
int *end_offset);
|
||||
|
||||
char *gtk_pango_get_text_before (PangoLayout *layout,
|
||||
int offset,
|
||||
AtspiTextBoundaryType boundary_type,
|
||||
@@ -47,10 +38,5 @@ char *gtk_pango_get_text_after (PangoLayout *layout,
|
||||
AtspiTextBoundaryType boundary_type,
|
||||
int *start_offset,
|
||||
int *end_offset);
|
||||
char *gtk_pango_get_string_at (PangoLayout *layout,
|
||||
int offset,
|
||||
AtspiTextGranularity granularity,
|
||||
int *start_offset,
|
||||
int *end_offset);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
@@ -418,8 +418,8 @@ gtk_at_spi_socket_embed (GtkAtSpiSocket *self,
|
||||
* usually done through a side channel with the remote side, for
|
||||
* example using sockets, or reading the output of a subprocess.
|
||||
*
|
||||
* The remote accessible object at @object_path must be a must
|
||||
* have an `org.a11y.atspi.Socket` interface with the `Embedded()`
|
||||
* The remote accessible object at @object_path must support
|
||||
* the `org.a11y.atspi.Socket` interface with the `Embedded()`
|
||||
* method.
|
||||
*
|
||||
* This constructor can fail, most notably if the accessibility
|
||||
@@ -463,7 +463,7 @@ gtk_at_spi_socket_get_bus_name (GtkAtSpiSocket *self)
|
||||
* gtk_at_spi_socket_get_object_path:
|
||||
* @self: a #GtkAtSpiSocket
|
||||
*
|
||||
* Retrieves the object path of the remove accessible object that
|
||||
* Retrieves the object path of the remote accessible object that
|
||||
* the socket is connected to.
|
||||
*
|
||||
* Returns: (transfer none): the object path of the socket remote
|
||||
|
||||
+563
-75
@@ -29,6 +29,7 @@
|
||||
|
||||
#include "a11y/atspi/atspi-text.h"
|
||||
|
||||
#include "gtkaccessibletextprivate.h"
|
||||
#include "gtkatcontextprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkeditable.h"
|
||||
@@ -44,6 +45,356 @@
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
static GtkAccessibleTextGranularity
|
||||
atspi_granularity_to_gtk (AtspiTextGranularity granularity)
|
||||
{
|
||||
switch (granularity)
|
||||
{
|
||||
case ATSPI_TEXT_GRANULARITY_CHAR:
|
||||
return GTK_ACCESSIBLE_TEXT_GRANULARITY_CHARACTER;
|
||||
case ATSPI_TEXT_GRANULARITY_WORD:
|
||||
return GTK_ACCESSIBLE_TEXT_GRANULARITY_WORD;
|
||||
case ATSPI_TEXT_GRANULARITY_SENTENCE:
|
||||
return GTK_ACCESSIBLE_TEXT_GRANULARITY_SENTENCE;
|
||||
case ATSPI_TEXT_GRANULARITY_LINE:
|
||||
return GTK_ACCESSIBLE_TEXT_GRANULARITY_LINE;
|
||||
case ATSPI_TEXT_GRANULARITY_PARAGRAPH:
|
||||
return GTK_ACCESSIBLE_TEXT_GRANULARITY_PARAGRAPH;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
/* {{{ GtkAccessibleText */
|
||||
|
||||
static void
|
||||
accessible_text_handle_method (GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *method_name,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkATContext *self = user_data;
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
|
||||
GtkAccessibleText *accessible_text = GTK_ACCESSIBLE_TEXT (accessible);
|
||||
|
||||
if (g_strcmp0 (method_name, "GetCaretOffset") == 0)
|
||||
{
|
||||
guint offset;
|
||||
|
||||
offset = gtk_accessible_text_get_caret_position (accessible_text);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", (int)offset));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "SetCaretOffset") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetText") == 0)
|
||||
{
|
||||
int start, end;
|
||||
GBytes *contents;
|
||||
|
||||
g_variant_get (parameters, "(ii)", &start, &end);
|
||||
|
||||
contents = gtk_accessible_text_get_contents (accessible_text, start, end < 0 ? G_MAXUINT : end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", g_bytes_get_data (contents, NULL)));
|
||||
|
||||
g_bytes_unref (contents);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextBeforeOffset") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This method is deprecated in favor of GetStringAtOffset");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextAtOffset") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This method is deprecated in favor of GetStringAtOffset");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetTextAfterOffset") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "This method is deprecated in favor of GetStringAtOffset");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetCharacterAtOffset") == 0)
|
||||
{
|
||||
int offset;
|
||||
gunichar ch = 0;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
GBytes *text = gtk_accessible_text_get_contents (accessible_text, offset, offset + 1);
|
||||
|
||||
if (text != NULL)
|
||||
{
|
||||
const char *str = g_bytes_get_data (text, NULL);
|
||||
if (g_utf8_strlen (str, -1) > 0)
|
||||
ch = g_utf8_get_char (str);
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", ch));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetStringAtOffset") == 0)
|
||||
{
|
||||
unsigned int start, end;
|
||||
int offset;
|
||||
AtspiTextGranularity granularity;
|
||||
GBytes *bytes;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
bytes = gtk_accessible_text_get_contents_at (accessible_text, offset,
|
||||
atspi_granularity_to_gtk (granularity),
|
||||
&start, &end);
|
||||
|
||||
if (bytes == NULL)
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", "", -1, -1));
|
||||
else
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", g_bytes_get_data (bytes, NULL), start, end));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gsize n_attrs = 0;
|
||||
GtkAccessibleTextRange *ranges = NULL;
|
||||
int start, end;
|
||||
char **attr_names = NULL;
|
||||
char **attr_values = NULL;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_accessible_text_get_attributes (accessible_text,
|
||||
offset,
|
||||
&n_attrs,
|
||||
&ranges,
|
||||
&attr_names,
|
||||
&attr_values);
|
||||
|
||||
start = 0;
|
||||
end = G_MAXINT;
|
||||
|
||||
for (int i = 0; i < n_attrs; i++)
|
||||
{
|
||||
g_variant_builder_add (&builder, "{ss}", attr_names[i], attr_values[i]);
|
||||
start = MAX (start, ranges[i].start);
|
||||
end = MIN (end, start + ranges[i].length);
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
|
||||
g_clear_pointer (&ranges, g_free);
|
||||
g_strfreev (attr_names);
|
||||
g_strfreev (attr_values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
int offset;
|
||||
const char *name;
|
||||
const char *val = "";
|
||||
char **names, **values;
|
||||
GtkAccessibleTextRange *ranges;
|
||||
gsize n_ranges;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
gtk_accessible_text_get_attributes (accessible_text, offset,
|
||||
&n_ranges, &ranges,
|
||||
&names, &values);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
{
|
||||
if (g_strcmp0 (names[i], name) == 0)
|
||||
{
|
||||
val = values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
gboolean include_defaults = FALSE;
|
||||
int offset;
|
||||
gsize n_ranges = 0;
|
||||
GtkAccessibleTextRange *ranges = NULL;
|
||||
int start, end;
|
||||
char **attr_names = NULL;
|
||||
char **attr_values = NULL;
|
||||
gboolean res;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
res = gtk_accessible_text_get_attributes_run (accessible_text,
|
||||
offset,
|
||||
include_defaults,
|
||||
&n_ranges,
|
||||
&ranges,
|
||||
&attr_names,
|
||||
&attr_values);
|
||||
if (!res)
|
||||
{
|
||||
/* No attributes */
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, 0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; attr_names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", attr_names[i], attr_values[i]);
|
||||
|
||||
start = 0;
|
||||
end = G_MAXINT;
|
||||
for (unsigned i = 0; i < n_ranges; i++)
|
||||
{
|
||||
start = MAX (start, ranges[i].start);
|
||||
end = MIN (end, start + ranges[i].length);
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
|
||||
g_clear_pointer (&ranges, g_free);
|
||||
g_strfreev (attr_names);
|
||||
g_strfreev (attr_values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
char **names, **values;
|
||||
|
||||
gtk_accessible_text_get_default_attributes (accessible_text, &names, &values);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||
{
|
||||
gsize n_ranges;
|
||||
GtkAccessibleTextRange *ranges = NULL;
|
||||
|
||||
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||
n_ranges = 0;
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(i)", (int)n_ranges));
|
||||
|
||||
g_clear_pointer (&ranges, g_free);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetSelection") == 0)
|
||||
{
|
||||
int num;
|
||||
gsize n_ranges;
|
||||
GtkAccessibleTextRange *ranges = NULL;
|
||||
|
||||
g_variant_get (parameters, "(i)", &num);
|
||||
|
||||
if (!gtk_accessible_text_get_selection (accessible_text, &n_ranges, &ranges))
|
||||
n_ranges = 0;
|
||||
|
||||
if (num < 0 || num >= n_ranges)
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Not a valid selection: %d", num);
|
||||
else
|
||||
{
|
||||
int start = ranges[num].start;
|
||||
int end = start + ranges[num].length;
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(ii)", start, end));
|
||||
}
|
||||
|
||||
g_clear_pointer (&ranges, g_free);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "AddSelection") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "RemoveSelection") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "SetSelection") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetCharacterExtents") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetRangeExtents") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetBoundedRanges") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "ScrollSubstringTo") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "ScrollSubstringToPoint") == 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error_literal (invocation, G_DBUS_ERROR, G_DBUS_ERROR_NOT_SUPPORTED, "");
|
||||
}
|
||||
}
|
||||
|
||||
static GVariant *
|
||||
accessible_text_get_property (GDBusConnection *connection,
|
||||
const gchar *sender,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *property_name,
|
||||
GError **error,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkATContext *self = user_data;
|
||||
GtkAccessible *accessible = gtk_at_context_get_accessible (self);
|
||||
GtkAccessibleText *accessible_text = GTK_ACCESSIBLE_TEXT (accessible);
|
||||
|
||||
if (g_strcmp0 (property_name, "CharacterCount") == 0)
|
||||
{
|
||||
GBytes *contents;
|
||||
const char *str;
|
||||
gsize len;
|
||||
|
||||
contents = gtk_accessible_text_get_contents (accessible_text, 0, G_MAXUINT);
|
||||
str = g_bytes_get_data (contents, NULL);
|
||||
len = g_utf8_strlen (str, -1);
|
||||
g_bytes_unref (contents);
|
||||
|
||||
return g_variant_new_int32 ((int) len);
|
||||
}
|
||||
else if (g_strcmp0 (property_name, "CaretOffset") == 0)
|
||||
{
|
||||
guint offset;
|
||||
|
||||
offset = gtk_accessible_text_get_caret_position (accessible_text);
|
||||
|
||||
return g_variant_new_int32 ((int) offset);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const GDBusInterfaceVTable accessible_text_vtable = {
|
||||
accessible_text_handle_method,
|
||||
accessible_text_get_property,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
/* {{{ GtkLabel */
|
||||
|
||||
static void
|
||||
@@ -175,11 +526,13 @@ label_handle_method (GDBusConnection *connection,
|
||||
int offset;
|
||||
AtspiTextGranularity granularity;
|
||||
char *string;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
string = gtk_pango_get_string_at (layout, offset, granularity, &start, &end);
|
||||
string = gtk_pango_get_string_at (layout, offset,
|
||||
atspi_granularity_to_gtk (granularity),
|
||||
&start, &end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
@@ -189,34 +542,47 @@ label_handle_method (GDBusConnection *connection,
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
unsigned int start, end;
|
||||
const char *val = "";
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
val = "";
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
{
|
||||
if (g_strcmp0 (names[i], name) == 0)
|
||||
{
|
||||
val = values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_variant_unref (attrs);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
@@ -224,14 +590,29 @@ label_handle_method (GDBusConnection *connection,
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
if (include_defaults)
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
{
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
@@ -240,8 +621,15 @@ label_handle_method (GDBusConnection *connection,
|
||||
{
|
||||
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
char **names, **values;
|
||||
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
}
|
||||
@@ -528,11 +916,13 @@ inscription_handle_method (GDBusConnection *connection,
|
||||
int offset;
|
||||
AtspiTextGranularity granularity;
|
||||
char *string;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
string = gtk_pango_get_string_at (layout, offset, granularity, &start, &end);
|
||||
string = gtk_pango_get_string_at (layout, offset,
|
||||
atspi_granularity_to_gtk (granularity),
|
||||
&start, &end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
@@ -542,34 +932,47 @@ inscription_handle_method (GDBusConnection *connection,
|
||||
PangoLayout *layout = gtk_inscription_get_layout (GTK_INSCRIPTION (widget));;
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_inscription_get_layout (GTK_INSCRIPTION (widget));;
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
unsigned int start, end;
|
||||
const char *val = "";
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
val = "";
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
{
|
||||
if (g_strcmp0 (names[i], name) == 0)
|
||||
{
|
||||
val = values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_variant_unref (attrs);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
@@ -577,14 +980,29 @@ inscription_handle_method (GDBusConnection *connection,
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
if (include_defaults)
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
{
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
@@ -593,8 +1011,15 @@ inscription_handle_method (GDBusConnection *connection,
|
||||
{
|
||||
PangoLayout *layout = gtk_inscription_get_layout (GTK_INSCRIPTION (widget));;
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
char **names, **values;
|
||||
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
}
|
||||
@@ -685,15 +1110,20 @@ gtk_editable_get_text_widget (GtkWidget *widget)
|
||||
{
|
||||
if (GTK_IS_EDITABLE (widget))
|
||||
{
|
||||
GtkEditable *delegate;
|
||||
GtkEditable *editable;
|
||||
guint redirects = 0;
|
||||
|
||||
delegate = gtk_editable_get_delegate (GTK_EDITABLE (widget));
|
||||
editable = GTK_EDITABLE (widget);
|
||||
|
||||
if (GTK_IS_TEXT (delegate))
|
||||
return GTK_TEXT (delegate);
|
||||
do {
|
||||
if (GTK_IS_TEXT (editable))
|
||||
return GTK_TEXT (editable);
|
||||
|
||||
if (GTK_IS_TEXT (widget))
|
||||
return GTK_TEXT (widget);
|
||||
if (++redirects >= 6)
|
||||
g_assert_not_reached ();
|
||||
|
||||
editable = gtk_editable_get_delegate (editable);
|
||||
} while (editable != NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -827,11 +1257,13 @@ editable_handle_method (GDBusConnection *connection,
|
||||
int offset;
|
||||
AtspiTextGranularity granularity;
|
||||
char *string;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
string = gtk_pango_get_string_at (layout, offset, granularity, &start, &end);
|
||||
string = gtk_pango_get_string_at (layout, offset,
|
||||
atspi_granularity_to_gtk (granularity),
|
||||
&start, &end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
@@ -841,33 +1273,47 @@ editable_handle_method (GDBusConnection *connection,
|
||||
PangoLayout *layout = gtk_text_get_layout (text_widget);
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
PangoLayout *layout = gtk_text_get_layout (text_widget);
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
unsigned int start, end;
|
||||
const char *val = "";
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
val = "";
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
{
|
||||
if (g_strcmp0 (names[i], name) == 0)
|
||||
{
|
||||
val = values[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_variant_unref (attrs);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
@@ -875,14 +1321,29 @@ editable_handle_method (GDBusConnection *connection,
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
unsigned int start, end;
|
||||
char **names, **values;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
if (include_defaults)
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
{
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
gtk_pango_get_run_attributes (layout, &builder, offset, &start, &end);
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
}
|
||||
|
||||
gtk_pango_get_run_attributes (layout, offset, &names, &values, &start, &end);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
}
|
||||
@@ -891,8 +1352,15 @@ editable_handle_method (GDBusConnection *connection,
|
||||
{
|
||||
PangoLayout *layout = gtk_text_get_layout (text_widget);
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
char **names, **values;
|
||||
|
||||
gtk_pango_get_default_attributes (layout, &builder);
|
||||
gtk_pango_get_default_attributes (layout, &names, &values);
|
||||
|
||||
for (unsigned i = 0; names[i] != NULL; i++)
|
||||
g_variant_builder_add (&builder, "{ss}", names[i], values[i]);
|
||||
|
||||
g_strfreev (names);
|
||||
g_strfreev (values);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
}
|
||||
@@ -1191,70 +1659,88 @@ text_view_handle_method (GDBusConnection *connection,
|
||||
|
||||
g_variant_get (parameters, "(iu)", &offset, &granularity);
|
||||
|
||||
string = gtk_text_view_get_string_at (GTK_TEXT_VIEW (widget), offset, granularity, &start, &end);
|
||||
string = gtk_text_view_get_string_at (GTK_TEXT_VIEW (widget), offset,
|
||||
granularity,
|
||||
&start, &end);
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(sii)", string, start, end));
|
||||
g_free (string);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributes") == 0)
|
||||
{
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
GHashTable *attrs;
|
||||
GHashTableIter iter;
|
||||
int offset;
|
||||
int start, end;
|
||||
gpointer key, value;
|
||||
|
||||
g_variant_get (parameters, "(i)", &offset);
|
||||
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
||||
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, FALSE, &start, &end);
|
||||
g_hash_table_iter_init (&iter, attrs);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
|
||||
g_hash_table_unref (attrs);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeValue") == 0)
|
||||
{
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
const char *name;
|
||||
int start, end;
|
||||
GVariant *attrs;
|
||||
const char *val;
|
||||
GHashTable *attrs;
|
||||
|
||||
g_variant_get (parameters, "(i&s)", &offset, &name);
|
||||
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
||||
|
||||
attrs = g_variant_builder_end (&builder);
|
||||
if (!g_variant_lookup (attrs, name, "&s", &val))
|
||||
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, FALSE, &start, &end);
|
||||
val = g_hash_table_lookup (attrs, name);
|
||||
if (val == NULL)
|
||||
val = "";
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", val));
|
||||
g_variant_unref (attrs);
|
||||
g_hash_table_unref (attrs);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetAttributeRun") == 0)
|
||||
{
|
||||
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
int offset;
|
||||
gboolean include_defaults;
|
||||
int start, end;
|
||||
GHashTable *attrs;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_variant_get (parameters, "(ib)", &offset, &include_defaults);
|
||||
|
||||
if (include_defaults)
|
||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &builder);
|
||||
|
||||
gtk_text_buffer_get_run_attributes (buffer, &builder, offset, &start, &end);
|
||||
attrs = gtk_text_view_get_attributes_run (GTK_TEXT_VIEW (widget), offset, include_defaults, &start, &end);
|
||||
g_hash_table_iter_init (&iter, attrs);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss}ii)", &builder, start, end));
|
||||
|
||||
g_hash_table_unref (attrs);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetDefaultAttributes") == 0 ||
|
||||
g_strcmp0 (method_name, "GetDefaultAttributeSet") == 0)
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("a{ss}"));
|
||||
GHashTable *attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), &builder);
|
||||
gtk_text_view_add_default_attributes (GTK_TEXT_VIEW (widget), attrs);
|
||||
g_hash_table_iter_init (&iter, attrs);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
g_variant_builder_add (&builder, "{ss}", key, value != NULL ? value : "");
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(a{ss})", &builder));
|
||||
|
||||
g_hash_table_unref (attrs);
|
||||
}
|
||||
else if (g_strcmp0 (method_name, "GetNSelections") == 0)
|
||||
{
|
||||
@@ -1573,7 +2059,9 @@ static const GDBusInterfaceVTable text_view_vtable = {
|
||||
const GDBusInterfaceVTable *
|
||||
gtk_atspi_get_text_vtable (GtkAccessible *accessible)
|
||||
{
|
||||
if (GTK_IS_LABEL (accessible))
|
||||
if (GTK_IS_ACCESSIBLE_TEXT (accessible))
|
||||
return &accessible_text_vtable;
|
||||
else if (GTK_IS_LABEL (accessible))
|
||||
return &label_vtable;
|
||||
else if (GTK_IS_INSCRIPTION (accessible))
|
||||
return &inscription_vtable;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user