Compare commits
429 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0eff31d7d5 | |||
| 32e21d5402 | |||
| fb3d8b8523 | |||
| 380523b41b | |||
| 2fda256bb0 | |||
| c71a66b6f6 | |||
| cb92778478 | |||
| ab67936a64 | |||
| 0ae2c1a8a7 | |||
| 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 | |||
| 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
|
||||
|
||||
+32
-36
@@ -210,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:
|
||||
@@ -430,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
|
||||
@@ -486,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,3 +1,156 @@
|
||||
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
|
||||
=========================================
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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") ||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+14
-26
@@ -5,6 +5,7 @@
|
||||
#include "gskglbufferprivate.h"
|
||||
#include "gskglimageprivate.h"
|
||||
|
||||
|
||||
struct _GskGLDescriptors
|
||||
{
|
||||
GskGpuDescriptors parent_instance;
|
||||
@@ -13,16 +14,12 @@ struct _GskGLDescriptors
|
||||
guint n_external;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_finalize (GObject *object)
|
||||
gsk_gl_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
{
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (object);
|
||||
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (desc);
|
||||
|
||||
g_object_unref (self->device);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gl_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -72,33 +69,24 @@ gsk_gl_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_class_init (GskGLDescriptorsClass *klass)
|
||||
static GskGpuDescriptorsClass GSK_GL_DESCRIPTORS_CLASS =
|
||||
{
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_gl_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_gl_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_gl_descriptors_add_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_descriptors_init (GskGLDescriptors *self)
|
||||
{
|
||||
}
|
||||
.finalize = gsk_gl_descriptors_finalize,
|
||||
.add_image = gsk_gl_descriptors_add_image,
|
||||
.add_buffer = gsk_gl_descriptors_add_buffer,
|
||||
};
|
||||
|
||||
GskGpuDescriptors *
|
||||
gsk_gl_descriptors_new (GskGLDevice *device)
|
||||
{
|
||||
GskGLDescriptors *self;
|
||||
GskGpuDescriptors *desc;
|
||||
|
||||
self = g_object_new (GSK_TYPE_GL_DESCRIPTORS, NULL);
|
||||
desc = gsk_gpu_descriptors_new ((GskGpuDescriptorsClass *) &GSK_GL_DESCRIPTORS_CLASS,
|
||||
sizeof (GskGLDescriptors));
|
||||
|
||||
self->device = g_object_ref (device);
|
||||
GSK_GL_DESCRIPTORS (desc)->device = g_object_ref (device);
|
||||
|
||||
return GSK_GPU_DESCRIPTORS (self);
|
||||
return desc;
|
||||
}
|
||||
|
||||
guint
|
||||
@@ -110,7 +98,7 @@ gsk_gl_descriptors_get_n_external (GskGLDescriptors *self)
|
||||
void
|
||||
gsk_gl_descriptors_use (GskGLDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
GskGpuDescriptors *desc = &self->parent_instance;
|
||||
gsize i, ext, n_textures;
|
||||
|
||||
n_textures = 16 - 3 * self->n_external;
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_DESCRIPTORS (gsk_gl_descriptors_get_type ())
|
||||
typedef struct _GskGLDescriptors GskGLDescriptors;
|
||||
|
||||
#define GSK_GL_DESCRIPTORS(d) ((GskGLDescriptors *) (d))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK, GL_DESCRIPTORS, GskGpuDescriptors)
|
||||
|
||||
GskGpuDescriptors * gsk_gl_descriptors_new (GskGLDevice *device);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
+45
-24
@@ -52,43 +52,39 @@ gsk_gpu_buffer_entry_clear (gpointer data)
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
typedef struct _GskGpuDescriptorsPrivate GskGpuDescriptorsPrivate;
|
||||
|
||||
struct _GskGpuDescriptorsPrivate
|
||||
{
|
||||
GskGpuImageEntries images;
|
||||
GskGpuBufferEntries buffers;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuDescriptors, gsk_gpu_descriptors, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gsk_gpu_descriptors_finalize (GObject *object)
|
||||
static inline GskGpuDescriptorsPrivate *
|
||||
gsk_gpu_descriptors_get_instance_private (GskGpuDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptors *self = GSK_GPU_DESCRIPTORS (object);
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
|
||||
gsk_gpu_image_entries_clear (&priv->images);
|
||||
gsk_gpu_buffer_entries_clear (&priv->buffers);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gpu_descriptors_parent_class)->finalize (object);
|
||||
return (GskGpuDescriptorsPrivate *) (((guchar *)self) - sizeof (GskGpuDescriptorsPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_descriptors_class_init (GskGpuDescriptorsClass *klass)
|
||||
/* Just for subclasses */
|
||||
GskGpuDescriptors *
|
||||
gsk_gpu_descriptors_new (GskGpuDescriptorsClass *desc_class,
|
||||
gsize child_size)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GskGpuDescriptors *self;
|
||||
GskGpuDescriptorsPrivate *priv;
|
||||
guchar *data;
|
||||
|
||||
object_class->finalize = gsk_gpu_descriptors_finalize;
|
||||
}
|
||||
data = g_new0 (guchar, child_size + sizeof (GskGpuDescriptorsPrivate));
|
||||
|
||||
static void
|
||||
gsk_gpu_descriptors_init (GskGpuDescriptors *self)
|
||||
{
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
priv = (GskGpuDescriptorsPrivate *) data;
|
||||
self = (GskGpuDescriptors *) (data + sizeof (GskGpuDescriptorsPrivate));
|
||||
|
||||
self->ref_count = 1;
|
||||
self->desc_class = desc_class;
|
||||
|
||||
gsk_gpu_image_entries_init (&priv->images);
|
||||
gsk_gpu_buffer_entries_init (&priv->buffers);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
gsize
|
||||
@@ -189,7 +185,7 @@ gsk_gpu_descriptors_add_image (GskGpuDescriptors *self,
|
||||
}
|
||||
}
|
||||
|
||||
if (!GSK_GPU_DESCRIPTORS_GET_CLASS (self)->add_image (self, image, sampler, &descriptor))
|
||||
if (!self->desc_class->add_image (self, image, sampler, &descriptor))
|
||||
return FALSE;
|
||||
|
||||
gsk_gpu_image_entries_append (&priv->images,
|
||||
@@ -224,7 +220,7 @@ gsk_gpu_descriptors_add_buffer (GskGpuDescriptors *self,
|
||||
}
|
||||
}
|
||||
|
||||
if (!GSK_GPU_DESCRIPTORS_GET_CLASS (self)->add_buffer (self, buffer, &descriptor))
|
||||
if (!self->desc_class->add_buffer (self, buffer, &descriptor))
|
||||
return FALSE;
|
||||
|
||||
gsk_gpu_buffer_entries_append (&priv->buffers,
|
||||
@@ -238,3 +234,28 @@ gsk_gpu_descriptors_add_buffer (GskGpuDescriptors *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GskGpuDescriptors *
|
||||
gsk_gpu_descriptors_ref (GskGpuDescriptors *self)
|
||||
{
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_descriptors_unref (GskGpuDescriptors *self)
|
||||
{
|
||||
self->ref_count--;
|
||||
|
||||
if (self->ref_count == 0)
|
||||
{
|
||||
GskGpuDescriptorsPrivate *priv = gsk_gpu_descriptors_get_instance_private (self);
|
||||
|
||||
self->desc_class->finalize (self);
|
||||
|
||||
gsk_gpu_image_entries_clear (&priv->images);
|
||||
gsk_gpu_buffer_entries_clear (&priv->buffers);
|
||||
|
||||
g_free (priv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,24 +4,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GPU_DESCRIPTORS (gsk_gpu_descriptors_get_type ())
|
||||
#define GSK_GPU_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptors))
|
||||
#define GSK_GPU_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptorsClass))
|
||||
#define GSK_IS_GPU_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSK_TYPE_GPU_DESCRIPTORS))
|
||||
#define GSK_IS_GPU_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSK_TYPE_GPU_DESCRIPTORS))
|
||||
#define GSK_GPU_DESCRIPTORS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSK_TYPE_GPU_DESCRIPTORS, GskGpuDescriptorsClass))
|
||||
|
||||
typedef struct _GskGpuDescriptors GskGpuDescriptors;
|
||||
typedef struct _GskGpuDescriptorsClass GskGpuDescriptorsClass;
|
||||
typedef struct _GskGpuDescriptorsPrivate GskGpuDescriptorsPrivate;
|
||||
|
||||
#define GSK_GPU_DESCRIPTORS(d) ((GskGpuDescriptors *) (d))
|
||||
|
||||
struct _GskGpuDescriptors
|
||||
{
|
||||
GObject parent_instance;
|
||||
GskGpuDescriptorsClass *desc_class;
|
||||
int ref_count;
|
||||
|
||||
GskGpuDescriptorsPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GskGpuDescriptorsClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* finalize) (GskGpuDescriptors *self);
|
||||
gboolean (* add_image) (GskGpuDescriptors *self,
|
||||
GskGpuImage *image,
|
||||
GskGpuSampler sampler,
|
||||
@@ -31,7 +30,8 @@ struct _GskGpuDescriptorsClass
|
||||
guint32 *out_id);
|
||||
};
|
||||
|
||||
GType gsk_gpu_descriptors_get_type (void) G_GNUC_CONST;
|
||||
GskGpuDescriptors * gsk_gpu_descriptors_ref (GskGpuDescriptors *self);
|
||||
void gsk_gpu_descriptors_unref (GskGpuDescriptors *self);
|
||||
|
||||
gsize gsk_gpu_descriptors_get_n_images (GskGpuDescriptors *self);
|
||||
gsize gsk_gpu_descriptors_get_n_buffers (GskGpuDescriptors *self);
|
||||
@@ -55,7 +55,8 @@ gboolean gsk_gpu_descriptors_add_buffer (GskGpuD
|
||||
GskGpuBuffer *buffer,
|
||||
guint32 *out_descriptor);
|
||||
|
||||
GskGpuDescriptors *gsk_gpu_descriptors_new (GskGpuDescriptorsClass *desc_class,
|
||||
gsize child_size);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuDescriptors, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
|
||||
+147
-80
@@ -40,10 +40,16 @@
|
||||
#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
|
||||
*
|
||||
* The rendering code keeps track of multiple coordinate systems to optimize rendering as
|
||||
@@ -146,7 +152,7 @@ static void
|
||||
gsk_gpu_node_processor_finish (GskGpuNodeProcessor *self)
|
||||
{
|
||||
g_clear_pointer (&self->modelview, gsk_transform_unref);
|
||||
g_clear_object (&self->desc);
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -164,7 +170,7 @@ gsk_gpu_node_processor_init (GskGpuNodeProcessor *self,
|
||||
|
||||
self->frame = frame;
|
||||
if (desc)
|
||||
self->desc = g_object_ref (desc);
|
||||
self->desc = gsk_gpu_descriptors_ref (desc);
|
||||
else
|
||||
self->desc = NULL;
|
||||
|
||||
@@ -178,13 +184,13 @@ 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;
|
||||
@@ -262,7 +268,7 @@ gsk_gpu_node_processor_add_image (GskGpuNodeProcessor *self,
|
||||
if (gsk_gpu_descriptors_add_image (self->desc, image, sampler, &descriptor))
|
||||
return descriptor;
|
||||
|
||||
g_object_unref (self->desc);
|
||||
gsk_gpu_descriptors_unref (self->desc);
|
||||
}
|
||||
|
||||
self->desc = gsk_gpu_frame_create_descriptors (self->frame);
|
||||
@@ -339,8 +345,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 (graphene_vec2_get_x (scale) * viewport->size.width - EPSILON);
|
||||
area.height = ceilf (graphene_vec2_get_y (scale) * viewport->size.height - EPSILON);
|
||||
|
||||
image = gsk_gpu_device_create_offscreen_image (gsk_gpu_frame_get_device (frame),
|
||||
FALSE,
|
||||
@@ -539,7 +545,7 @@ gsk_gpu_pattern_writer_finish (GskGpuPatternWriter *self)
|
||||
{
|
||||
pattern_buffer_clear (&self->buffer);
|
||||
g_assert (self->stack == 0);
|
||||
g_clear_object (&self->desc);
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -563,7 +569,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;
|
||||
@@ -748,6 +753,8 @@ gsk_gpu_node_processor_create_offscreen (GskGpuFrame *frame,
|
||||
gsk_render_node_get_preferred_depth (node),
|
||||
scale,
|
||||
viewport);
|
||||
if (image == NULL)
|
||||
return NULL;
|
||||
|
||||
gsk_gpu_node_processor_add_node (&self, node);
|
||||
|
||||
@@ -950,9 +957,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,
|
||||
@@ -997,36 +1008,25 @@ 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 },
|
||||
&intermediate_rect);
|
||||
|
||||
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);
|
||||
|
||||
@@ -1040,11 +1040,7 @@ 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);
|
||||
@@ -1332,7 +1328,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;
|
||||
@@ -1615,7 +1611,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))
|
||||
{
|
||||
@@ -1653,10 +1649,13 @@ gsk_gpu_node_processor_add_transform_node (GskGpuNodeProcessor *self,
|
||||
|
||||
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 (graphene_vec2_get_x (&old_scale) * old_clip.rect.bounds.size.width,
|
||||
graphene_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;
|
||||
@@ -2060,16 +2059,24 @@ gsk_gpu_node_processor_add_texture_scale_node (GskGpuNodeProcessor *self,
|
||||
guint32 descriptor;
|
||||
gboolean need_mipmap, need_offscreen;
|
||||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
need_offscreen = self->modelview != NULL ||
|
||||
!graphene_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);
|
||||
/* 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,
|
||||
@@ -2993,7 +3000,12 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
guint i, num_glyphs;
|
||||
float scale, inv_scale;
|
||||
GdkRGBA color;
|
||||
gboolean glyph_align;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
GskGpuImage *last_image;
|
||||
guint32 descriptor;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
|
||||
if (self->opacity < 1.0 &&
|
||||
gsk_text_node_has_color_glyphs (node))
|
||||
@@ -3002,9 +3014,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);
|
||||
@@ -3017,29 +3028,38 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
scale = MAX (graphene_vec2_get_x (&self->scale), graphene_vec2_get_y (&self->scale));
|
||||
inv_scale = 1.f / scale;
|
||||
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
last_image = NULL;
|
||||
descriptor = 0;
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
{
|
||||
GskGpuImage *image;
|
||||
graphene_rect_t glyph_bounds, glyph_tex_rect;
|
||||
graphene_point_t glyph_offset, glyph_origin;
|
||||
guint32 descriptor;
|
||||
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 (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
|
||||
{
|
||||
flags = 0;
|
||||
}
|
||||
glyph_origin = GRAPHENE_POINT_INIT (offset.x + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
@@ -3050,11 +3070,23 @@ 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 (image != last_image)
|
||||
{
|
||||
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
|
||||
last_image = image;
|
||||
}
|
||||
|
||||
if (glyphs[i].attr.is_color)
|
||||
gsk_gpu_texture_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &glyph_offset, &glyph_bounds),
|
||||
@@ -3073,7 +3105,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
|
||||
&glyph_tex_rect,
|
||||
&color);
|
||||
|
||||
offset.x += (float) glyphs[i].geometry.width / PANGO_SCALE;
|
||||
offset.x += glyphs[i].geometry.width * inv_pango_scale;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3090,6 +3122,10 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
guint32 tex_id;
|
||||
GskGpuImage *last_image;
|
||||
graphene_point_t offset;
|
||||
float align_scale_x, align_scale_y;
|
||||
float inv_align_scale_x, inv_align_scale_y;
|
||||
unsigned int flags_mask;
|
||||
const float inv_pango_scale = 1.f / PANGO_SCALE;
|
||||
|
||||
if (gsk_text_node_has_color_glyphs (node))
|
||||
return FALSE;
|
||||
@@ -3109,18 +3145,43 @@ gsk_gpu_node_processor_create_glyph_pattern (GskGpuPatternWriter *self,
|
||||
gsk_gpu_pattern_writer_append_rgba (self, gsk_text_node_get_color (node));
|
||||
gsk_gpu_pattern_writer_append_uint (self, num_glyphs);
|
||||
|
||||
if (gsk_font_get_hint_style (font) != CAIRO_HINT_STYLE_NONE)
|
||||
{
|
||||
align_scale_x = scale * 4;
|
||||
align_scale_y = scale;
|
||||
flags_mask = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
align_scale_x = align_scale_y = scale * 4;
|
||||
flags_mask = 15;
|
||||
}
|
||||
|
||||
inv_align_scale_x = 1 / align_scale_x;
|
||||
inv_align_scale_y = 1 / align_scale_y;
|
||||
|
||||
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 + glyphs[i].geometry.x_offset * inv_pango_scale,
|
||||
offset.y + glyphs[i].geometry.y_offset * inv_pango_scale);
|
||||
|
||||
glyph_origin.x = floorf (glyph_origin.x * align_scale_x + 0.5f);
|
||||
glyph_origin.y = floorf (glyph_origin.y * align_scale_y + 0.5f);
|
||||
flags = (((int) glyph_origin.x & 3) | (((int) glyph_origin.y & 3) << 2)) & flags_mask;
|
||||
glyph_origin.x *= inv_align_scale_x;
|
||||
glyph_origin.y *= inv_align_scale_y;
|
||||
|
||||
image = gsk_gpu_device_lookup_glyph_image (device,
|
||||
self->frame,
|
||||
font,
|
||||
glyphs[i].glyph,
|
||||
0,
|
||||
flags,
|
||||
scale,
|
||||
&glyph_bounds,
|
||||
&glyph_offset);
|
||||
@@ -3133,8 +3194,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,
|
||||
@@ -3144,7 +3205,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,
|
||||
@@ -3152,9 +3213,9 @@ 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;
|
||||
offset.x += glyphs[i].geometry.width * inv_pango_scale;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -3742,6 +3803,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));
|
||||
}
|
||||
@@ -3781,7 +3848,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,
|
||||
},
|
||||
|
||||
@@ -30,7 +30,6 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
|
||||
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
|
||||
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
|
||||
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
|
||||
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the subpixel grid" },
|
||||
|
||||
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
|
||||
};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -23,7 +23,7 @@ gsk_gpu_shader_op_finish (GskGpuOp *op)
|
||||
{
|
||||
GskGpuShaderOp *self = (GskGpuShaderOp *) op;
|
||||
|
||||
g_clear_object (&self->desc);
|
||||
g_clear_pointer (&self->desc, gsk_gpu_descriptors_unref);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
@@ -197,7 +197,7 @@ gsk_gpu_shader_op_alloc (GskGpuFrame *frame,
|
||||
self->variation = variation;
|
||||
self->clip = clip;
|
||||
if (desc)
|
||||
self->desc = g_object_ref (desc);
|
||||
self->desc = gsk_gpu_descriptors_ref (desc);
|
||||
else
|
||||
self->desc = NULL;
|
||||
self->vertex_offset = gsk_gpu_frame_reserve_vertex_data (frame, op_class->vertex_size);
|
||||
|
||||
@@ -118,8 +118,7 @@ typedef enum {
|
||||
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
|
||||
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
|
||||
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
|
||||
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
|
||||
/* These require hardware support */
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
|
||||
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 6,
|
||||
} GskGpuOptimizations;
|
||||
|
||||
|
||||
@@ -110,8 +110,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,
|
||||
@@ -485,7 +485,6 @@ struct _GskGpuUploadGlyphOp
|
||||
cairo_rectangle_int_t area;
|
||||
PangoFont *font;
|
||||
PangoGlyph glyph;
|
||||
float scale;
|
||||
graphene_point_t origin;
|
||||
|
||||
GskGpuBuffer *buffer;
|
||||
@@ -509,11 +508,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 +531,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 +539,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 +553,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 +624,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 +634,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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -6,22 +6,13 @@
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanDescriptors, gsk_vulkan_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
|
||||
|
||||
static void
|
||||
gsk_vulkan_descriptors_class_init (GskVulkanDescriptorsClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_descriptors_init (GskVulkanDescriptors *self)
|
||||
{
|
||||
}
|
||||
|
||||
GskVulkanPipelineLayout *
|
||||
gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self)
|
||||
{
|
||||
return GSK_VULKAN_DESCRIPTORS_GET_CLASS (self)->get_pipeline_layout (self);
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
GskVulkanDescriptorsClass *class = GSK_VULKAN_DESCRIPTORS_CLASS (desc->desc_class);
|
||||
|
||||
return class->get_pipeline_layout (self);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -48,5 +39,19 @@ gsk_vulkan_descriptors_bind (GskVulkanDescriptors *self,
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer)
|
||||
{
|
||||
return GSK_VULKAN_DESCRIPTORS_GET_CLASS (self)->bind (self, previous, vk_command_buffer);
|
||||
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
|
||||
GskVulkanDescriptorsClass *class = GSK_VULKAN_DESCRIPTORS_CLASS (desc->desc_class);
|
||||
|
||||
return class->bind (self, previous, vk_command_buffer);
|
||||
}
|
||||
|
||||
GskVulkanDescriptors *
|
||||
gsk_vulkan_descriptors_new (GskVulkanDescriptorsClass *desc_class,
|
||||
gsize child_size)
|
||||
{
|
||||
GskGpuDescriptors *desc;
|
||||
|
||||
desc = gsk_gpu_descriptors_new ((GskGpuDescriptorsClass *)desc_class, child_size);
|
||||
|
||||
return GSK_VULKAN_DESCRIPTORS (desc);
|
||||
}
|
||||
|
||||
@@ -6,15 +6,12 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_DESCRIPTORS (gsk_vulkan_descriptors_get_type ())
|
||||
#define GSK_VULKAN_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptors))
|
||||
#define GSK_VULKAN_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptorsClass))
|
||||
#define GSK_IS_VULKAN_DESCRIPTORS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSK_TYPE_VULKAN_DESCRIPTORS))
|
||||
#define GSK_IS_VULKAN_DESCRIPTORS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSK_TYPE_VULKAN_DESCRIPTORS))
|
||||
#define GSK_VULKAN_DESCRIPTORS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSK_TYPE_VULKAN_DESCRIPTORS, GskVulkanDescriptorsClass))
|
||||
|
||||
typedef struct _GskVulkanDescriptors GskVulkanDescriptors;
|
||||
typedef struct _GskVulkanDescriptorsClass GskVulkanDescriptorsClass;
|
||||
|
||||
#define GSK_VULKAN_DESCRIPTORS(d) ((GskVulkanDescriptors *) (d))
|
||||
#define GSK_VULKAN_DESCRIPTORS_CLASS(d) ((GskVulkanDescriptorsClass *) (d))
|
||||
|
||||
struct _GskVulkanDescriptors
|
||||
{
|
||||
GskGpuDescriptors parent_instance;
|
||||
@@ -30,8 +27,6 @@ struct _GskVulkanDescriptorsClass
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
};
|
||||
|
||||
GType gsk_vulkan_descriptors_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GskVulkanPipelineLayout * gsk_vulkan_descriptors_get_pipeline_layout (GskVulkanDescriptors *self);
|
||||
|
||||
void gsk_vulkan_descriptors_transition (GskVulkanDescriptors *self,
|
||||
@@ -41,7 +36,9 @@ void gsk_vulkan_descriptors_bind
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskVulkanDescriptors, g_object_unref)
|
||||
GskVulkanDescriptors * gsk_vulkan_descriptors_new (GskVulkanDescriptorsClass *desc_class,
|
||||
gsize child_size);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -13,10 +13,16 @@
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdkdmabuftextureprivate.h"
|
||||
|
||||
static inline void
|
||||
gsk_vulkan_real_descriptors_unref (GskVulkanRealDescriptors *desc)
|
||||
{
|
||||
gsk_gpu_descriptors_unref (GSK_GPU_DESCRIPTORS (desc));
|
||||
}
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_descriptors
|
||||
#define GDK_ARRAY_TYPE_NAME GskDescriptors
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GskVulkanRealDescriptors *
|
||||
#define GDK_ARRAY_FREE_FUNC g_object_unref
|
||||
#define GDK_ARRAY_FREE_FUNC gsk_vulkan_real_descriptors_unref
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
@@ -262,7 +268,7 @@ gsk_vulkan_frame_create_descriptors (GskGpuFrame *frame)
|
||||
desc = gsk_vulkan_real_descriptors_new (self);
|
||||
gsk_descriptors_append (&self->descriptors, desc);
|
||||
|
||||
return GSK_GPU_DESCRIPTORS (g_object_ref (desc));
|
||||
return gsk_gpu_descriptors_ref (GSK_GPU_DESCRIPTORS (desc));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
#include "gskvulkanrealdescriptorsprivate.h"
|
||||
|
||||
#include "gskvulkanbufferprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_descriptor_image_infos
|
||||
#define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorImageInfo
|
||||
@@ -45,8 +41,6 @@ struct _GskVulkanRealDescriptors
|
||||
VkDescriptorSet descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanRealDescriptors, gsk_vulkan_real_descriptors, GSK_TYPE_VULKAN_DESCRIPTORS)
|
||||
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_real_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc)
|
||||
{
|
||||
@@ -154,9 +148,9 @@ gsk_vulkan_real_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_finalize (GObject *object)
|
||||
gsk_vulkan_real_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
{
|
||||
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (object);
|
||||
GskVulkanRealDescriptors *self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
||||
|
||||
gsk_samplers_clear (&self->immutable_samplers);
|
||||
gsk_descriptor_image_infos_clear (&self->descriptor_immutable_images);
|
||||
@@ -165,25 +159,18 @@ gsk_vulkan_real_descriptors_finalize (GObject *object)
|
||||
|
||||
gsk_vulkan_device_release_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self->frame))),
|
||||
self->pipeline_layout);
|
||||
|
||||
G_OBJECT_CLASS (gsk_vulkan_real_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_class_init (GskVulkanRealDescriptorsClass *klass)
|
||||
static GskVulkanDescriptorsClass GSK_VULKAN_REAL_DESCRIPTORS_CLASS =
|
||||
{
|
||||
GskVulkanDescriptorsClass *vulkan_descriptors_class = GSK_VULKAN_DESCRIPTORS_CLASS (klass);
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_vulkan_real_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_vulkan_real_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_vulkan_real_descriptors_add_buffer;
|
||||
|
||||
vulkan_descriptors_class->get_pipeline_layout = gsk_vulkan_real_descriptors_get_pipeline_layout;
|
||||
vulkan_descriptors_class->bind = gsk_vulkan_real_descriptors_bind;
|
||||
}
|
||||
.parent_class = (GskGpuDescriptorsClass) {
|
||||
.finalize = gsk_vulkan_real_descriptors_finalize,
|
||||
.add_image = gsk_vulkan_real_descriptors_add_image,
|
||||
.add_buffer = gsk_vulkan_real_descriptors_add_buffer,
|
||||
},
|
||||
.get_pipeline_layout = gsk_vulkan_real_descriptors_get_pipeline_layout,
|
||||
.bind = gsk_vulkan_real_descriptors_bind
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_vulkan_real_descriptors_init (GskVulkanRealDescriptors *self)
|
||||
@@ -198,9 +185,14 @@ GskVulkanRealDescriptors *
|
||||
gsk_vulkan_real_descriptors_new (GskVulkanFrame *frame)
|
||||
{
|
||||
GskVulkanRealDescriptors *self;
|
||||
GskVulkanDescriptors *desc;
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_REAL_DESCRIPTORS, NULL);
|
||||
desc = gsk_vulkan_descriptors_new (&GSK_VULKAN_REAL_DESCRIPTORS_CLASS,
|
||||
sizeof (GskVulkanRealDescriptors));
|
||||
|
||||
self = GSK_VULKAN_REAL_DESCRIPTORS (desc);
|
||||
|
||||
gsk_vulkan_real_descriptors_init (self);
|
||||
self->frame = frame;
|
||||
|
||||
return self;
|
||||
|
||||
@@ -3,11 +3,17 @@
|
||||
#include "gskvulkandescriptorsprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
|
||||
#include "gskvulkanbufferprivate.h"
|
||||
#include "gskvulkanframeprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_REAL_DESCRIPTORS (gsk_vulkan_real_descriptors_get_type ())
|
||||
typedef struct _GskVulkanRealDescriptors GskVulkanRealDescriptors;
|
||||
|
||||
#define GSK_VULKAN_REAL_DESCRIPTORS(d) ((GskVulkanRealDescriptors *) (d))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskVulkanRealDescriptors, gsk_vulkan_real_descriptors, GSK, VULKAN_REAL_DESCRIPTORS, GskVulkanDescriptors)
|
||||
|
||||
GskVulkanRealDescriptors * gsk_vulkan_real_descriptors_new (GskVulkanFrame *frame);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "gskvulkansubdescriptorsprivate.h"
|
||||
|
||||
|
||||
struct _GskVulkanSubDescriptors
|
||||
{
|
||||
GskVulkanDescriptors parent_instance;
|
||||
@@ -9,7 +10,31 @@ struct _GskVulkanSubDescriptors
|
||||
GskVulkanDescriptors *parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GskVulkanSubDescriptors, gsk_vulkan_sub_descriptors, GSK_TYPE_VULKAN_DESCRIPTORS)
|
||||
|
||||
static void gsk_vulkan_sub_descriptors_finalize (GskGpuDescriptors *desc);
|
||||
static gboolean gsk_vulkan_sub_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
GskGpuBuffer *buffer,
|
||||
guint32 *out_descriptor);
|
||||
static gboolean gsk_vulkan_sub_descriptors_add_image (GskGpuDescriptors *desc,
|
||||
GskGpuImage *image,
|
||||
GskGpuSampler sampler,
|
||||
guint32 *out_descriptor);
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_sub_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc);
|
||||
static void gsk_vulkan_sub_descriptors_bind (GskVulkanDescriptors *desc,
|
||||
GskVulkanDescriptors *previous,
|
||||
VkCommandBuffer vk_command_buffer);
|
||||
|
||||
static GskVulkanDescriptorsClass GSK_VULKAN_SUB_DESCRIPTORS_CLASS =
|
||||
{
|
||||
.parent_class = (GskGpuDescriptorsClass) {
|
||||
.finalize = gsk_vulkan_sub_descriptors_finalize,
|
||||
.add_image = gsk_vulkan_sub_descriptors_add_image,
|
||||
.add_buffer = gsk_vulkan_sub_descriptors_add_buffer,
|
||||
},
|
||||
.get_pipeline_layout = gsk_vulkan_sub_descriptors_get_pipeline_layout,
|
||||
.bind = gsk_vulkan_sub_descriptors_bind,
|
||||
};
|
||||
|
||||
static GskVulkanPipelineLayout *
|
||||
gsk_vulkan_sub_descriptors_get_pipeline_layout (GskVulkanDescriptors *desc)
|
||||
@@ -26,7 +51,7 @@ gsk_vulkan_sub_descriptors_bind (GskVulkanDescriptors *desc,
|
||||
{
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
|
||||
if (GSK_IS_VULKAN_SUB_DESCRIPTORS (previous))
|
||||
if (GSK_GPU_DESCRIPTORS (previous)->desc_class == (GskGpuDescriptorsClass *) &GSK_VULKAN_SUB_DESCRIPTORS_CLASS)
|
||||
previous = GSK_VULKAN_SUB_DESCRIPTORS (previous)->parent;
|
||||
|
||||
if (self->parent == previous)
|
||||
@@ -62,45 +87,24 @@ gsk_vulkan_sub_descriptors_add_buffer (GskGpuDescriptors *desc,
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_finalize (GObject *object)
|
||||
gsk_vulkan_sub_descriptors_finalize (GskGpuDescriptors *desc)
|
||||
{
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (object);
|
||||
GskVulkanSubDescriptors *self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
|
||||
g_object_unref (self->parent);
|
||||
|
||||
G_OBJECT_CLASS (gsk_vulkan_sub_descriptors_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_class_init (GskVulkanSubDescriptorsClass *klass)
|
||||
{
|
||||
GskVulkanDescriptorsClass *vulkan_descriptors_class = GSK_VULKAN_DESCRIPTORS_CLASS (klass);
|
||||
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = gsk_vulkan_sub_descriptors_finalize;
|
||||
|
||||
descriptors_class->add_image = gsk_vulkan_sub_descriptors_add_image;
|
||||
descriptors_class->add_buffer = gsk_vulkan_sub_descriptors_add_buffer;
|
||||
|
||||
vulkan_descriptors_class->get_pipeline_layout = gsk_vulkan_sub_descriptors_get_pipeline_layout;
|
||||
vulkan_descriptors_class->bind = gsk_vulkan_sub_descriptors_bind;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_vulkan_sub_descriptors_init (GskVulkanSubDescriptors *self)
|
||||
{
|
||||
gsk_gpu_descriptors_unref (GSK_GPU_DESCRIPTORS (self->parent));
|
||||
}
|
||||
|
||||
GskVulkanSubDescriptors *
|
||||
gsk_vulkan_sub_descriptors_new (GskVulkanDescriptors *parent)
|
||||
{
|
||||
GskVulkanSubDescriptors *self;
|
||||
GskVulkanDescriptors *desc;
|
||||
|
||||
self = g_object_new (GSK_TYPE_VULKAN_SUB_DESCRIPTORS, NULL);
|
||||
desc = gsk_vulkan_descriptors_new (&GSK_VULKAN_SUB_DESCRIPTORS_CLASS,
|
||||
sizeof (GskVulkanSubDescriptors));
|
||||
|
||||
self->parent = g_object_ref (parent);
|
||||
self = GSK_VULKAN_SUB_DESCRIPTORS (desc);
|
||||
self->parent = GSK_VULKAN_DESCRIPTORS (gsk_gpu_descriptors_ref (GSK_GPU_DESCRIPTORS (parent)));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_VULKAN_SUB_DESCRIPTORS (gsk_vulkan_sub_descriptors_get_type ())
|
||||
typedef struct _GskVulkanSubDescriptors GskVulkanSubDescriptors;
|
||||
|
||||
#define GSK_VULKAN_SUB_DESCRIPTORS(d) ((GskVulkanSubDescriptors *) (d))
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GskVulkanSubDescriptors, gsk_vulkan_sub_descriptors, GSK, VULKAN_SUB_DESCRIPTORS, GskVulkanDescriptors)
|
||||
|
||||
GskVulkanSubDescriptors * gsk_vulkan_sub_descriptors_new (GskVulkanDescriptors *parent);
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
static inline void G_GNUC_PURE
|
||||
gsk_point_interpolate (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2,
|
||||
float t,
|
||||
graphene_point_t *p)
|
||||
{
|
||||
p->x = p1->x * (1 - t) + p2->x * t;
|
||||
p->Y = p1->y * (1 - t) + p2->y * t;
|
||||
}
|
||||
|
||||
static inline float G_GNUC_PURE
|
||||
gsk_point_distance (const graphene_point_t *p1,
|
||||
const graphene_point_t *p2)
|
||||
{
|
||||
return sqrtf ((p1->x - p2->x)*(p1->x - p2->x) + (p1->y - p2->y)*(p1->y - p2->y));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -159,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -630,16 +632,53 @@ 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)
|
||||
{
|
||||
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;
|
||||
|
||||
+34
-10
@@ -31,6 +31,7 @@
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gskstrokeprivate.h"
|
||||
#include "gsktransformprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include "gdk/gdkmemoryformatprivate.h"
|
||||
#include "gdk/gdkprivate.h"
|
||||
@@ -234,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;
|
||||
}
|
||||
@@ -420,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);
|
||||
|
||||
@@ -473,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);
|
||||
|
||||
@@ -765,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;
|
||||
@@ -834,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;
|
||||
@@ -1227,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;
|
||||
@@ -1872,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));
|
||||
|
||||
@@ -2089,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));
|
||||
@@ -3077,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;
|
||||
}
|
||||
@@ -3464,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;
|
||||
}
|
||||
@@ -4279,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);
|
||||
|
||||
@@ -4431,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);
|
||||
|
||||
@@ -5775,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
|
||||
@@ -5801,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)
|
||||
@@ -5839,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;
|
||||
}
|
||||
@@ -6820,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);
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
+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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,91 +23,6 @@
|
||||
#include "gtktextviewprivate.h"
|
||||
#include "gtkpangoprivate.h"
|
||||
|
||||
void
|
||||
gtk_text_view_add_default_attributes (GtkTextView *view,
|
||||
GVariantBuilder *builder)
|
||||
{
|
||||
GtkTextAttributes *text_attrs;
|
||||
PangoFontDescription *font;
|
||||
char *value;
|
||||
|
||||
text_attrs = gtk_text_view_get_default_attributes (view);
|
||||
|
||||
font = text_attrs->font;
|
||||
|
||||
if (font)
|
||||
gtk_pango_get_font_attributes (font, builder);
|
||||
|
||||
g_variant_builder_add (builder, "{ss}", "justification",
|
||||
gtk_justification_to_string (text_attrs->justification));
|
||||
g_variant_builder_add (builder, "{ss}", "direction",
|
||||
gtk_text_direction_to_string (text_attrs->direction));
|
||||
g_variant_builder_add (builder, "{ss}", "wrap-mode",
|
||||
gtk_wrap_mode_to_string (text_attrs->wrap_mode));
|
||||
g_variant_builder_add (builder, "{ss}", "editable",
|
||||
text_attrs->editable ? "true" : "false");
|
||||
g_variant_builder_add (builder, "{ss}", "invisible",
|
||||
text_attrs->invisible ? "true" : "false");
|
||||
g_variant_builder_add (builder, "{ss}", "bg-full-height",
|
||||
text_attrs->bg_full_height ? "true" : "false");
|
||||
g_variant_builder_add (builder, "{ss}", "strikethrough",
|
||||
text_attrs->appearance.strikethrough ? "true" : "false");
|
||||
g_variant_builder_add (builder, "{ss}", "underline",
|
||||
pango_underline_to_string (text_attrs->appearance.underline));
|
||||
|
||||
value = g_strdup_printf ("%u,%u,%u",
|
||||
(guint)(text_attrs->appearance.bg_rgba->red * 65535),
|
||||
(guint)(text_attrs->appearance.bg_rgba->green * 65535),
|
||||
(guint)(text_attrs->appearance.bg_rgba->blue * 65535));
|
||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%u,%u,%u",
|
||||
(guint)(text_attrs->appearance.fg_rgba->red * 65535),
|
||||
(guint)(text_attrs->appearance.fg_rgba->green * 65535),
|
||||
(guint)(text_attrs->appearance.fg_rgba->blue * 65535));
|
||||
g_variant_builder_add (builder, "{ss}", "bg-color", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%g", text_attrs->font_scale);
|
||||
g_variant_builder_add (builder, "{ss}", "scale", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup ((gchar *)(text_attrs->language));
|
||||
g_variant_builder_add (builder, "{ss}", "language", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->appearance.rise);
|
||||
g_variant_builder_add (builder, "{ss}", "rise", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->pixels_inside_wrap);
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-inside-wrap", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->pixels_below_lines);
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-below-lines", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->pixels_above_lines);
|
||||
g_variant_builder_add (builder, "{ss}", "pixels-above-lines", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->indent);
|
||||
g_variant_builder_add (builder, "{ss}", "indent", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->left_margin);
|
||||
g_variant_builder_add (builder, "{ss}", "left-margin", value);
|
||||
g_free (value);
|
||||
|
||||
value = g_strdup_printf ("%i", text_attrs->right_margin);
|
||||
g_variant_builder_add (builder, "{ss}", "right-margin", value);
|
||||
g_free (value);
|
||||
|
||||
gtk_text_attributes_unref (text_attrs);
|
||||
}
|
||||
|
||||
char *
|
||||
gtk_text_view_get_text_before (GtkTextView *view,
|
||||
int offset,
|
||||
|
||||
@@ -23,9 +23,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_text_view_add_default_attributes (GtkTextView *view,
|
||||
GVariantBuilder *builder);
|
||||
|
||||
char *gtk_text_view_get_text_before (GtkTextView *view,
|
||||
int offset,
|
||||
AtspiTextBoundaryType boundary_type,
|
||||
|
||||
@@ -291,6 +291,9 @@ gtk_accessible_role_to_atspi_role (GtkAccessibleRole role)
|
||||
case GTK_ACCESSIBLE_ROLE_TOGGLE_BUTTON:
|
||||
return ATSPI_ROLE_TOGGLE_BUTTON;
|
||||
|
||||
case GTK_ACCESSIBLE_ROLE_TERMINAL:
|
||||
return ATSPI_ROLE_TERMINAL;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -370,6 +370,7 @@ gtk_cell_renderer_pixbuf_set_property (GObject *object,
|
||||
else
|
||||
texture = NULL;
|
||||
take_image_definition (cellpixbuf, gtk_image_definition_new_paintable (GDK_PAINTABLE (texture)));
|
||||
g_clear_object (&texture);
|
||||
break;
|
||||
case PROP_PIXBUF_EXPANDER_OPEN:
|
||||
g_clear_object (&priv->pixbuf_expander_open);
|
||||
|
||||
@@ -852,7 +852,8 @@ gtk_tree_path_prepend_index (GtkTreePath *path,
|
||||
int *indices;
|
||||
path->alloc = MAX (path->alloc * 2, 1);
|
||||
indices = g_new (int, path->alloc);
|
||||
memcpy (indices + 1, path->indices, path->depth * sizeof (int));
|
||||
if (path->depth > 0)
|
||||
memcpy (indices + 1, path->indices, path->depth * sizeof (int));
|
||||
g_free (path->indices);
|
||||
path->indices = indices;
|
||||
}
|
||||
@@ -972,7 +973,8 @@ gtk_tree_path_copy (const GtkTreePath *path)
|
||||
retval->depth = path->depth;
|
||||
retval->alloc = retval->depth;
|
||||
retval->indices = g_new (int, path->alloc);
|
||||
memcpy (retval->indices, path->indices, path->depth * sizeof (int));
|
||||
if (path->depth > 0)
|
||||
memcpy (retval->indices, path->indices, path->depth * sizeof (int));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
+115
-54
@@ -22,13 +22,20 @@
|
||||
* language-specific data.raw.json as input
|
||||
*/
|
||||
|
||||
/* The format of the generated data is: a(ausasu).
|
||||
/* The format of the generated data is: a(aussasasu).
|
||||
* Each member of the array has the following fields:
|
||||
* au - sequence of unicode codepoints. If the
|
||||
* sequence contains a 0, it marks the point
|
||||
* where skin tone modifiers should be inserted
|
||||
* s - name, e.g. "man worker"
|
||||
* as - keywords, e.g. "man", "worker"
|
||||
* au - sequence of unicode codepoints, including the emoji presentation
|
||||
* selector (FE0F) where necessary. skin tone variations are represented
|
||||
* with either the first tone code point (1F3FB) or 0. the choice indicates
|
||||
* the handling of the generic sequence (i.e., no tone), which may have a
|
||||
* default text presentation and thus require the emoji presentation
|
||||
* selector (unlike sequences with a tone, which are always presented as
|
||||
* emojis). 0 indicates the text case, that is, replace this code point
|
||||
* with FE0F, while 1F3FB indicates this code point should be omitted.
|
||||
* s - name in english, e.g. "man worker"
|
||||
* s - name in locale
|
||||
* as - keywords in english, e.g. "man", "worker"
|
||||
* as - keywords in locale
|
||||
* u - the group that this item belongs to:
|
||||
* 0: smileys-emotion
|
||||
* 1: people-body
|
||||
@@ -46,7 +53,8 @@
|
||||
|
||||
gboolean
|
||||
parse_code (GVariantBuilder *b,
|
||||
const char *code)
|
||||
const char *code,
|
||||
gboolean needs_presentation_selector)
|
||||
{
|
||||
g_auto(GStrv) strv = NULL;
|
||||
int j;
|
||||
@@ -64,11 +72,31 @@ parse_code (GVariantBuilder *b,
|
||||
return FALSE;
|
||||
}
|
||||
if (0x1f3fb <= u && u <= 0x1f3ff)
|
||||
g_variant_builder_add (b, "u", 0);
|
||||
{
|
||||
if (needs_presentation_selector)
|
||||
{
|
||||
if (strv[j+1])
|
||||
{
|
||||
g_error ("unexpected inner skin tone in default-text generic sequence: %s\n", code);
|
||||
return FALSE;
|
||||
}
|
||||
g_variant_builder_add (b, "u", 0);
|
||||
needs_presentation_selector = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_variant_builder_add (b, "u", 0x1f3fb);
|
||||
}
|
||||
}
|
||||
else
|
||||
g_variant_builder_add (b, "u", u);
|
||||
{
|
||||
g_variant_builder_add (b, "u", u);
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_presentation_selector)
|
||||
g_variant_builder_add (b, "u", 0xfe0f);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -77,90 +105,123 @@ main (int argc, char *argv[])
|
||||
{
|
||||
JsonParser *parser;
|
||||
JsonNode *root;
|
||||
JsonParser *parser_en;
|
||||
JsonNode *root_en;
|
||||
JsonObject *ro;
|
||||
JsonArray *array;
|
||||
JsonArray *array_en;
|
||||
JsonNode *node;
|
||||
const char *unicode;
|
||||
JsonObjectIter iter;
|
||||
GError *error = NULL;
|
||||
guint length, i;
|
||||
guint length, length_en, i;
|
||||
GVariantBuilder builder;
|
||||
GVariant *v;
|
||||
GString *s;
|
||||
GHashTable *names;
|
||||
GString *name_key;
|
||||
|
||||
if (argc != 3)
|
||||
if (argc != 4) //0 -> compiled file, 1 -> en/data.raw.json, 2 -> de/data.raw.json, 3 -> de.data
|
||||
{
|
||||
g_print ("Usage: emoji-convert INPUT OUTPUT\n");
|
||||
g_print ("Usage: emoji-convert INPUT1 INPUT2 OUTPUT\nINPUT1 should be raw json data for English\nINPUT2 should be raw json data for the locale\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
parser = json_parser_new ();
|
||||
parser_en = json_parser_new ();
|
||||
|
||||
if (!json_parser_load_from_file (parser, argv[1], &error))
|
||||
if (!json_parser_load_from_file (parser_en, argv[1], &error))
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
return 1;
|
||||
}
|
||||
if (!json_parser_load_from_file (parser, argv[2], &error))
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
root = json_parser_get_root (parser);
|
||||
array = json_node_get_array (root);
|
||||
length = json_array_get_length (array);
|
||||
root_en = json_parser_get_root (parser_en);
|
||||
array_en = json_node_get_array (root_en);
|
||||
length_en = json_array_get_length (array_en);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ausasu)"));
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(aussasasu)"));
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
JsonObject *obj = json_array_get_object_element (array, i);
|
||||
GVariantBuilder b1;
|
||||
GVariantBuilder b2;
|
||||
guint group;
|
||||
const char *name;
|
||||
char *code;
|
||||
{
|
||||
JsonObject *obj = json_array_get_object_element (array, i);
|
||||
JsonObject *obj_en = json_array_get_object_element (array_en, i);
|
||||
GVariantBuilder b1;
|
||||
GVariantBuilder b2;
|
||||
GVariantBuilder b3;
|
||||
guint group;
|
||||
const char *name;
|
||||
const char *name_en;
|
||||
char *code;
|
||||
const char *text;
|
||||
gboolean needs_presentation_selector;
|
||||
|
||||
if (!json_object_has_member (obj, "group"))
|
||||
continue;
|
||||
if (!json_object_has_member (obj, "group"))
|
||||
continue;
|
||||
if (!json_object_has_member (obj_en, "group"))
|
||||
continue;
|
||||
|
||||
group = json_object_get_int_member (obj, "group");
|
||||
name = json_object_get_string_member (obj, "label");
|
||||
group = json_object_get_int_member (obj, "group");
|
||||
name = json_object_get_string_member (obj, "label");
|
||||
name_en = json_object_get_string_member (obj_en, "label");
|
||||
|
||||
if (json_object_has_member (obj, "skins"))
|
||||
if (g_str_has_suffix (name_en, "skin tone"))
|
||||
continue;
|
||||
|
||||
if (json_object_has_member (obj, "skins") && json_object_has_member (obj_en, "skins"))
|
||||
{
|
||||
JsonArray *a2 = json_object_get_array_member (obj, "skins");
|
||||
JsonNode *n2 = json_array_get_element (a2, 0);
|
||||
JsonObject *o2 = json_node_get_object (n2);
|
||||
code = g_strdup (json_object_get_string_member (o2, "hexcode"));
|
||||
}
|
||||
else
|
||||
{
|
||||
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
|
||||
}
|
||||
|
||||
text = json_object_get_string_member (obj, "text");
|
||||
needs_presentation_selector = *text != '\0' && json_object_get_int_member (obj, "type") == 0;
|
||||
|
||||
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
|
||||
if (!parse_code (&b1, code, needs_presentation_selector))
|
||||
return 1;
|
||||
|
||||
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
|
||||
if (json_object_has_member (obj_en, "tags"))
|
||||
{
|
||||
JsonArray *tags_en = json_object_get_array_member (obj_en, "tags");
|
||||
for (int j = 0; j < json_array_get_length (tags_en); j++)
|
||||
{
|
||||
JsonArray *a2 = json_object_get_array_member (obj, "skins");
|
||||
JsonNode *n2 = json_array_get_element (a2, 0);
|
||||
JsonObject *o2 = json_node_get_object (n2);
|
||||
code = g_strdup (json_object_get_string_member (o2, "hexcode"));
|
||||
g_variant_builder_add (&b2, "s", json_array_get_string_element (tags_en, j));
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
g_variant_builder_init (&b3, G_VARIANT_TYPE ("as"));
|
||||
if (json_object_has_member (obj, "tags"))
|
||||
{
|
||||
JsonArray *tags = json_object_get_array_member (obj, "tags");
|
||||
for (int j = 0; j < json_array_get_length (tags); j++)
|
||||
{
|
||||
code = g_strdup (json_object_get_string_member (obj, "hexcode"));
|
||||
g_variant_builder_add (&b3, "s", json_array_get_string_element (tags, j));
|
||||
}
|
||||
|
||||
g_variant_builder_init (&b1, G_VARIANT_TYPE ("au"));
|
||||
|
||||
if (!parse_code (&b1, code))
|
||||
return 1;
|
||||
|
||||
g_variant_builder_init (&b2, G_VARIANT_TYPE ("as"));
|
||||
if (json_object_has_member (obj, "tags"))
|
||||
{
|
||||
JsonArray *tags = json_object_get_array_member (obj, "tags");
|
||||
for (int j = 0; j < json_array_get_length (tags); j++)
|
||||
g_variant_builder_add (&b2, "s", json_array_get_string_element (tags, j));
|
||||
}
|
||||
|
||||
g_variant_builder_add (&builder, "(ausasu)", &b1, name, &b2, group);
|
||||
}
|
||||
|
||||
}
|
||||
g_variant_builder_add (&builder, "(aussasasu)", &b1, name_en, name, &b2, &b3, group);
|
||||
}
|
||||
v = g_variant_builder_end (&builder);
|
||||
if (g_str_has_suffix (argv[2], ".json"))
|
||||
if (g_str_has_suffix (argv[3], ".json"))
|
||||
{
|
||||
JsonNode *node;
|
||||
char *out;
|
||||
|
||||
node = json_gvariant_serialize (v);
|
||||
out = json_to_string (node, TRUE);
|
||||
if (!g_file_set_contents (argv[2], out, -1, &error))
|
||||
if (!g_file_set_contents (argv[3], out, -1, &error))
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
return 1;
|
||||
@@ -171,7 +232,7 @@ main (int argc, char *argv[])
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = g_variant_get_data_as_bytes (v);
|
||||
if (!g_file_set_contents (argv[2], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
|
||||
if (!g_file_set_contents (argv[3], g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error))
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
return 1;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user