Compare commits
561 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ff7c86b65 | |||
| 79a0f183ec | |||
| e8c8be8e37 | |||
| bfc80c32ea | |||
| 5f48764ac8 | |||
| cc6fcbfc09 | |||
| ea7185bdb1 | |||
| 429dfcf483 | |||
| be3f352b59 | |||
| 5b8896f1db | |||
| 4e27de7df9 | |||
| 2712f536c2 | |||
| a1f7073ff5 | |||
| 9770872d12 | |||
| de24b4f91b | |||
| 650fd9c291 | |||
| b509809f34 | |||
| 60ff231fac | |||
| 958005317b | |||
| 15c36aaa1e | |||
| 482b73c376 | |||
| 4a8bf6e13d | |||
| 3e2e6633b0 | |||
| 4724f9907c | |||
| 26e84a7b8c | |||
| d5838f14f9 | |||
| 5c532104e4 | |||
| 2f42e1fb89 | |||
| b5200bd076 | |||
| aa5bd38137 | |||
| 0eba833595 | |||
| 1e0ea21297 | |||
| e91e75173d | |||
| 927fdb9a83 | |||
| 041f410838 | |||
| c71c8919fe | |||
| 3f28399f7d | |||
| 3c15fa96bc | |||
| 0a0a059397 | |||
| 18e83fe16d | |||
| 90d7ed5dd1 | |||
| 3c6e7569ff | |||
| 4e2ec2d68d | |||
| 1af72eac21 | |||
| 640273a0e2 | |||
| a14a0c6315 | |||
| 38481680e1 | |||
| 12a540c284 | |||
| 289bf078bf | |||
| 58ab9ddc40 | |||
| c78036fc51 | |||
| 120f2768e6 | |||
| 592b33cb48 | |||
| 7a9bc1f1d8 | |||
| 9cc6f3ee29 | |||
| 9efaa0b51d | |||
| f0967fa5e4 | |||
| f8529983f9 | |||
| 919c08d4fd | |||
| e9b06b6346 | |||
| 949c783187 | |||
| 814a4a781a | |||
| 676f875bf6 | |||
| 140c5c5333 | |||
| cebf2b2009 | |||
| 86b437a1b6 | |||
| 773ae0cd0f | |||
| 564793d5b5 | |||
| 9142aa0f51 | |||
| af9a578d68 | |||
| ecb072fdd0 | |||
| ef053ebb4a | |||
| 8d18d93742 | |||
| 10fcdd88e3 | |||
| 5d9509c51b | |||
| c9cac5fbc3 | |||
| aa9054a5f1 | |||
| 9ebf3fac73 | |||
| 569294070b | |||
| be35c46ce9 | |||
| dbbcb13721 | |||
| edeaf9c040 | |||
| 61f709811c | |||
| f7c4375509 | |||
| 52fb900ced | |||
| 031944ad30 | |||
| bf8b974f68 | |||
| 6ad2a049e7 | |||
| 3d85d53e5d | |||
| 094a346539 | |||
| 162814f969 | |||
| e39b5c99f1 | |||
| 8883243aaa | |||
| 89511eecf1 | |||
| 2c304ca80d | |||
| bf4102e664 | |||
| b86153cee3 | |||
| 7985d277b3 | |||
| 752da5c2a5 | |||
| de4b8d547b | |||
| 1048ad1a01 | |||
| 4d11158d97 | |||
| 293b81cad2 | |||
| 65c38111f9 | |||
| ec8db379a6 | |||
| 1484b4ae9f | |||
| 4cecbf1654 | |||
| 234ba90e2b | |||
| bdd2244f75 | |||
| cd7ec8ac92 | |||
| cc5edbbbb2 | |||
| 94d9e34dd3 | |||
| 3dbf5038fa | |||
| 456a2f3bcf | |||
| 8e1fa52d14 | |||
| cbf2feb633 | |||
| afe8ee501c | |||
| 4644dab081 | |||
| b37a69d76c | |||
| 51bc6ce2e4 | |||
| 988ebc2248 | |||
| 9f31e95420 | |||
| 3a076e26f7 | |||
| e3e85fc6f3 | |||
| ad3a35b4c5 | |||
| 454caa3eec | |||
| 0ffe67ffed | |||
| 8eb46bbfb2 | |||
| d8e8b3c235 | |||
| 79f273348d | |||
| fc99081658 | |||
| aba14e6a43 | |||
| 8ebcef97ff | |||
| 00956a3770 | |||
| 11f3b7730c | |||
| f63e6394ac | |||
| bbca4c38df | |||
| 28f5d26719 | |||
| bf2620f041 | |||
| 870b82b541 | |||
| 1635d9fb78 | |||
| 20fb155e8c | |||
| da59c77ae2 | |||
| 0d0bdaa02e | |||
| 04cf5044da | |||
| b005cd0bbd | |||
| f5379d2047 | |||
| 98c247ec29 | |||
| 38e2f9138d | |||
| 3cc7d9b8c0 | |||
| 1ac9400712 | |||
| 10d5705b70 | |||
| 2d0d579735 | |||
| ac0f524722 | |||
| 2cd0e5f60b | |||
| d83502d054 | |||
| 9e539a7f59 | |||
| c60247f51f | |||
| 06321511ad | |||
| 2e7923cad0 | |||
| 3c66c27caa | |||
| 7f4bd6917e | |||
| b89376da55 | |||
| a1dd6521e8 | |||
| 0088f840fe | |||
| 1b698c896e | |||
| 04000f28e7 | |||
| 976a05f6eb | |||
| b15902bf44 | |||
| 5ac7529771 | |||
| bbf68c0d9d | |||
| eeb3dd3511 | |||
| 7b0ce11e46 | |||
| 8ef1d6a49c | |||
| 7db60f958d | |||
| 30043e072e | |||
| 5ee7606779 | |||
| 25409c5a5a | |||
| 51122dd287 | |||
| ec9159f983 | |||
| f3d77d1c21 | |||
| 1258fcaaf4 | |||
| 00fd60aaa8 | |||
| c7a7d0582a | |||
| b6e7acfb90 | |||
| 40eae298d5 | |||
| 09a9131a10 | |||
| c93c9f5c2a | |||
| 7f08adc23e | |||
| f41012080f | |||
| 786e9d351c | |||
| 3d2cf97fbf | |||
| 1fe6fb6739 | |||
| 6710eb5eb3 | |||
| 80b1d55683 | |||
| 1cebc4316b | |||
| 20895d6f3f | |||
| 65a4118d50 | |||
| 4857829aaa | |||
| 2ea4574caf | |||
| 102b74f9eb | |||
| 8a0d4dfa94 | |||
| b4e645862a | |||
| ea48506a32 | |||
| 23f0a29260 | |||
| 9249717cf4 | |||
| 4196dfc374 | |||
| 23af707b41 | |||
| 421088c3a0 | |||
| 749f1a7c00 | |||
| 344f9fcf05 | |||
| 4c971cd4da | |||
| 43d553dcfb | |||
| 66264f9a3d | |||
| 269f369541 | |||
| 1973019962 | |||
| fe515c4c1c | |||
| 14f0a0addb | |||
| 64a2d0221c | |||
| 0ef91c3ba8 | |||
| 2adcb7be71 | |||
| a332f2402a | |||
| 131a61c51b | |||
| 39d5dd89c5 | |||
| 341efe9a40 | |||
| 5ed6f89b4a | |||
| 4d609149d2 | |||
| 0d790505aa | |||
| a486536925 | |||
| e808fb424a | |||
| 6c54abeca7 | |||
| d24b8a094c | |||
| c46391420f | |||
| 68df7527f7 | |||
| 5a3c3d8210 | |||
| 95ceb49770 | |||
| 0bde58ffd7 | |||
| ccd9827b63 | |||
| db189cfb9f | |||
| 7527f181d5 | |||
| c05b418512 | |||
| e97d996fe4 | |||
| 0537b167ca | |||
| 40446201ff | |||
| fff6b35821 | |||
| 75f2d7583f | |||
| 1fd8d3b487 | |||
| a1216599ff | |||
| 8fff0e0fdf | |||
| 439727a84a | |||
| 3a18a6dddf | |||
| d7050c63ae | |||
| b7c88ec87d | |||
| 5985b62f60 | |||
| e7c29b989c | |||
| 2100e427d9 | |||
| 2550d6dc63 | |||
| ca72fae884 | |||
| 4fc1af14a7 | |||
| 1a30ec6da6 | |||
| e77d519482 | |||
| 59806eee38 | |||
| 5968b10b0b | |||
| e6f0103940 | |||
| cbaad3dbd9 | |||
| ee43a6a603 | |||
| 1ac1147ecb | |||
| 1edbc1f1f9 | |||
| 146b4c93ba | |||
| 94f90f457a | |||
| 6b7d56ac49 | |||
| 1635d7be8c | |||
| 992cd088cf | |||
| f6010b2a59 | |||
| 9222a5fd6d | |||
| 6f7fb6ba5a | |||
| a57a144f8e | |||
| 7b47e3225b | |||
| 6aa893e091 | |||
| 5aa03bcb0d | |||
| d7060025e0 | |||
| 00883016af | |||
| f0d8b614d0 | |||
| ddbd574643 | |||
| 5ea3777599 | |||
| a3949763f2 | |||
| 1b961a9ae2 | |||
| d9f6b268d3 | |||
| 934b91f65f | |||
| c3050231d1 | |||
| 4d7a01562e | |||
| 650eed7f72 | |||
| ec8614e8e4 | |||
| cb41b96a9e | |||
| 872b46a527 | |||
| b1c8613dbe | |||
| de6cd4f0d2 | |||
| aec2fb939f | |||
| 69293db804 | |||
| 61a7ebf980 | |||
| f14762b026 | |||
| 187d261400 | |||
| e905f7ff7c | |||
| aefc630d29 | |||
| a5e929ce36 | |||
| 1641d365f5 | |||
| 07d9cd8efe | |||
| 29868b2a05 | |||
| 691b6b88ea | |||
| 2ee1a00177 | |||
| 144cf2d040 | |||
| e1a308d151 | |||
| bbfaacb598 | |||
| d89ff71819 | |||
| 141c725489 | |||
| bbc3aa4ff9 | |||
| f7856f29fd | |||
| 7b69c58deb | |||
| f60d245e32 | |||
| f04e5bd590 | |||
| 90c428b4a7 | |||
| 97b5fad131 | |||
| 285a91715d | |||
| 880468f5a3 | |||
| 6ddbb2a402 | |||
| 7eab565225 | |||
| b34101d45d | |||
| 6c21a7be0b | |||
| a6f2bcb220 | |||
| ef0db01d5c | |||
| ef33ec639c | |||
| 27ca4434e2 | |||
| 9861c7d25c | |||
| 13ef82fc4d | |||
| b33ca43e14 | |||
| 39e07a8d56 | |||
| 5286743cbe | |||
| 58bb998ef0 | |||
| a56b2900dd | |||
| ff34124394 | |||
| 03b60a2d5e | |||
| d939d04885 | |||
| 73fb28a058 | |||
| 65eaf8e8c4 | |||
| beeedb5141 | |||
| 1d40750a60 | |||
| 96baf9769a | |||
| 5044031b53 | |||
| 9f7119ee58 | |||
| c514c41d0e | |||
| 45848c5298 | |||
| 8c61038b9f | |||
| b5cb2f7e41 | |||
| 8af0d4b51f | |||
| 378ad75d48 | |||
| 01d19e2aa4 | |||
| 64e16ecaf1 | |||
| 6a047e53a8 | |||
| 31a7bc70c9 | |||
| 874cae1dab | |||
| 7a3dd41dba | |||
| 149962670a | |||
| 849e3c8b4b | |||
| c9807f5afe | |||
| 9a9899597c | |||
| fecb7af66e | |||
| f5efb15cba | |||
| d7d4fed0f3 | |||
| c2c2635763 | |||
| fb33e83c96 | |||
| 291ad17a22 | |||
| 0f052d46b2 | |||
| 506423cf23 | |||
| 946a496a2e | |||
| d20526570b | |||
| 8312b9d9ca | |||
| 992f092968 | |||
| 60835227a1 | |||
| 2b6b35d91f | |||
| 897164c66c | |||
| 441d944c08 | |||
| 2b8ad6c4b5 | |||
| 99b2da4c47 | |||
| 8243b5493b | |||
| d5ef906cff | |||
| a720d8bc79 | |||
| 57691eacc5 | |||
| 526e24f5b1 | |||
| 2a79152762 | |||
| f03acaf7ab | |||
| 4e7ce9edcf | |||
| ff72619333 | |||
| 59692599ea | |||
| 4761641098 | |||
| afaa275dc8 | |||
| c736deb83b | |||
| e930a20522 | |||
| 137f32f9ef | |||
| 195b98f19a | |||
| 87e0a28482 | |||
| 3ca3d7efef | |||
| d8d8322912 | |||
| 1ea1a70fd2 | |||
| 1d5bc2838b | |||
| 45ec3fc389 | |||
| 3a5eee7dbe | |||
| 0cda6f42b8 | |||
| 0d99ef7cee | |||
| 7583810c90 | |||
| 1341bc0b19 | |||
| fd073deea9 | |||
| 5652ab0a61 | |||
| 2ff23b08be | |||
| 0336af06f1 | |||
| 2af9f1ad62 | |||
| e657da6658 | |||
| fd00aa98ea | |||
| de8a8d7bde | |||
| eb6fbf907f | |||
| 4035f86b6d | |||
| 855b44f2ed | |||
| f2e0097cac | |||
| 7c9bc7a204 | |||
| f4f104c9f9 | |||
| 28a6f0df05 | |||
| 0eab4deab0 | |||
| 6e8e467cc9 | |||
| ca9801f5fb | |||
| 6b6fc1e5d8 | |||
| e3641d0568 | |||
| a5b88a53c2 | |||
| e4d0114e0d | |||
| f974c5343e | |||
| bc39da0619 | |||
| 1995b7f34b | |||
| 36eb7c40d0 | |||
| 56af472cfc | |||
| d1fcfa58b9 | |||
| cf23324749 | |||
| b79c26b39e | |||
| 532b8c71a8 | |||
| 7c5b8911d8 | |||
| e141d61593 | |||
| 9595d440cf | |||
| 1063924bd0 | |||
| 42fedfc870 | |||
| 24836c0351 | |||
| 21b6c8b5d8 | |||
| 41fb6f6a8e | |||
| 071ea6b559 | |||
| 397a71ca8b | |||
| 40c10f83e2 | |||
| fb31581bb4 | |||
| 536a67ec96 | |||
| 53fe751371 | |||
| 7901ab857b | |||
| 8f585f7a53 | |||
| 874b19b27e | |||
| fe7b11b4e9 | |||
| 601dfeeff9 | |||
| cf623ce774 | |||
| 36b49950e8 | |||
| 77feb51b9c | |||
| 710ef00dfe | |||
| 0c8124828f | |||
| 0605c3c167 | |||
| 93d795e7c0 | |||
| d55f938f7c | |||
| 45bb4dc80c | |||
| 53af35d256 | |||
| 51a6b29e01 | |||
| e3835476ba | |||
| 256b094b13 | |||
| 699adb0b10 | |||
| c91b5eaa41 | |||
| 7e1f20bf4c | |||
| f9fe640905 | |||
| 34ea99006f | |||
| 06cce81a97 | |||
| 4a1a7940d5 | |||
| 1108d00014 | |||
| 034672e84e | |||
| 00c885c93c | |||
| 114f0bd8d6 | |||
| 24c67efdfd | |||
| 6a3748146d | |||
| 92ec754737 | |||
| d11fbbc478 | |||
| f11f0da11c | |||
| ebdf2989f8 | |||
| bc35c5d494 | |||
| 70a3e5e8ce | |||
| 74ff61a937 | |||
| 280d7e57bd | |||
| 03f5a368ec | |||
| 0b15aba82a | |||
| d8fa9de93a | |||
| afabbc4957 | |||
| d978ba31d6 | |||
| 71efa96ef2 | |||
| e336fe2bf8 | |||
| d7f15c15e9 | |||
| fff570538c | |||
| 38166a67c7 | |||
| 01b94db73d | |||
| c804645382 | |||
| 384081ce0a | |||
| afccb86f7e | |||
| 0ba5631100 | |||
| c72589f0ee | |||
| f2e5775380 | |||
| a7164208d3 | |||
| 20f3d1608d | |||
| 9320148d71 | |||
| ad617a0e06 | |||
| 62af8365f6 | |||
| 29afe5a688 | |||
| 2d3885a44a | |||
| 75a297632e | |||
| 572649740e | |||
| b5938faa06 | |||
| a4baac7193 | |||
| bdde41e290 | |||
| d888402bf9 | |||
| 378bd9fab2 | |||
| 4ad5e77907 | |||
| 4fb70c5e4d | |||
| d5963ad109 | |||
| b5fe434fea | |||
| 224c2674ab | |||
| 878b34fae3 | |||
| 5fe433418d | |||
| 02ba9bc1da | |||
| 2336120010 | |||
| 0d54d73a51 | |||
| 6c09832b9b | |||
| 1758f88492 | |||
| 34ffdc6e3f | |||
| 108933b655 | |||
| 3344bcaf92 | |||
| f22ec063a1 | |||
| 0fcf01ddd5 | |||
| 1119a74ff0 | |||
| 18ea60e235 | |||
| d752828977 | |||
| 1034271d9a | |||
| f013d3b5d6 | |||
| 5f41d26abc | |||
| 7d5826ccf7 | |||
| 2c9f2325e2 | |||
| daded2bc86 | |||
| bc7619abaf | |||
| 459d6e1349 | |||
| 6e108d310a | |||
| cf20cfd31e | |||
| 6bd0dc3e78 | |||
| 4f0c920a8e | |||
| b0b793dd94 | |||
| efbb649eee | |||
| 90dfb5e138 | |||
| 0d2ea14ac1 |
@@ -24,7 +24,7 @@ variables:
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v25"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v27"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v25"
|
||||
|
||||
@@ -43,6 +43,7 @@ style-check-diff:
|
||||
- .gitlab-ci/run-style-check-diff.sh
|
||||
|
||||
.build-fedora-default:
|
||||
extends: .only-default
|
||||
image: $FEDORA_IMAGE
|
||||
artifacts:
|
||||
when: always
|
||||
@@ -121,6 +122,7 @@ installed-tests:
|
||||
|
||||
|
||||
.mingw-defaults:
|
||||
extends: .only-default
|
||||
stage: build
|
||||
tags:
|
||||
- win32-ps
|
||||
@@ -144,6 +146,31 @@ msys2-mingw64:
|
||||
MSYSTEM: "MINGW64"
|
||||
CHERE_INVOKING: "yes"
|
||||
|
||||
macos:
|
||||
extends: .only-default
|
||||
only:
|
||||
- branches@GNOME/gtk
|
||||
stage: build
|
||||
tags:
|
||||
- macos
|
||||
needs: []
|
||||
before_script:
|
||||
- bash .gitlab-ci/show-execution-environment.sh
|
||||
- pip3 install --user meson==0.56
|
||||
- pip3 install --user ninja
|
||||
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
|
||||
script:
|
||||
- meson -Dx11-backend=false
|
||||
-Dintrospection=disabled
|
||||
-Dcpp_std=c++11
|
||||
-Dpixman:tests=disabled
|
||||
_build
|
||||
- ninja -C _build
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
|
||||
.flatpak-defaults:
|
||||
image: $FLATPAK_IMAGE
|
||||
stage: flatpak
|
||||
|
||||
@@ -65,6 +65,7 @@ RUN dnf -y install \
|
||||
libxslt \
|
||||
mesa-dri-drivers \
|
||||
mesa-libEGL-devel \
|
||||
mesa-libGLES-devel \
|
||||
mesa-libwayland-egl-devel \
|
||||
ninja-build \
|
||||
pango-devel \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v25
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v27
|
||||
|
||||
# Enable sudo for wheel users
|
||||
RUN sed -i -e 's/# %wheel/%wheel/' -e '0,/%wheel/{s/%wheel/# %wheel/}' /etc/sudoers
|
||||
|
||||
@@ -8,7 +8,8 @@ builddir=$1
|
||||
backend=$2
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0
|
||||
export G_SLICE=always-malloc
|
||||
|
||||
case "${backend}" in
|
||||
x11)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eux -o pipefail
|
||||
|
||||
xcodebuild -version || :
|
||||
xcodebuild -showsdks || :
|
||||
|
||||
system_profiler SPSoftwareDataType || :
|
||||
@@ -1,4 +1,13 @@
|
||||
<!--
|
||||
Please, read the CONTRIBUTING.md guide on how to file a new issue.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
## Steps to reproduce
|
||||
<!--
|
||||
Please, explain the sequence of actions necessary to reproduce the
|
||||
bug
|
||||
-->
|
||||
|
||||
1. ...
|
||||
2. ...
|
||||
@@ -32,5 +41,8 @@
|
||||
## Additional information
|
||||
<!--
|
||||
- Screenshots or screen recordings are useful for visual errors
|
||||
- Attaching a screenshot or a video without explaining the current
|
||||
behavior and the actions necessary to reproduce the bug will lead
|
||||
to the bug being closed
|
||||
- Please report any warning or message printed on the terminal
|
||||
-->
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
<!--
|
||||
Please, read the CONTRIBUTING.md guide on how to file a new issue.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gtk/-/blob/master/CONTRIBUTING.md
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
<!--
|
||||
Please, explain the sequence of actions necessary to reproduce the
|
||||
crash
|
||||
-->
|
||||
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
import subprocess
|
||||
|
||||
stylesheets = [ 'gtk/theme/Adwaita/Adwaita.css',
|
||||
'gtk/theme/Adwaita/Adwaita-dark.css',
|
||||
'gtk/theme/HighContrast/HighContrast.css',
|
||||
'gtk/theme/HighContrast/HighContrast-dark.css' ]
|
||||
|
||||
sourceroot = os.environ.get('MESON_SOURCE_ROOT')
|
||||
distroot = os.environ.get('MESON_DIST_ROOT')
|
||||
|
||||
for stylesheet in stylesheets:
|
||||
stylesheet_path = PurePath(stylesheet)
|
||||
src = PurePath(sourceroot, stylesheet_path.with_suffix('.scss'))
|
||||
dst = PurePath(distroot, stylesheet_path)
|
||||
subprocess.call(['sassc', '-a', '-M', '-t', 'compact', src, dst])
|
||||
@@ -98,6 +98,9 @@ create_page1 (GtkWidget *assistant)
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_accessible_update_relation (GTK_ACCESSIBLE (entry),
|
||||
GTK_ACCESSIBLE_RELATION_LABELLED_BY, label, NULL,
|
||||
-1);
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
||||
gtk_widget_set_valign (entry, GTK_ALIGN_CENTER);
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
@@ -119,13 +119,12 @@ create_label (void)
|
||||
static GtkWidget *
|
||||
create_video (void)
|
||||
{
|
||||
GtkMediaStream *stream = gtk_media_file_new_for_resource ("/images/gtk-logo.webm");
|
||||
GtkWidget *w = gtk_picture_new_for_paintable (GDK_PAINTABLE (stream));
|
||||
GtkWidget *w = gtk_video_new ();
|
||||
|
||||
gtk_widget_set_size_request (w, 64, 64);
|
||||
gtk_media_stream_set_loop (stream, TRUE);
|
||||
gtk_media_stream_play (stream);
|
||||
g_object_unref (stream);
|
||||
gtk_video_set_loop (GTK_VIDEO (w), TRUE);
|
||||
gtk_video_set_autoplay (GTK_VIDEO (w), TRUE);
|
||||
gtk_video_set_resource (GTK_VIDEO (w), "/images/gtk-logo.webm");
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -787,6 +787,8 @@ gtk_gears_realize (GtkWidget *widget)
|
||||
glLinkProgram(program);
|
||||
glGetProgramInfoLog(program, sizeof msg, NULL, msg);
|
||||
g_debug ("program info: %s\n", msg);
|
||||
glDetachShader (program, v);
|
||||
glDetachShader (program, f);
|
||||
glDeleteShader (v);
|
||||
glDeleteShader (f);
|
||||
|
||||
|
||||
@@ -279,11 +279,31 @@ drag_prepare_texture (GtkDragSource *source,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
|
||||
GtkSnapshot *snapshot;
|
||||
double width, height;
|
||||
GskRenderNode *node;
|
||||
GskRenderer *renderer;
|
||||
GdkTexture *texture;
|
||||
GdkContentProvider *ret;
|
||||
|
||||
if (!GDK_IS_PAINTABLE (paintable))
|
||||
return NULL;
|
||||
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
|
||||
snapshot = gtk_snapshot_new ();
|
||||
width = gdk_paintable_get_intrinsic_width (paintable);
|
||||
height = gdk_paintable_get_intrinsic_height (paintable);
|
||||
gdk_paintable_snapshot (paintable, snapshot, width, height);
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
|
||||
renderer = gtk_native_get_renderer (gtk_widget_get_native (widget));
|
||||
texture = gsk_renderer_render_texture (renderer, node, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
|
||||
ret = gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, texture);
|
||||
|
||||
g_object_unref (texture);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GdkContentProvider *
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<property name="right-margin">20</property>
|
||||
<property name="top-margin">20</property>
|
||||
<property name="bottom-margin">20</property>
|
||||
<property name="monospace">1</property>
|
||||
<property name="buffer">
|
||||
<object class="GtkTextBuffer" id="buffer"/>
|
||||
</property>
|
||||
|
||||
@@ -700,6 +700,16 @@ out:
|
||||
g_free (source_dir);
|
||||
}
|
||||
|
||||
static void
|
||||
dark_mode_cb (GtkToggleButton *button,
|
||||
GParamSpec *pspec,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
g_object_set (gtk_widget_get_settings (GTK_WIDGET (self)),
|
||||
"gtk-application-prefer-dark-theme", gtk_toggle_button_get_active (button),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_finalize (GObject *object)
|
||||
{
|
||||
@@ -814,6 +824,7 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, export_image_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_save_clicked_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, testcase_name_entry_changed_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@@ -910,6 +921,26 @@ node_editor_window_init (NodeEditorWindow *self)
|
||||
self->text_buffer = gtk_text_buffer_new (self->tag_table);
|
||||
g_signal_connect (self->text_buffer, "changed", G_CALLBACK (text_changed), self);
|
||||
gtk_text_view_set_buffer (GTK_TEXT_VIEW (self->text_view), self->text_buffer);
|
||||
|
||||
/* Default */
|
||||
gtk_text_buffer_set_text (self->text_buffer,
|
||||
"shadow {\n"
|
||||
" child: texture {\n"
|
||||
" bounds: 0 0 128 128;\n"
|
||||
" texture: url(\"resource:///org/gtk/gtk4/node-editor/icons/apps/org.gtk.gtk4.NodeEditor.Devel.svg\");\n"
|
||||
" }\n"
|
||||
" shadows: rgba(0,0,0,0.5) 0 1 12;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"transform {\n"
|
||||
" child: text {\n"
|
||||
" color: rgb(46,52,54);\n"
|
||||
" font: \"Cantarell Bold 11\";\n"
|
||||
" glyphs: \"GTK Node Editor\";\n"
|
||||
" offset: 8 14.418;\n"
|
||||
" }\n"
|
||||
" transform: translate(0, 140);\n"
|
||||
"}", -1);
|
||||
}
|
||||
|
||||
NodeEditorWindow *
|
||||
|
||||
@@ -139,6 +139,15 @@
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="dark_bg_button">
|
||||
<property name="valign">center</property>
|
||||
<property name="has-frame">0</property>
|
||||
<property name="icon-name">display-brightness-symbolic</property>
|
||||
<property name="tooltip-text" translatable="yes">Use a dark background</property>
|
||||
<signal name="notify::active" handler="dark_mode_cb" swapped="0"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
||||
@@ -3298,7 +3298,6 @@ bad things might happen.</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkSizeGroup" id="basement-indicators"/>
|
||||
<menu id="new_style_menu_model">
|
||||
<section>
|
||||
<attribute name="display-hint">circular-buttons</attribute>
|
||||
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
@@ -146,6 +146,9 @@ images = [
|
||||
'images/nwse_resize_cursor.png',
|
||||
'images/zoom_in_cursor.png',
|
||||
'images/zoom_out_cursor.png',
|
||||
'images/popup-anchors.png',
|
||||
'images/popup-flip.png',
|
||||
'images/popup-slide.png',
|
||||
]
|
||||
|
||||
src_dir = [ gdkinc ]
|
||||
|
||||
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
@@ -18,9 +18,9 @@ Length
|
||||
Percentage
|
||||
: %, calc()
|
||||
Angle
|
||||
: deg | grad | turn, calc()
|
||||
: deg, grad, turn, calc()
|
||||
Time
|
||||
: s | ms, calc()
|
||||
: s, ms, calc()
|
||||
|
||||
Length values with the em or ex units are resolved using the font
|
||||
size value, unless they occur in setting the font-size itself, in
|
||||
@@ -32,7 +32,7 @@ not quite the same as the CSS definition of rem.
|
||||
The calc() notation adds considerable expressive power. There are limits
|
||||
on what types can be combined in such an expression (e.g. it does not make
|
||||
sense to add a number and a time). For the full details, see the
|
||||
[CSS3 VAlues and Units](https://www.w3.org/TR/css3-values/#calc-notation)
|
||||
[CSS3 Values and Units](https://www.w3.org/TR/css3-values/#calc-notation)
|
||||
spec.
|
||||
|
||||
A common pattern among shorthand properties (called 'four sides') is one
|
||||
@@ -80,6 +80,31 @@ and in some cases a number as arguments.
|
||||
|
||||
## Images
|
||||
|
||||
CSS allows to specify images in various forms, the most simple one being
|
||||
a url for an image file. Beyond that, images can be specified as
|
||||
|
||||
`linear-gradient(Angle, ColorStops)`
|
||||
`repeating-linear-gradient(Angle, ColorStops)`
|
||||
: creates a linear gradient.
|
||||
|
||||
`radial-gradient(Shape, ColorStops)`
|
||||
`repeating-radial-gradient(Shape, ColorStops)`
|
||||
: creates a radial gradient.
|
||||
|
||||
`conic-gradient(Angle, ColorStops)`
|
||||
: creates a conic gradient.
|
||||
|
||||
`cross-fade(Percentage Image,…)`
|
||||
: combines two or more images.
|
||||
|
||||
`image(Image,… Color)`
|
||||
: falls back to the first valid image, or to a solid color.
|
||||
|
||||
`filter(Image, Filters)`
|
||||
: applies filters to an image.
|
||||
|
||||
For more details, see [CSS Image Level 4](https://www.w3.org/TR/css-images-4/).
|
||||
|
||||
GTK extends the CSS syntax for images and also uses it for specifying icons.
|
||||
To load a themed icon, use
|
||||
|
||||
@@ -151,7 +176,7 @@ done with
|
||||
|caret-color|[CSS Basic User Interface Level 3](https://www.w3.org/TR/css3-ui/#caret-color) | CSS allows an auto value |
|
||||
|-gtk-secondary-caret-color|[Color](https://www.w3.org/TR/css-color-3/#valuea-def-color) | used for the secondary caret in bidirectional text |
|
||||
|letter-spacing| [CSS Text Level 3](https://www.w3.org/TR/css3-text/#letter-spacing) | |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | CSS allows overline |
|
||||
|text-decoration-line| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-line-property) | |
|
||||
|text-decoration-color| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-color-property) | |
|
||||
|text-decoration-style| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-decoration-style-property) | CSS allows dashed and dotted |
|
||||
|text-shadow| [CSS Text Decoration Level 3](https://www.w3.org/TR/css-text-decor-3/#text-shadow-property) | |
|
||||
@@ -159,11 +184,12 @@ done with
|
||||
|-gtk-icon-source| [Image](https://www.w3.org/TR/css-backgrounds-3/#typedef-image), `builtin` or `none` | used for builtin icons in buttons and expanders |
|
||||
|-gtk-icon-size| [Length](https://www.w3.org/TR/css3-values/#length-value) | size used for builtin icons in buttons and expanders |
|
||||
|-gtk-icon-style| `requested`, `regular` or `symbolic` | preferred style for application-loaded icons |
|
||||
|-gtk-icon-transform| [Transform list](https://drafts.csswg.org/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-transform| [Transform list](https://www.w3.org/TR/css-transforms-1/#typedef-transform-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-palette| Color palette, as explained above | used to recolor symbolic icons |
|
||||
|-gtk-icon-shadow| [Shadow](https://www.w3.org/TR/css-backgrounds-3/#typedef-shadow) or `none` | applied to builtin and application-loaded icons |
|
||||
|-gtk-icon-filter| [Filter value list](https://www.w3.org/TR/filter-effects-1/#typedef-filter-value-list) or `none` | applied to builtin and application-loaded icons |
|
||||
|transform| [CSS Transforms Level 2](https://drafts.csswg.org/css-transforms-2/) | |
|
||||
|transform| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-property) | |
|
||||
|transform-origin| [CSS Transforms Level 1](https://www.w3.org/TR/css-transforms-1/#transform-origin-property) | CSS allows specifying a z component|
|
||||
|min-width| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-width) | CSS allows percentages |
|
||||
|min-height| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#min-height) | CSS allows percentages |
|
||||
|margin-top| [CSS Box Model Level 3](https://www.w3.org/TR/css3-box/#margin-top) | CSS allows percentages or auto |
|
||||
@@ -217,7 +243,7 @@ done with
|
||||
|background-size| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-size) | |
|
||||
|background-position| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-position) | |
|
||||
|background-repeat| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-repeat) | |
|
||||
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes, colors in crossfades |
|
||||
|background-image| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background-image) | not supported: urls without quotes |
|
||||
|box-shadow| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#box-shadow) | |
|
||||
|background-blend-mode| [CSS Compositing and Blending Level 1](https://www.w3.org/TR/compositing-1/#propdef-background-blend-mode) | only affects multiple backgrounds |
|
||||
|background| [CSS Backgrounds and Borders Level 3](https://www.w3.org/TR/css3-background/#background) | |
|
||||
@@ -235,4 +261,4 @@ done with
|
||||
|animation-delay| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-delay) | |
|
||||
|animation-fill-mode| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation-fill-mode) | |
|
||||
|animation| [CSS Animations Level 1](https://www.w3.org/TR/css3-animations/#animation) | |
|
||||
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBox and GtkGrid |
|
||||
|border-spacing| [CSS Table Level 3](https://www.w3.org/TR/css-tables-3/#border-spacing-property) | respected by GtkBoxLayout, GtkGridLayout, GtkCenterLayout |
|
||||
|
||||
@@ -343,20 +343,19 @@ Many widgets, like buttons, do all their drawing themselves. You just tell
|
||||
them the label you want to see, and they figure out what font to use, draw
|
||||
the button outline and focus rectangle, etc. Sometimes, it is necessary to
|
||||
do some custom drawing. In that case, a GtkDrawingArea might be the right
|
||||
widget to use. It offers a canvas on which you can draw by connecting to
|
||||
the ::draw signal.
|
||||
widget to use. It offers a canvas on which you can draw by setting its
|
||||
draw function.
|
||||
|
||||
The contents of a widget often need to be partially or fully redrawn,
|
||||
e.g. when another window is moved and uncovers part of the widget, or
|
||||
when the window containing it is resized. It is also possible to explicitly
|
||||
cause part or all of the widget to be redrawn, by calling
|
||||
gtk_widget_queue_draw() or its variants. GTK takes care of most of the
|
||||
details by providing a ready-to-use cairo context to the ::draw signal
|
||||
handler.
|
||||
cause a widget to be redrawn, by calling gtk_widget_queue_draw(). GTK takes
|
||||
care of most of the details by providing a ready-to-use cairo context to the
|
||||
draw function.
|
||||
|
||||
The following example shows a ::draw signal handler. It is a bit more
|
||||
complicated than the previous examples, since it also demonstrates
|
||||
input event handling by means of event controllers.
|
||||
The following example shows how to use a draw function with GtkDrawingArea.
|
||||
It is a bit more complicated than the previous examples, since it also
|
||||
demonstrates input event handling with event controllers.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -41,35 +41,41 @@
|
||||
<command>gtk4-builder-tool</command> can perform various operations
|
||||
on GtkBuilder .ui files.
|
||||
</para>
|
||||
<para>
|
||||
The <option>validate</option> command validates the .ui file and reports
|
||||
errors to stderr.
|
||||
</para>
|
||||
<para>
|
||||
The <option>enumerate</option> command lists all the named objects that
|
||||
are created in the .ui file.
|
||||
</para>
|
||||
<para>
|
||||
The <option>preview</option> command displays the .ui file. This command
|
||||
accepts options to specify the ID of the toplevel object and a .css file
|
||||
to use.
|
||||
</para>
|
||||
<para>
|
||||
The <option>simplify</option> command simplifies the .ui file by removing
|
||||
properties that are set to their default values and writes the resulting XML
|
||||
to stdout, or back to the input file.
|
||||
</para>
|
||||
<para>
|
||||
When the <option>--3to4</option> is specified, <option>simplify</option>
|
||||
interprets the input as a GTK 3 ui file and attempts to convert it to GTK 4
|
||||
equivalents. It performs various conversions, such as renaming properties,
|
||||
translating child properties to layout properties, rewriting the setup for
|
||||
GtkNotebook, GtkStack, GtkAssistant or changing toolbars into boxes.
|
||||
</para>
|
||||
<para>
|
||||
You should always test the modified .ui files produced by gtk4-builder-tool
|
||||
before using them in production.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1><title>Commands</title>
|
||||
<para>The following commands are understood:</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>validate</option></term>
|
||||
<listitem><para>Validates the .ui file and report errors to stderr.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>simplify</option></term>
|
||||
<listitem><para>Simplifies the .ui file by removing properties that
|
||||
are set to their default values and write the resulting XML to stdout,
|
||||
or back to the input file.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>enumerate</option></term>
|
||||
<listitem><para>Lists all the named objects that are created in the .ui file.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>preview</option></term>
|
||||
<listitem><para>Preview the .ui file. This command accepts options
|
||||
to specify the ID of an object and a .css file to use.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
Note in particular that the conversion
|
||||
done with <option>--3to4</option> is meant as a starting point for a port
|
||||
from GTK 3 to GTK 4. It is expected that you will have to do manual fixups
|
||||
after the initial conversion.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1><title>Simplify Options</title>
|
||||
|
||||
@@ -61,6 +61,13 @@
|
||||
<listitem><para>Write png files to <replaceable>DIRECTORY</replaceable>
|
||||
instead of the current working directory.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>--debug</term>
|
||||
<listitem><para>Generate png files of the various channels during
|
||||
the conversion. If these files are not monochrome green, they
|
||||
are often helpful in pinpointing the problematic parts of
|
||||
the source svg.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@@ -1831,7 +1831,6 @@ GtkIMContextSimple
|
||||
gtk_im_context_simple_new
|
||||
gtk_im_context_simple_add_table
|
||||
gtk_im_context_simple_add_compose_file
|
||||
GTK_MAX_COMPOSE_LEN
|
||||
<SUBSECTION Standard>
|
||||
GTK_IM_CONTEXT_SIMPLE
|
||||
GTK_IS_IM_CONTEXT_SIMPLE
|
||||
@@ -4668,7 +4667,6 @@ GTK_WINDOW_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
GtkWindowPrivate
|
||||
gtk_window_get_type
|
||||
GtkWindowGeometryInfo
|
||||
gtk_window_remove_embedded_xid
|
||||
gtk_window_add_embedded_xid
|
||||
GtkWindowKeysForeachFunc
|
||||
|
||||
@@ -413,10 +413,6 @@ images = [
|
||||
'images/password-entry.png',
|
||||
'images/picture.png',
|
||||
'images/popover.png',
|
||||
'images/popup-anchors.png',
|
||||
'images/popup-at.svg',
|
||||
'images/popup-flip.png',
|
||||
'images/popup-slide.png',
|
||||
'images/printdialog.png',
|
||||
'images/progressbar.png',
|
||||
'images/right-center.png',
|
||||
|
||||
@@ -165,11 +165,11 @@ for this change.
|
||||
| ::key-release-event | #GtkEventControllerKey |
|
||||
| ::enter-notify-event | #GtkEventControllerMotion |
|
||||
| ::leave-notify-event | #GtkEventControllerMotion |
|
||||
| ::configure-event | replaced by #GdkSurface::layout |
|
||||
| ::configure-event | - |
|
||||
| ::focus-in-event | #GtkEventControllerFocus |
|
||||
| ::focus-out-event | #GtkEventControllerFocus |
|
||||
| ::map-event | replaced by #GdkSurface:mapped |
|
||||
| ::unmap-event | replaced by #GdkSurface:mapped |
|
||||
| ::map-event | - |
|
||||
| ::unmap-event | - |
|
||||
| ::property-notify-event | replaced by #GdkClipboard |
|
||||
| ::selection-clear-event | replaced by #GdkClipboard |
|
||||
| ::selection-request-event | replaced by #GdkClipboard |
|
||||
@@ -178,10 +178,17 @@ for this change.
|
||||
| ::proximity-in-event | #GtkGestureStylus |
|
||||
| ::proximity-out-event | #GtkGestureStylus |
|
||||
| ::visibility-notify-event | - |
|
||||
| ::window-state-event | replaced by #GdkToplevel:state |
|
||||
| ::window-state-event | - |
|
||||
| ::damage-event | - |
|
||||
| ::grab-broken-event | - |
|
||||
|
||||
Event signals which are not directly related to input have to be dealt
|
||||
with on a one-by-one basis. If you were using ::configure-event and
|
||||
::window-state-event to save window state, you should use property
|
||||
notification for corresponding GtkWindow properties, such as
|
||||
#GtkWindow:default-width, #GtkWindow:default-height, #GtkWindow:maximized
|
||||
or #GtkWindow:fullscreened.
|
||||
|
||||
### Set a proper application ID
|
||||
|
||||
In GTK 4 we want the application's #GApplication 'application-id'
|
||||
@@ -264,14 +271,6 @@ therefore can no longer be used to break reference cycles. A typical sign
|
||||
of a reference cycle involving a toplevel window is when closing the window
|
||||
does not make the application quit.
|
||||
|
||||
A good rule to follow is: If you set a widget pointer with
|
||||
gtk_widget_class_bind_template_child() in class_init(), you need to
|
||||
unparent it in dispose(). The slight complication here is that you need
|
||||
to respect the widget hierarchy while doing so. Ie if you set both `field1`
|
||||
and `field2`, but `field1` is an ancestor of `field2`, then you only need
|
||||
to unparent `field1` — doing so will remove the the entire subtree below
|
||||
`field1`, including `field2`.
|
||||
|
||||
### Stop using GdkScreen
|
||||
|
||||
The GdkScreen object has been removed in GTK 4. Most of its APIs already
|
||||
@@ -407,7 +406,7 @@ and gdk_keymap_get_entries_for_keyval().
|
||||
GTK 3 has the idea that use of modifiers may differ between different
|
||||
platforms, and has a #GdkModifierIntent api to let platforms provide
|
||||
hint about how modifiers are expected to be used. It also promoted
|
||||
the use of <Primary> instead of <Control> to specify accelerators that
|
||||
the use of `<Primary>` instead of `<Control>` to specify accelerators that
|
||||
adapt to platform conventions.
|
||||
|
||||
In GTK 4, the meaning of modifiers has been fixed, and backends are
|
||||
@@ -426,13 +425,88 @@ GDK_CONTROL_MASK|GDK_ALT_MASK
|
||||
: Prevent text input
|
||||
|
||||
Consequently, #GdkModifierIntent and related APIs have been removed,
|
||||
and <Control> is preferred over <Primary> in accelerators.
|
||||
and `<Control>` is preferred over `<Primary>` in accelerators.
|
||||
|
||||
A related change is that GTK 4 no longer supports the use of archaic
|
||||
X11 'real' modifiers with the names Mod1,..., Mod5, and %GDK_MOD1_MASK
|
||||
has been renamed to %GDK_ALT_MASK.
|
||||
|
||||
### Stop using gtk_get_current_... APIs
|
||||
### Replace GtkClipboard with GdkClipboard
|
||||
|
||||
The `GtkClipboard` API has been removed, and replaced by #GdkClipboard.
|
||||
There is not direct 1:1 mapping between the old an the new API, so it cannot
|
||||
be a mechanical replacement; the new API is based on object types and #GValue
|
||||
like object properties, instead of opaque identifiers, so it should be easier
|
||||
to use.
|
||||
|
||||
For instance, the example below copies the contents of an entry into the
|
||||
clipboard:
|
||||
|
||||
```
|
||||
static void
|
||||
copy_text (GtkWidget *widget)
|
||||
{
|
||||
GtkEditable *editable = GTK_EDITABLE (widget);
|
||||
|
||||
// Initialize a GValue with the contents of the widget
|
||||
GValue value = G_VALUE_INIT;
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
g_value_set_string (&value, gtk_editable_get_text (editable));
|
||||
|
||||
// Store the value in the clipboard object
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
|
||||
gdk_clipboard_set_value (clipboard, &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
```
|
||||
|
||||
whereas the example below pastes the contents into the entry:
|
||||
|
||||
```
|
||||
static void
|
||||
paste_text (GtkWidget *widget)
|
||||
{
|
||||
GtkEditable *editable = GTK_EDITABLE (widget);
|
||||
|
||||
// Initialize a GValue to receive text
|
||||
GValue value = G_VALUE_INIT;
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
|
||||
// Get the content provider for the clipboard, and ask it for text
|
||||
GdkClipboard *clipboard = gtk_widget_get_clipboard (widget);
|
||||
GdkContentProvider *provider = gdk_clipboard_get_content (clipboard);
|
||||
|
||||
// If the content provider does not contain text, we are not interested
|
||||
if (!gdk_content_provider_get_value (provider, &value, NULL))
|
||||
return;
|
||||
|
||||
const char *str = g_value_get_string (&value);
|
||||
|
||||
gtk_editable_set_text (editable, str);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
```
|
||||
|
||||
The convenience API for specific target types in `GtkClipboard` has been
|
||||
replaced by their corresponding GType:
|
||||
|
||||
| GtkClipboard | GType |
|
||||
| ----------------------------------- | ---------------------- |
|
||||
| `gtk_clipboard_request_text()` | `G_TYPE_STRING` |
|
||||
| `gtk_clipboard_request_rich_text()` | `GTK_TYPE_TEXT_BUFFER` |
|
||||
| `gtk_clipboard_request_image()` | `GDK_TYPE_PIXBUF` |
|
||||
| `gtk_clipboard_request_uris()` |` GDK_TYPE_FILE_LIST` |
|
||||
|
||||
**Note**: Support for rich text serialization across different processes
|
||||
for #GtkTextBuffer is not available any more.
|
||||
|
||||
If you are copying the contents of an image, it is recommended to use
|
||||
GDK_TYPE_PAINTABLE instead of GDK_TYPE_PIXBUF, to minimize the amount of
|
||||
potential copies.
|
||||
|
||||
### Stop using `gtk_get_current_...` APIs
|
||||
|
||||
The function gtk_get_current_event() and its variants have been
|
||||
replaced by equivalent event controller APIs:
|
||||
@@ -448,6 +522,25 @@ option. You should always review the resulting changes.
|
||||
The <requires> tag now supports for the 'lib' attribute the
|
||||
'gtk' value only, instead of the 'gtk+' one previously.
|
||||
|
||||
### Adapt to GtkBuilder API changes
|
||||
|
||||
gtk_builder_connect_signals() no longer exists. Instead, signals are
|
||||
always connected automatically. If you need to add user data to your
|
||||
signals, gtk_builder_set_current_object() must be called. An important
|
||||
caveat is that you have to do this before loading any XML. This means if
|
||||
you need to use gtk_builder_set_current_object(), you can no longer use
|
||||
gtk_builder_new_from_file(), gtk_builder_new_from_resource(), or
|
||||
gtk_builder_new_from_string(). Instead, you must use vanilla gtk_builder_new(),
|
||||
then call gtk_builder_set_current_object(), then load the XML using
|
||||
gtk_builder_add_from_file(), gtk_builder_add_from_resource(), or
|
||||
gtk_builder_add_from_string(). You must check the return value for
|
||||
failure and manually abort with g_error() if something went wrong.
|
||||
|
||||
You only have to worry about this if you were previously using
|
||||
gtk_builder_connect_signals(). If you are using templates, then
|
||||
gtk_widget_init_template() will call gtk_builder_set_current_object()
|
||||
for you, so templates work like before.
|
||||
|
||||
### Adapt to event controller API changes
|
||||
|
||||
A few changes to the event controller and #GtkGesture APIs
|
||||
@@ -458,6 +551,23 @@ Another is that #GtkGestureMultiPress has been renamed to #GtkGestureClick,
|
||||
and has lost its area property. A #GtkEventControllerFocus has been
|
||||
split off from #GtkEventcontrollerKey.
|
||||
|
||||
In GTK 3, #GtkEventController:widget was a construct-only property, so
|
||||
a #GtkWidget was provided whenever constructing a #GtkEventController.
|
||||
In GTK 4, #GtkEventController:widget is now read-only. Use
|
||||
gtk_widget_add_controller() to add an event controller to a widget.
|
||||
|
||||
In GTK 3, widgets did not own their event controllers, and event
|
||||
controllers did not own their widgets, so developers were responsible
|
||||
for manually keeping event controllers alive for the lifetime of their
|
||||
associated widgets. In GTK 4, widgets own their event controllers.
|
||||
gtk_widget_add_controller() takes ownership of the event controller, so
|
||||
there is no longer any need to store a reference to the event controller
|
||||
after it has been added to a widget.
|
||||
|
||||
Although not normally needed, an event controller could be removed from
|
||||
a widget in GTK 3 by destroying the event controller with g_object_unref().
|
||||
In GTK 4, you must use gtk_widget_remove_controller().
|
||||
|
||||
### Focus handling changes
|
||||
|
||||
The semantics of the #GtkWidget:can-focus property have changed.
|
||||
@@ -751,7 +861,8 @@ to get it.
|
||||
The ::size-allocate signal has been removed, since it is easy
|
||||
to misuse. If you need to learn about sizing changes of custom
|
||||
drawing widgets, use the #GtkDrawingArea::resize or #GtkGLArea::resize
|
||||
signals.
|
||||
signals. If you want to track the size of toplevel windows, use
|
||||
property notification for #GtkWindow:default-width and #GtkWindow:default-height.
|
||||
|
||||
### Switch to GtkWidget's children APIs
|
||||
|
||||
@@ -968,6 +1079,11 @@ that wants to override the default handling, you can provide an
|
||||
implementation of the default.activate action in your widgets' action
|
||||
groups.
|
||||
|
||||
### Stop using gtk_widget_grab_default()
|
||||
|
||||
The function gtk_widget_grab_default() has been removed. If you need
|
||||
to mark a widget as default, use gtk_window_set_default_widget() directly.
|
||||
|
||||
### Stop setting ::has-default and ::has-focus in .ui files
|
||||
|
||||
The special handling for the ::has-default and ::has-focus properties
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "exampleapp.h"
|
||||
#include "exampleappwin.h"
|
||||
|
||||
struct _ExampleAppWindow
|
||||
{
|
||||
GtkApplicationWindow parent;
|
||||
|
||||
GSettings *settings;
|
||||
GtkWidget *stack;
|
||||
GtkWidget *search;
|
||||
GtkWidget *searchbar;
|
||||
GtkWidget *searchentry;
|
||||
GtkWidget *gears;
|
||||
GtkWidget *sidebar;
|
||||
GtkWidget *words;
|
||||
GtkWidget *lines;
|
||||
GtkWidget *lines_label;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static void
|
||||
search_text_changed (GtkEntry *entry,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
const char *text;
|
||||
GtkWidget *tab;
|
||||
GtkWidget *view;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter start, match_start, match_end;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
if (text[0] == '\0')
|
||||
return;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
/* Very simple-minded search implementation */
|
||||
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||
if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
|
||||
&match_start, &match_end, NULL))
|
||||
{
|
||||
gtk_text_buffer_select_range (buffer, &match_start, &match_end);
|
||||
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
|
||||
0.0, FALSE, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_word (GtkButton *button,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
const char *word;
|
||||
|
||||
word = gtk_button_get_label (button);
|
||||
gtk_editable_set_text (GTK_EDITABLE (win->searchentry), word);
|
||||
}
|
||||
|
||||
static void
|
||||
update_words (ExampleAppWindow *win)
|
||||
{
|
||||
GHashTable *strings;
|
||||
GHashTableIter iter;
|
||||
GtkWidget *tab, *view, *row;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter start, end;
|
||||
char *word, *key;
|
||||
GtkWidget *child;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||
while (!gtk_text_iter_is_end (&start))
|
||||
{
|
||||
while (!gtk_text_iter_starts_word (&start))
|
||||
{
|
||||
if (!gtk_text_iter_forward_char (&start))
|
||||
goto done;
|
||||
}
|
||||
end = start;
|
||||
if (!gtk_text_iter_forward_word_end (&end))
|
||||
goto done;
|
||||
word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||
g_hash_table_add (strings, g_utf8_strdown (word, -1));
|
||||
g_free (word);
|
||||
start = end;
|
||||
}
|
||||
|
||||
done:
|
||||
while ((child = gtk_widget_get_first_child (win->words)))
|
||||
gtk_list_box_remove (GTK_LIST_BOX (win->words), child);
|
||||
|
||||
g_hash_table_iter_init (&iter, strings);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
|
||||
{
|
||||
row = gtk_button_new_with_label (key);
|
||||
g_signal_connect (row, "clicked",
|
||||
G_CALLBACK (find_word), win);
|
||||
gtk_box_append (GTK_BOX (win->words), row);
|
||||
}
|
||||
|
||||
g_hash_table_unref (strings);
|
||||
}
|
||||
|
||||
static void
|
||||
update_lines (ExampleAppWindow *win)
|
||||
{
|
||||
GtkWidget *tab, *view;
|
||||
GtkTextBuffer *buffer;
|
||||
int count;
|
||||
char *lines;
|
||||
|
||||
tab = gtk_stack_get_visible_child (GTK_STACK (win->stack));
|
||||
|
||||
if (tab == NULL)
|
||||
return;
|
||||
|
||||
view = gtk_scrolled_window_get_child (GTK_SCROLLED_WINDOW (tab));
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
count = gtk_text_buffer_get_line_count (buffer);
|
||||
lines = g_strdup_printf ("%d", count);
|
||||
gtk_label_set_text (GTK_LABEL (win->lines), lines);
|
||||
g_free (lines);
|
||||
}
|
||||
|
||||
static void
|
||||
visible_child_changed (GObject *stack,
|
||||
GParamSpec *pspec,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
if (gtk_widget_in_destruction (GTK_WIDGET (stack)))
|
||||
return;
|
||||
|
||||
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (win->searchbar), FALSE);
|
||||
update_words (win);
|
||||
update_lines (win);
|
||||
}
|
||||
|
||||
static void
|
||||
words_changed (GObject *sidebar,
|
||||
GParamSpec *pspec,
|
||||
ExampleAppWindow *win)
|
||||
{
|
||||
update_words (win);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_init (ExampleAppWindow *win)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GMenuModel *menu;
|
||||
GAction *action;
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (win));
|
||||
win->settings = g_settings_new ("org.gtk.exampleapp");
|
||||
|
||||
g_settings_bind (win->settings, "transition",
|
||||
win->stack, "transition-type",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_settings_bind (win->settings, "show-words",
|
||||
win->sidebar, "reveal-child",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
g_object_bind_property (win->search, "active",
|
||||
win->searchbar, "search-mode-enabled",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
|
||||
g_signal_connect (win->sidebar, "notify::reveal-child",
|
||||
G_CALLBACK (words_changed), win);
|
||||
|
||||
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
|
||||
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
|
||||
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (win->gears), menu);
|
||||
g_object_unref (builder);
|
||||
|
||||
action = g_settings_create_action (win->settings, "show-words");
|
||||
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||
g_object_unref (action);
|
||||
|
||||
action = (GAction*) g_property_action_new ("show-lines", win->lines, "visible");
|
||||
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||
g_object_unref (action);
|
||||
|
||||
g_object_bind_property (win->lines, "visible",
|
||||
win->lines_label, "visible",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
g_object_set (gtk_settings_get_default (), "gtk-shell-shows-app-menu", FALSE, NULL);
|
||||
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_dispose (GObject *object)
|
||||
{
|
||||
ExampleAppWindow *win;
|
||||
|
||||
win = EXAMPLE_APP_WINDOW (object);
|
||||
|
||||
g_clear_object (&win->settings);
|
||||
|
||||
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
example_app_window_class_init (ExampleAppWindowClass *class)
|
||||
{
|
||||
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
|
||||
|
||||
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||
"/org/gtk/exampleapp/window.ui");
|
||||
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);
|
||||
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
||||
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed);
|
||||
}
|
||||
|
||||
ExampleAppWindow *
|
||||
example_app_window_new (ExampleApp *app)
|
||||
{
|
||||
return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
example_app_window_open (ExampleAppWindow *win,
|
||||
GFile *file)
|
||||
{
|
||||
char *basename;
|
||||
GtkWidget *scrolled, *view;
|
||||
char *contents;
|
||||
gsize length;
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextTag *tag;
|
||||
GtkTextIter start_iter, end_iter;
|
||||
|
||||
basename = g_file_get_basename (file);
|
||||
|
||||
scrolled = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_hexpand (scrolled, TRUE);
|
||||
gtk_widget_set_vexpand (scrolled, TRUE);
|
||||
view = gtk_text_view_new ();
|
||||
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
|
||||
gtk_stack_add_titled (GTK_STACK (win->stack), scrolled, basename, basename);
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||
|
||||
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
|
||||
{
|
||||
gtk_text_buffer_set_text (buffer, contents, length);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
|
||||
g_settings_bind (win->settings, "font",
|
||||
tag, "font",
|
||||
G_SETTINGS_BIND_DEFAULT);
|
||||
|
||||
gtk_text_buffer_get_start_iter (buffer, &start_iter);
|
||||
gtk_text_buffer_get_end_iter (buffer, &end_iter);
|
||||
gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter);
|
||||
|
||||
g_free (basename);
|
||||
|
||||
gtk_widget_set_sensitive (win->search, TRUE);
|
||||
|
||||
update_words (win);
|
||||
update_lines (win);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ stash_desktop_startup_notification_id (void)
|
||||
if (!g_utf8_validate (desktop_startup_id, -1, NULL))
|
||||
g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
|
||||
else
|
||||
startup_notification_id = g_strdup (desktop_startup_id ? desktop_startup_id : "");
|
||||
startup_notification_id = g_strdup (desktop_startup_id);
|
||||
}
|
||||
|
||||
/* Clear the environment variable so it won't be inherited by
|
||||
|
||||
@@ -611,17 +611,7 @@ _gdk_device_set_associated_device (GdkDevice *device,
|
||||
g_return_if_fail (GDK_IS_DEVICE (device));
|
||||
g_return_if_fail (associated == NULL || GDK_IS_DEVICE (associated));
|
||||
|
||||
if (device->associated == associated)
|
||||
return;
|
||||
|
||||
if (device->associated)
|
||||
{
|
||||
g_object_unref (device->associated);
|
||||
device->associated = NULL;
|
||||
}
|
||||
|
||||
if (associated)
|
||||
device->associated = g_object_ref (associated);
|
||||
g_set_object (&device->associated, associated);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -280,7 +280,7 @@ gdk_draw_context_get_surface (GdkDrawContext *context)
|
||||
* implementation must use gdk_draw_context_get_frame_region() to query the
|
||||
* region that must be drawn.
|
||||
*
|
||||
* When using GTK+, the widget system automatically places calls to
|
||||
* When using GTK, the widget system automatically places calls to
|
||||
* gdk_draw_context_begin_frame() and gdk_draw_context_end_frame() via the
|
||||
* use of #GskRenderers, so application code does not need to call these
|
||||
* functions explicitly.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
static gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||
{
|
||||
|
||||
@@ -210,7 +210,7 @@ gdk_event_init (GdkEvent *self)
|
||||
GType
|
||||
gdk_event_get_type (void)
|
||||
{
|
||||
static volatile gsize event_type__volatile;
|
||||
static gsize event_type__volatile;
|
||||
|
||||
if (g_once_init_enter (&event_type__volatile))
|
||||
{
|
||||
@@ -374,7 +374,7 @@ static GType gdk_event_types[GDK_EVENT_LAST];
|
||||
GType \
|
||||
type_name ## _get_type (void) \
|
||||
{ \
|
||||
static volatile gsize gdk_define_event_type_id__volatile; \
|
||||
static gsize gdk_define_event_type_id__volatile; \
|
||||
if (g_once_init_enter (&gdk_define_event_type_id__volatile)) \
|
||||
{ \
|
||||
GType gdk_define_event_type_id = \
|
||||
@@ -452,7 +452,7 @@ gdk_event_init_types_once (void)
|
||||
void
|
||||
gdk_event_init_types (void)
|
||||
{
|
||||
static volatile gsize event_types__volatile;
|
||||
static gsize event_types__volatile;
|
||||
|
||||
if (g_once_init_enter (&event_types__volatile))
|
||||
{
|
||||
|
||||
@@ -107,6 +107,9 @@ make_program (GdkGLContextProgram *program,
|
||||
|
||||
glLinkProgram (program->program);
|
||||
|
||||
glDetachShader (program->program, vertex_shader);
|
||||
glDetachShader (program->program, fragment_shader);
|
||||
|
||||
glDeleteShader (vertex_shader);
|
||||
glDeleteShader (fragment_shader);
|
||||
|
||||
|
||||
@@ -30,6 +30,37 @@
|
||||
* Popups are positioned relative to their parent surface.
|
||||
* The GdkPopupLayout struct contains information that is
|
||||
* necessary to do so.
|
||||
*
|
||||
* The positioning requires a negotiation with the windowing system,
|
||||
* since it depends on external constraints, such as the position of
|
||||
* the parent surface, and the screen dimensions.
|
||||
*
|
||||
* The basic ingredients are a rectangle on the parent surface,
|
||||
* and the anchor on both that rectangle and the popup. The anchors
|
||||
* specify a side or corner to place next to each other.
|
||||
*
|
||||
* 
|
||||
*
|
||||
* For cases where placing the anchors next to each other would make
|
||||
* the popup extend offscreen, the layout includes some hints for how
|
||||
* to resolve this problem. The hints may suggest to flip the anchor
|
||||
* position to the other side, or to 'slide' the popup along a side,
|
||||
* or to resize it.
|
||||
*
|
||||
* 
|
||||
*
|
||||
* 
|
||||
*
|
||||
* These hints may be combined.
|
||||
*
|
||||
* Ultimatively, it is up to the windowing system to determine the position
|
||||
* and size of the popup. You can learn about the result by calling
|
||||
* gdk_popup_get_position_x(), gdk_popup_get_position_y(),
|
||||
* gdk_popup_get_rect_anchor() and gdk_popup_get_surface_anchor() after the
|
||||
* popup has been presented. This can be used to adjust the rendering. For
|
||||
* example, GtkPopover changes its arrow position accordingly. But you have
|
||||
* to be careful avoid changing the size of the popover, or it has to be
|
||||
* presented again.
|
||||
*/
|
||||
|
||||
struct _GdkPopupLayout
|
||||
|
||||
@@ -436,9 +436,10 @@ gdk_seat_tool_removed (GdkSeat *seat,
|
||||
}
|
||||
|
||||
GdkDeviceTool *
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial,
|
||||
guint64 hw_id)
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial,
|
||||
guint64 hw_id,
|
||||
GdkDeviceToolType type)
|
||||
{
|
||||
GdkDeviceTool *match = NULL;
|
||||
GList *tools, *l;
|
||||
@@ -449,7 +450,7 @@ gdk_seat_get_tool (GdkSeat *seat,
|
||||
{
|
||||
GdkDeviceTool *tool = l->data;
|
||||
|
||||
if (tool->serial == serial && tool->hw_id == hw_id)
|
||||
if (tool->serial == serial && tool->hw_id == hw_id && tool->type == type)
|
||||
{
|
||||
match = tool;
|
||||
break;
|
||||
|
||||
@@ -49,7 +49,7 @@ struct _GdkSeatDefaultPrivate
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GdkSeatDefault, gdk_seat_default, GDK_TYPE_SEAT)
|
||||
|
||||
static void
|
||||
gdk_seat_dispose (GObject *object)
|
||||
gdk_seat_default_dispose (GObject *object)
|
||||
{
|
||||
GdkSeatDefault *seat = GDK_SEAT_DEFAULT (object);
|
||||
GdkSeatDefaultPrivate *priv = gdk_seat_default_get_instance_private (seat);
|
||||
@@ -79,11 +79,7 @@ gdk_seat_dispose (GObject *object)
|
||||
g_object_unref (l->data);
|
||||
}
|
||||
|
||||
if (priv->tools)
|
||||
{
|
||||
g_ptr_array_unref (priv->tools);
|
||||
priv->tools = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->tools, g_ptr_array_unref);
|
||||
|
||||
g_list_free (priv->physical_pointers);
|
||||
g_list_free (priv->physical_keyboards);
|
||||
@@ -307,7 +303,7 @@ gdk_seat_default_class_init (GdkSeatDefaultClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass);
|
||||
|
||||
object_class->dispose = gdk_seat_dispose;
|
||||
object_class->dispose = gdk_seat_default_dispose;
|
||||
|
||||
seat_class->get_capabilities = gdk_seat_default_get_capabilities;
|
||||
|
||||
@@ -442,7 +438,7 @@ gdk_seat_default_remove_tool (GdkSeatDefault *seat,
|
||||
|
||||
priv = gdk_seat_default_get_instance_private (seat);
|
||||
|
||||
if (tool != gdk_seat_get_tool (GDK_SEAT (seat), tool->serial, tool->hw_id))
|
||||
if (tool != gdk_seat_get_tool (GDK_SEAT (seat), tool->serial, tool->hw_id, tool->type))
|
||||
return;
|
||||
|
||||
g_signal_emit_by_name (seat, "tool-removed", tool);
|
||||
|
||||
@@ -75,9 +75,10 @@ void gdk_seat_tool_removed (GdkSeat *seat,
|
||||
GdkDeviceTool *tool);
|
||||
|
||||
GdkDeviceTool *
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial,
|
||||
guint64 hw_id);
|
||||
gdk_seat_get_tool (GdkSeat *seat,
|
||||
guint64 serial,
|
||||
guint64 hw_id,
|
||||
GdkDeviceToolType type);
|
||||
|
||||
GdkGrabStatus gdk_seat_grab (GdkSeat *seat,
|
||||
GdkSurface *surface,
|
||||
|
||||
@@ -92,6 +92,7 @@ enum {
|
||||
PROP_MAPPED,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_SCALE_FACTOR,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
@@ -551,6 +552,13 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
properties[PROP_SCALE_FACTOR] =
|
||||
g_param_spec_int ("scale-factor",
|
||||
P_("Scale factor"),
|
||||
P_("Scale factor"),
|
||||
1, G_MAXINT, 1,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, properties);
|
||||
|
||||
/**
|
||||
@@ -782,6 +790,10 @@ gdk_surface_get_property (GObject *object,
|
||||
g_value_set_int (value, surface->height);
|
||||
break;
|
||||
|
||||
case PROP_SCALE_FACTOR:
|
||||
g_value_set_int (value, gdk_surface_get_scale_factor (surface));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -2545,8 +2557,7 @@ gdk_surface_get_frame_clock (GdkSurface *surface)
|
||||
* value can be used to determine whether to use a pixel resource
|
||||
* with higher resolution data.
|
||||
*
|
||||
* The scale of a surface may change during runtime, if this happens
|
||||
* a configure event will be sent to the toplevel surface.
|
||||
* The scale of a surface may change during runtime.
|
||||
*
|
||||
* Returns: the scale factor
|
||||
*/
|
||||
@@ -2949,8 +2960,8 @@ gdk_surface_request_motion (GdkSurface *surface)
|
||||
* gdk_surface_translate_coordinates:
|
||||
* @from: the origin surface
|
||||
* @to: the target surface
|
||||
* @x: coordinates to translate
|
||||
* @y: coordinates to translate
|
||||
* @x: (inout): coordinates to translate
|
||||
* @y: (inout): coordinates to translate
|
||||
*
|
||||
* Translates the given coordinates from being
|
||||
* relative to the @from surface to being relative
|
||||
@@ -2969,9 +2980,18 @@ gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
double *x,
|
||||
double *y)
|
||||
{
|
||||
double in_x, in_y, out_x, out_y;
|
||||
int x1, y1, x2, y2;
|
||||
GdkSurface *f, *t;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (from), FALSE);
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (to), FALSE);
|
||||
g_return_val_if_fail (x != NULL, FALSE);
|
||||
g_return_val_if_fail (y != NULL, FALSE);
|
||||
|
||||
in_x = *x;
|
||||
in_y = *y;
|
||||
|
||||
x1 = 0;
|
||||
y1 = 0;
|
||||
f = from;
|
||||
@@ -2995,8 +3015,11 @@ gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
if (f != t)
|
||||
return FALSE;
|
||||
|
||||
*x += x1 - x2;
|
||||
*y += y1 - y2;
|
||||
out_x = in_x + (x1 - x2);
|
||||
out_y = in_y + (y1 - y2);
|
||||
|
||||
*x = out_x;
|
||||
*y = out_y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -316,9 +316,9 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
||||
* @resource_path: the path of the resource file
|
||||
*
|
||||
* Creates a new texture by loading an image from a resource.
|
||||
* The file format is detected automatically, and can be any
|
||||
* format that is supported by the gdk-pixbuf library, such as
|
||||
* JPEG or PNG.
|
||||
* The file format is detected automatically.
|
||||
* The supported formats are PNG and JPEG, though more formats might be
|
||||
* available.
|
||||
*
|
||||
* It is a fatal error if @resource_path does not specify a valid
|
||||
* image resource and the program will abort if that happens.
|
||||
@@ -352,9 +352,9 @@ gdk_texture_new_from_resource (const char *resource_path)
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new texture by loading an image from a file.
|
||||
* The file format is detected automatically, and can be any
|
||||
* format that is supported by the gdk-pixbuf library, such as
|
||||
* JPEG or PNG.
|
||||
* The file format is detected automatically.
|
||||
* The supported formats are PNG and JPEG, though more formats might be
|
||||
* available.
|
||||
*
|
||||
* If %NULL is returned, then @error will be set.
|
||||
*
|
||||
|
||||
@@ -149,12 +149,6 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
|
||||
{
|
||||
int geometry_width, geometry_height;
|
||||
|
||||
if (size->min_width > size->bounds_width ||
|
||||
size->min_height > size->bounds_height)
|
||||
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds bounds (%d, %d)",
|
||||
size->min_width, size->min_height,
|
||||
size->bounds_width, size->bounds_height);
|
||||
|
||||
geometry_width = size->width;
|
||||
geometry_height = size->height;
|
||||
if (size->shadow.is_valid)
|
||||
@@ -162,15 +156,4 @@ gdk_toplevel_size_validate (GdkToplevelSize *size)
|
||||
geometry_width -= size->shadow.left + size->shadow.right;
|
||||
geometry_height -= size->shadow.top + size->shadow.bottom;
|
||||
}
|
||||
if (geometry_width > size->bounds_width ||
|
||||
geometry_height > size->bounds_height)
|
||||
g_warning ("GdkToplevelSize: geometry size (%d, %d) exceeds bounds (%d, %d)",
|
||||
size->width, size->height,
|
||||
size->bounds_width, size->bounds_height);
|
||||
|
||||
if (size->min_width > size->width ||
|
||||
size->min_height > size->height)
|
||||
g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds size (%d, %d)",
|
||||
size->min_width, size->min_height,
|
||||
size->width, size->height);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,14 @@
|
||||
*/
|
||||
#define GDK_VERSION_4_0 (G_ENCODE_VERSION (4, 0))
|
||||
|
||||
/**
|
||||
* GDK_VERSION_4_2:
|
||||
*
|
||||
* A macro that evaluates to the 4.2 version of GDK, in a format
|
||||
* that can be used by the C pre-processor.
|
||||
*/
|
||||
#define GDK_VERSION_4_2 (G_ENCODE_VERSION (4, 2))
|
||||
|
||||
|
||||
/* evaluates to the current stable version; for development cycles,
|
||||
* this means the next stable target, with a hard backstop to the
|
||||
@@ -175,4 +183,19 @@
|
||||
# define GDK_DEPRECATED_IN_4_0_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
|
||||
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_4_2
|
||||
# define GDK_AVAILABLE_IN_4_2 GDK_UNAVAILABLE(4, 2)
|
||||
#else
|
||||
# define GDK_AVAILABLE_IN_4_2 _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_2
|
||||
# define GDK_DEPRECATED_IN_4_2 GDK_DEPRECATED
|
||||
# define GDK_DEPRECATED_IN_4_2_FOR(f) GDK_DEPRECATED_FOR(f)
|
||||
#else
|
||||
# define GDK_DEPRECATED_IN_4_2 _GDK_EXTERN
|
||||
# define GDK_DEPRECATED_IN_4_2_FOR(f) _GDK_EXTERN
|
||||
#endif
|
||||
|
||||
#endif /* __GDK_VERSION_MACROS_H__ */
|
||||
|
||||
@@ -225,7 +225,7 @@ gdk_vulkan_strerror (VkResult result)
|
||||
case VK_ERROR_PIPELINE_COMPILE_REQUIRED_EXT:
|
||||
return "A requested pipeline creation would have required compilation, but the application requested compilation to not be performed.";
|
||||
#endif
|
||||
#if VK_HEADER_VERSION < 142
|
||||
#if VK_HEADER_VERSION < 140
|
||||
case VK_RESULT_RANGE_SIZE:
|
||||
#endif
|
||||
case VK_RESULT_MAX_ENUM:
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
|
||||
#ifndef AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER
|
||||
typedef NSString *CALayerContentsGravity;
|
||||
#endif
|
||||
|
||||
@implementation GdkMacosWindow
|
||||
|
||||
-(BOOL)windowShouldClose:(id)sender
|
||||
@@ -466,7 +470,7 @@
|
||||
|
||||
inTrackManualResize = YES;
|
||||
|
||||
mouse_location = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
|
||||
mouse_location = convert_nspoint_to_screen (self, [self mouseLocationOutsideOfEventStream]);
|
||||
mdx = initialResizeLocation.x - mouse_location.x;
|
||||
mdy = initialResizeLocation.y - mouse_location.y;
|
||||
|
||||
@@ -588,7 +592,7 @@
|
||||
}
|
||||
|
||||
initialResizeFrame = [self frame];
|
||||
initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
|
||||
initialResizeLocation = convert_nspoint_to_screen (self, [self mouseLocationOutsideOfEventStream]);
|
||||
}
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
||||
typedef NSString *NSPasteboardType;
|
||||
#endif
|
||||
|
||||
#define GDK_TYPE_MACOS_CLIPBOARD (_gdk_macos_clipboard_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
|
||||
|
||||
@@ -40,8 +40,56 @@ typedef struct
|
||||
guint done : 1;
|
||||
} WriteRequest;
|
||||
|
||||
enum {
|
||||
TYPE_STRING,
|
||||
TYPE_PBOARD,
|
||||
TYPE_URL,
|
||||
TYPE_FILE_URL,
|
||||
TYPE_COLOR,
|
||||
TYPE_TIFF,
|
||||
TYPE_PNG,
|
||||
TYPE_LAST
|
||||
};
|
||||
|
||||
#define PTYPE(k) (get_pasteboard_type(TYPE_##k))
|
||||
|
||||
static NSPasteboardType pasteboard_types[TYPE_LAST];
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
|
||||
|
||||
static NSPasteboardType
|
||||
get_pasteboard_type (int type)
|
||||
{
|
||||
static gsize initialized = FALSE;
|
||||
|
||||
g_assert (type >= 0);
|
||||
g_assert (type < TYPE_LAST);
|
||||
|
||||
if (g_once_init_enter (&initialized))
|
||||
{
|
||||
pasteboard_types[TYPE_PNG] = NSPasteboardTypePNG;
|
||||
pasteboard_types[TYPE_STRING] = NSPasteboardTypeString;
|
||||
pasteboard_types[TYPE_TIFF] = NSPasteboardTypeTIFF;
|
||||
pasteboard_types[TYPE_COLOR] = NSPasteboardTypeColor;
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
pasteboard_types[TYPE_PBOARD] = NSStringPboardType;
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER
|
||||
pasteboard_types[TYPE_URL] = NSPasteboardTypeURL;
|
||||
pasteboard_types[TYPE_FILE_URL] = NSPasteboardTypeFileURL;
|
||||
#else
|
||||
pasteboard_types[TYPE_URL] = [[NSString alloc] initWithUTF8String:"public.url"];
|
||||
pasteboard_types[TYPE_FILE_URL] = [[NSString alloc] initWithUTF8String:"public.file-url"];
|
||||
#endif
|
||||
|
||||
g_once_init_leave (&initialized, TRUE);
|
||||
}
|
||||
|
||||
return pasteboard_types[type];
|
||||
}
|
||||
|
||||
static void
|
||||
write_request_free (WriteRequest *wr)
|
||||
{
|
||||
@@ -56,17 +104,17 @@ _gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([type isEqualToString:NSPasteboardTypeString] ||
|
||||
[type isEqualToString:NSStringPboardType])
|
||||
if ([type isEqualToString:PTYPE(STRING)] ||
|
||||
[type isEqualToString:PTYPE(PBOARD)])
|
||||
return g_intern_string ("text/plain;charset=utf-8");
|
||||
else if ([type isEqualToString:NSPasteboardTypeURL] ||
|
||||
[type isEqualToString:NSPasteboardTypeFileURL])
|
||||
else if ([type isEqualToString:PTYPE(URL)] ||
|
||||
[type isEqualToString:PTYPE(FILE_URL)])
|
||||
return g_intern_string ("text/uri-list");
|
||||
else if ([type isEqualToString:NSPasteboardTypeColor])
|
||||
else if ([type isEqualToString:PTYPE(COLOR)])
|
||||
return g_intern_string ("application/x-color");
|
||||
else if ([type isEqualToString:NSPasteboardTypeTIFF])
|
||||
else if ([type isEqualToString:PTYPE(TIFF)])
|
||||
return g_intern_string ("image/tiff");
|
||||
else if ([type isEqualToString:NSPasteboardTypePNG])
|
||||
else if ([type isEqualToString:PTYPE(PNG)])
|
||||
return g_intern_string ("image/png");
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
@@ -83,25 +131,25 @@ _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
|
||||
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
return NSPasteboardTypeString;
|
||||
return PTYPE(STRING);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = NSPasteboardTypeURL;
|
||||
return NSPasteboardTypeFileURL;
|
||||
*alternate = PTYPE(URL);
|
||||
return PTYPE(FILE_URL);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
return NSPasteboardTypeColor;
|
||||
return PTYPE(COLOR);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
return NSPasteboardTypeTIFF;
|
||||
return PTYPE(TIFF);
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
||||
{
|
||||
return NSPasteboardTypePNG;
|
||||
return PTYPE(PNG);
|
||||
}
|
||||
|
||||
return nil;
|
||||
@@ -220,7 +268,7 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([[self->pasteboard types] containsObject:NSPasteboardTypeFileURL])
|
||||
if ([[self->pasteboard types] containsObject:PTYPE(FILE_URL)])
|
||||
{
|
||||
GString *str = g_string_new (NULL);
|
||||
NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
|
||||
@@ -267,12 +315,12 @@ _gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
}
|
||||
else if (strcmp (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
NSData *data = [self->pasteboard dataForType:NSPasteboardTypeTIFF];
|
||||
NSData *data = [self->pasteboard dataForType:PTYPE(TIFF)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/png") == 0)
|
||||
{
|
||||
NSData *data = [self->pasteboard dataForType:NSPasteboardTypePNG];
|
||||
NSData *data = [self->pasteboard dataForType:PTYPE(PNG)];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacoskeymap-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
#include "gdkmacosseat-private.h"
|
||||
|
||||
#define GDK_MOD2_MASK (1 << 4)
|
||||
#define GRIP_WIDTH 15
|
||||
@@ -205,6 +206,9 @@ fill_button_event (GdkMacosDisplay *display,
|
||||
GdkSeat *seat;
|
||||
GdkEventType type;
|
||||
GdkModifierType state;
|
||||
GdkDevice *pointer = NULL;
|
||||
GdkDeviceTool *tool = NULL;
|
||||
double *axes = NULL;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DISPLAY (display));
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
@@ -241,16 +245,22 @@ fill_button_event (GdkMacosDisplay *display,
|
||||
y < 0 || y > GDK_SURFACE (surface)->height))
|
||||
return NULL;
|
||||
|
||||
if (([nsevent subtype] == NSEventSubtypeTabletPoint) &&
|
||||
_gdk_macos_seat_get_tablet (GDK_MACOS_SEAT (seat), &pointer, &tool))
|
||||
axes = _gdk_macos_seat_get_tablet_axes_from_nsevent (GDK_MACOS_SEAT (seat), nsevent);
|
||||
else
|
||||
pointer = gdk_seat_get_pointer (seat);
|
||||
|
||||
return gdk_button_event_new (type,
|
||||
GDK_SURFACE (surface),
|
||||
gdk_seat_get_pointer (seat),
|
||||
NULL,
|
||||
pointer,
|
||||
tool,
|
||||
get_time_from_ns_event (nsevent),
|
||||
state,
|
||||
get_mouse_button_from_ns_event (nsevent),
|
||||
x,
|
||||
y,
|
||||
NULL);
|
||||
axes);
|
||||
}
|
||||
|
||||
static GdkEvent *
|
||||
@@ -557,6 +567,9 @@ fill_motion_event (GdkMacosDisplay *display,
|
||||
{
|
||||
GdkSeat *seat;
|
||||
GdkModifierType state;
|
||||
GdkDevice *pointer = NULL;
|
||||
GdkDeviceTool *tool = NULL;
|
||||
double *axes = NULL;
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
g_assert (nsevent != NULL);
|
||||
@@ -566,14 +579,20 @@ fill_motion_event (GdkMacosDisplay *display,
|
||||
state = get_keyboard_modifiers_from_ns_event (nsevent) |
|
||||
_gdk_macos_display_get_current_mouse_modifiers (display);
|
||||
|
||||
if (([nsevent subtype] == NSEventSubtypeTabletPoint) &&
|
||||
_gdk_macos_seat_get_tablet (GDK_MACOS_SEAT (seat), &pointer, &tool))
|
||||
axes = _gdk_macos_seat_get_tablet_axes_from_nsevent (GDK_MACOS_SEAT (seat), nsevent);
|
||||
else
|
||||
pointer = gdk_seat_get_pointer (seat);
|
||||
|
||||
return gdk_motion_event_new (GDK_SURFACE (surface),
|
||||
gdk_seat_get_pointer (seat),
|
||||
NULL,
|
||||
pointer,
|
||||
tool,
|
||||
get_time_from_ns_event (nsevent),
|
||||
state,
|
||||
x,
|
||||
y,
|
||||
NULL);
|
||||
axes);
|
||||
}
|
||||
|
||||
static GdkEvent *
|
||||
@@ -700,7 +719,7 @@ get_surface_point_from_screen_point (GdkSurface *surface,
|
||||
NSPoint point;
|
||||
|
||||
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
|
||||
point = [nswindow convertPointFromScreen:screen_point];
|
||||
point = convert_nspoint_from_screen (nswindow, screen_point);
|
||||
|
||||
*x = point.x;
|
||||
*y = surface->height - point.y;
|
||||
@@ -762,7 +781,7 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
||||
GdkSurface *surface = NULL;
|
||||
NSWindow *nswindow = [nsevent window];
|
||||
|
||||
if (nswindow)
|
||||
if (GDK_IS_MACOS_WINDOW (nswindow))
|
||||
{
|
||||
GdkMacosBaseView *view;
|
||||
NSPoint point, view_point;
|
||||
@@ -821,7 +840,7 @@ get_surface_from_ns_event (GdkMacosDisplay *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
*screen_point = [(GdkMacosWindow *)[nsevent window] convertPointToScreen:point];
|
||||
*screen_point = convert_nspoint_to_screen ([nsevent window], point);
|
||||
*x = point.x;
|
||||
*y = surface->height - point.y;
|
||||
}
|
||||
@@ -974,11 +993,11 @@ find_surface_for_ns_event (GdkMacosDisplay *self,
|
||||
g_assert (x != NULL);
|
||||
g_assert (y != NULL);
|
||||
|
||||
view = (GdkMacosBaseView *)[[nsevent window] contentView];
|
||||
|
||||
if (!(surface = get_surface_from_ns_event (self, nsevent, &point, x, y)))
|
||||
return NULL;
|
||||
|
||||
view = (GdkMacosBaseView *)[GDK_MACOS_SURFACE (surface)->window contentView];
|
||||
|
||||
_gdk_macos_display_from_display_coords (self, point.x, point.y, &x_tmp, &y_tmp);
|
||||
|
||||
switch ((int)[nsevent type])
|
||||
@@ -1051,6 +1070,23 @@ _gdk_macos_display_translate (GdkMacosDisplay *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We need to register the proximity event from any point on the screen
|
||||
* to properly register the devices
|
||||
* FIXME: is there a better way to detect if a tablet has been plugged?
|
||||
*/
|
||||
if (event_type == NSEventTypeTabletProximity)
|
||||
{
|
||||
GdkSeat *seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
|
||||
|
||||
_gdk_macos_seat_handle_tablet_tool_event (GDK_MACOS_SEAT (seat), nsevent);
|
||||
|
||||
/* FIXME: we might want to cache this proximity event and propagate it
|
||||
* but proximity events in gdk work at a window level while on macos
|
||||
* works at a screen level. For now we just skip them.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -547,6 +547,20 @@ _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
|
||||
_gdk_macos_display_clear_sorting (self);
|
||||
}
|
||||
|
||||
/* Raises a transient window.
|
||||
*/
|
||||
static void
|
||||
raise_transient (GdkMacosSurface *surface)
|
||||
{
|
||||
GdkMacosSurface *parent_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
|
||||
|
||||
NSWindow *parent = _gdk_macos_surface_get_native (parent_surface);
|
||||
NSWindow *window = _gdk_macos_surface_get_native (surface);
|
||||
|
||||
[parent removeChildWindow:window];
|
||||
[parent addChildWindow:window ordered:NSWindowAbove];
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface)
|
||||
@@ -559,6 +573,9 @@ _gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
|
||||
|
||||
g_queue_push_head_link (&self->main_surfaces, &surface->main);
|
||||
|
||||
if (GDK_SURFACE (surface)->transient_for)
|
||||
raise_transient (surface);
|
||||
|
||||
_gdk_macos_display_clear_sorting (self);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ GetSubpixelLayout (CGDirectDisplayID screen_id)
|
||||
static char *
|
||||
GetLocalizedName (NSScreen *screen)
|
||||
{
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
NSString *str;
|
||||
@@ -158,6 +159,9 @@ GetLocalizedName (NSScreen *screen)
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
return g_steal_pointer (&name);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacosseat.h"
|
||||
|
||||
#include "gdkseatprivate.h"
|
||||
|
||||
@@ -30,6 +31,16 @@ G_BEGIN_DECLS
|
||||
|
||||
GdkSeat *_gdk_macos_seat_new (GdkMacosDisplay *display);
|
||||
|
||||
void _gdk_macos_seat_handle_tablet_tool_event (GdkMacosSeat *seat,
|
||||
NSEvent *nsevent);
|
||||
|
||||
gboolean _gdk_macos_seat_get_tablet (GdkMacosSeat *seat,
|
||||
GdkDevice **device,
|
||||
GdkDeviceTool **tool);
|
||||
|
||||
double *_gdk_macos_seat_get_tablet_axes_from_nsevent (GdkMacosSeat *seat,
|
||||
NSEvent *nsevent);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_SEAT_PRIVATE_H__ */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2021 Amazon.com, Inc. and its affiliates. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -22,42 +23,605 @@
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkseatdefaultprivate.h"
|
||||
#include "gdkdevicetoolprivate.h"
|
||||
|
||||
#include "gdkmacosdevice.h"
|
||||
#include "gdkmacosseat-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NSUInteger device_id;
|
||||
char *name;
|
||||
|
||||
GdkDevice *logical_device;
|
||||
GdkDevice *stylus_device;
|
||||
GdkSeat *seat;
|
||||
|
||||
GdkDeviceTool *current_tool;
|
||||
|
||||
int axis_indices[GDK_AXIS_LAST];
|
||||
double axes[GDK_AXIS_LAST];
|
||||
} GdkMacosTabletData;
|
||||
|
||||
struct _GdkMacosSeat
|
||||
{
|
||||
GdkSeat parent_instance;
|
||||
|
||||
GdkMacosDisplay *display;
|
||||
|
||||
GdkDevice *logical_pointer;
|
||||
GdkDevice *logical_keyboard;
|
||||
|
||||
GdkMacosTabletData *current_tablet;
|
||||
GPtrArray *tablets;
|
||||
GPtrArray *tools;
|
||||
};
|
||||
|
||||
struct _GdkMacosSeatClass
|
||||
{
|
||||
GdkSeatClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosSeat, gdk_macos_seat, GDK_TYPE_SEAT)
|
||||
|
||||
#define KEYBOARD_EVENTS (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | \
|
||||
GDK_FOCUS_CHANGE_MASK)
|
||||
#define TOUCH_EVENTS (GDK_TOUCH_MASK)
|
||||
#define POINTER_EVENTS (GDK_POINTER_MOTION_MASK | \
|
||||
GDK_BUTTON_PRESS_MASK | \
|
||||
GDK_BUTTON_RELEASE_MASK | \
|
||||
GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK | \
|
||||
GDK_ENTER_NOTIFY_MASK | \
|
||||
GDK_LEAVE_NOTIFY_MASK | \
|
||||
GDK_PROXIMITY_IN_MASK | \
|
||||
GDK_PROXIMITY_OUT_MASK)
|
||||
|
||||
static void
|
||||
gdk_macos_tablet_data_free (gpointer user_data)
|
||||
{
|
||||
GdkMacosTabletData *tablet = user_data;
|
||||
|
||||
gdk_seat_device_removed (GDK_SEAT (tablet->seat), tablet->stylus_device);
|
||||
gdk_seat_device_removed (GDK_SEAT (tablet->seat), tablet->logical_device);
|
||||
|
||||
_gdk_device_set_associated_device (tablet->logical_device, NULL);
|
||||
_gdk_device_set_associated_device (tablet->stylus_device, NULL);
|
||||
|
||||
g_object_unref (tablet->logical_device);
|
||||
g_object_unref (tablet->stylus_device);
|
||||
|
||||
g_free (tablet->name);
|
||||
g_free (tablet);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_seat_dispose (GObject *object)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (object);
|
||||
|
||||
if (self->logical_pointer)
|
||||
{
|
||||
gdk_seat_device_removed (GDK_SEAT (self), self->logical_pointer);
|
||||
g_clear_object (&self->logical_pointer);
|
||||
}
|
||||
|
||||
if (self->logical_keyboard)
|
||||
{
|
||||
gdk_seat_device_removed (GDK_SEAT (self), self->logical_keyboard);
|
||||
g_clear_object (&self->logical_pointer);
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->tablets, g_ptr_array_unref);
|
||||
g_clear_pointer (&self->tools, g_ptr_array_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_macos_seat_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static GdkSeatCapabilities
|
||||
gdk_macos_seat_get_capabilities (GdkSeat *seat)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
GdkSeatCapabilities caps = 0;
|
||||
|
||||
if (self->logical_pointer)
|
||||
caps |= GDK_SEAT_CAPABILITY_POINTER;
|
||||
if (self->logical_keyboard)
|
||||
caps |= GDK_SEAT_CAPABILITY_KEYBOARD;
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static GdkGrabStatus
|
||||
gdk_macos_seat_grab (GdkSeat *seat,
|
||||
GdkSurface *surface,
|
||||
GdkSeatCapabilities capabilities,
|
||||
gboolean owner_events,
|
||||
GdkCursor *cursor,
|
||||
GdkEvent *event,
|
||||
GdkSeatGrabPrepareFunc prepare_func,
|
||||
gpointer prepare_func_data)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
guint32 evtime = event ? gdk_event_get_time (event) : GDK_CURRENT_TIME;
|
||||
GdkGrabStatus status = GDK_GRAB_SUCCESS;
|
||||
gboolean was_visible;
|
||||
|
||||
was_visible = gdk_surface_get_mapped (surface);
|
||||
|
||||
if (prepare_func)
|
||||
(prepare_func) (seat, surface, prepare_func_data);
|
||||
|
||||
if (!gdk_surface_get_mapped (surface))
|
||||
{
|
||||
g_critical ("Surface %p has not been mapped in GdkSeatGrabPrepareFunc",
|
||||
surface);
|
||||
return GDK_GRAB_NOT_VIEWABLE;
|
||||
}
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if (capabilities & GDK_SEAT_CAPABILITY_ALL_POINTING)
|
||||
{
|
||||
/* ALL_POINTING spans 3 capabilities; get the mask for the ones we have */
|
||||
GdkEventMask pointer_evmask = 0;
|
||||
|
||||
/* We let tablet styli take over the pointer cursor */
|
||||
if (capabilities & (GDK_SEAT_CAPABILITY_POINTER |
|
||||
GDK_SEAT_CAPABILITY_TABLET_STYLUS))
|
||||
{
|
||||
pointer_evmask |= POINTER_EVENTS;
|
||||
}
|
||||
|
||||
if (capabilities & GDK_SEAT_CAPABILITY_TOUCH)
|
||||
pointer_evmask |= TOUCH_EVENTS;
|
||||
|
||||
status = gdk_device_grab (self->logical_pointer, surface,
|
||||
owner_events,
|
||||
pointer_evmask, cursor,
|
||||
evtime);
|
||||
}
|
||||
|
||||
if (status == GDK_GRAB_SUCCESS &&
|
||||
capabilities & GDK_SEAT_CAPABILITY_KEYBOARD)
|
||||
{
|
||||
status = gdk_device_grab (self->logical_keyboard, surface,
|
||||
owner_events,
|
||||
KEYBOARD_EVENTS, cursor,
|
||||
evtime);
|
||||
|
||||
if (status != GDK_GRAB_SUCCESS)
|
||||
{
|
||||
if (capabilities & ~GDK_SEAT_CAPABILITY_KEYBOARD)
|
||||
gdk_device_ungrab (self->logical_pointer, evtime);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != GDK_GRAB_SUCCESS && !was_visible)
|
||||
gdk_surface_hide (surface);
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_seat_ungrab (GdkSeat *seat)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
gdk_device_ungrab (self->logical_pointer, GDK_CURRENT_TIME);
|
||||
gdk_device_ungrab (self->logical_keyboard, GDK_CURRENT_TIME);
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
}
|
||||
|
||||
static GdkDevice *
|
||||
gdk_macos_seat_get_logical_device (GdkSeat *seat,
|
||||
GdkSeatCapabilities capability)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
|
||||
/* There must be only one flag set */
|
||||
switch ((guint) capability)
|
||||
{
|
||||
case GDK_SEAT_CAPABILITY_POINTER:
|
||||
case GDK_SEAT_CAPABILITY_TOUCH:
|
||||
return self->logical_pointer;
|
||||
case GDK_SEAT_CAPABILITY_KEYBOARD:
|
||||
return self->logical_keyboard;
|
||||
default:
|
||||
g_warning ("Unhandled capability %x", capability);
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GList *
|
||||
gdk_macos_seat_get_devices (GdkSeat *seat,
|
||||
GdkSeatCapabilities capabilities)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
GList *physical_devices = NULL;
|
||||
|
||||
if (self->logical_pointer && (capabilities & GDK_SEAT_CAPABILITY_POINTER))
|
||||
physical_devices = g_list_prepend (physical_devices, self->logical_pointer);
|
||||
|
||||
if (self->logical_keyboard && (capabilities & GDK_SEAT_CAPABILITY_KEYBOARD))
|
||||
physical_devices = g_list_prepend (physical_devices, self->logical_keyboard);
|
||||
|
||||
if (capabilities & GDK_SEAT_CAPABILITY_TABLET_STYLUS)
|
||||
{
|
||||
for (guint i = 0; i < self->tablets->len; i++)
|
||||
{
|
||||
GdkMacosTabletData *tablet = g_ptr_array_index (self->tablets, i);
|
||||
|
||||
physical_devices = g_list_prepend (physical_devices, tablet->stylus_device);
|
||||
}
|
||||
}
|
||||
|
||||
return physical_devices;
|
||||
}
|
||||
|
||||
static GList *
|
||||
gdk_macos_seat_get_tools (GdkSeat *seat)
|
||||
{
|
||||
GdkMacosSeat *self = GDK_MACOS_SEAT (seat);
|
||||
GdkDeviceTool *tool;
|
||||
GList *tools = NULL;
|
||||
|
||||
for (guint i = 0; i < self->tools->len; i++)
|
||||
{
|
||||
tool = g_ptr_array_index (self->tools, i);
|
||||
tools = g_list_prepend (tools, tool);
|
||||
}
|
||||
|
||||
return tools;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_seat_class_init (GdkMacosSeatClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkSeatClass *seat_class = GDK_SEAT_CLASS (klass);
|
||||
|
||||
object_class->dispose = gdk_macos_seat_dispose;
|
||||
|
||||
seat_class->get_capabilities = gdk_macos_seat_get_capabilities;
|
||||
seat_class->grab = gdk_macos_seat_grab;
|
||||
seat_class->ungrab = gdk_macos_seat_ungrab;
|
||||
seat_class->get_logical_device = gdk_macos_seat_get_logical_device;
|
||||
seat_class->get_devices = gdk_macos_seat_get_devices;
|
||||
seat_class->get_tools = gdk_macos_seat_get_tools;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_seat_init (GdkMacosSeat *self)
|
||||
{
|
||||
self->tablets = g_ptr_array_new_with_free_func (gdk_macos_tablet_data_free);
|
||||
self->tools = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
init_devices (GdkMacosSeat *self)
|
||||
{
|
||||
/* pointer */
|
||||
self->logical_pointer = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", "Core Pointer",
|
||||
"source", GDK_SOURCE_MOUSE,
|
||||
"has-cursor", TRUE,
|
||||
"display", self->display,
|
||||
"seat", self,
|
||||
NULL);
|
||||
|
||||
/* keyboard */
|
||||
self->logical_keyboard = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", "Core Keyboard",
|
||||
"source", GDK_SOURCE_KEYBOARD,
|
||||
"has-cursor", FALSE,
|
||||
"display", self->display,
|
||||
"seat", self,
|
||||
NULL);
|
||||
|
||||
/* link both */
|
||||
_gdk_device_set_associated_device (self->logical_pointer, self->logical_keyboard);
|
||||
_gdk_device_set_associated_device (self->logical_keyboard, self->logical_pointer);
|
||||
|
||||
gdk_seat_device_added (GDK_SEAT (self), self->logical_pointer);
|
||||
gdk_seat_device_added (GDK_SEAT (self), self->logical_keyboard);
|
||||
}
|
||||
|
||||
GdkSeat *
|
||||
_gdk_macos_seat_new (GdkMacosDisplay *display)
|
||||
{
|
||||
GdkDevice *core_keyboard;
|
||||
GdkDevice *core_pointer;
|
||||
GdkSeat *seat;
|
||||
GdkMacosSeat *self;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
|
||||
|
||||
core_pointer = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", "Core Pointer",
|
||||
"source", GDK_SOURCE_MOUSE,
|
||||
"has-cursor", TRUE,
|
||||
"display", display,
|
||||
NULL);
|
||||
core_keyboard = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", "Core Keyboard",
|
||||
"source", GDK_SOURCE_KEYBOARD,
|
||||
self = g_object_new (GDK_TYPE_MACOS_SEAT,
|
||||
"display", display,
|
||||
NULL);
|
||||
|
||||
self->display = display;
|
||||
|
||||
init_devices (self);
|
||||
|
||||
return g_steal_pointer (&self);
|
||||
}
|
||||
|
||||
static GdkDeviceToolType
|
||||
get_device_tool_type_from_nsevent (NSEvent *nsevent)
|
||||
{
|
||||
GdkDeviceToolType tool_type;
|
||||
|
||||
switch ([nsevent pointingDeviceType])
|
||||
{
|
||||
case NSPointingDeviceTypePen:
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_PEN;
|
||||
break;
|
||||
case NSPointingDeviceTypeEraser:
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_ERASER;
|
||||
break;
|
||||
case NSPointingDeviceTypeCursor:
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_MOUSE;
|
||||
break;
|
||||
case NSPointingDeviceTypeUnknown:
|
||||
default:
|
||||
tool_type = GDK_DEVICE_TOOL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
return tool_type;
|
||||
}
|
||||
|
||||
static GdkAxisFlags
|
||||
get_device_tool_axes_from_nsevent (NSEvent *nsevent)
|
||||
{
|
||||
/* TODO: do we need to be smarter about the capabilities? */
|
||||
return GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT | GDK_AXIS_FLAG_PRESSURE |
|
||||
GDK_AXIS_FLAG_ROTATION;
|
||||
}
|
||||
|
||||
static GdkMacosTabletData *
|
||||
create_tablet_data_from_nsevent (GdkMacosSeat *self,
|
||||
NSEvent *nsevent)
|
||||
{
|
||||
GdkMacosTabletData *tablet;
|
||||
GdkDisplay *display = gdk_seat_get_display (GDK_SEAT (self));
|
||||
GdkDevice *logical_device, *stylus_device;
|
||||
char *logical_name;
|
||||
char *vid, *pid;
|
||||
|
||||
tablet = g_new0 (GdkMacosTabletData, 1);
|
||||
tablet->seat = GDK_SEAT (self);
|
||||
tablet->device_id = [nsevent deviceID];
|
||||
/* FIXME: find a better name */
|
||||
tablet->name = g_strdup_printf ("Tablet %lu", [nsevent deviceID]);
|
||||
|
||||
vid = g_strdup_printf ("%.4lx", [nsevent vendorID]);
|
||||
pid = g_strdup_printf ("%.4lx", [nsevent tabletID]);
|
||||
|
||||
logical_name = g_strdup_printf ("Logical pointer for %s", tablet->name);
|
||||
logical_device = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", logical_name,
|
||||
"source", GDK_SOURCE_MOUSE,
|
||||
"has-cursor", TRUE,
|
||||
"display", display,
|
||||
"seat", self,
|
||||
NULL);
|
||||
|
||||
stylus_device = g_object_new (GDK_TYPE_MACOS_DEVICE,
|
||||
"name", tablet->name,
|
||||
"source", GDK_SOURCE_PEN,
|
||||
"has-cursor", FALSE,
|
||||
"display", display,
|
||||
"seat", self,
|
||||
"vendor-id", vid,
|
||||
"product-id", pid,
|
||||
NULL);
|
||||
|
||||
_gdk_device_set_associated_device (GDK_DEVICE (core_pointer),
|
||||
GDK_DEVICE (core_keyboard));
|
||||
_gdk_device_set_associated_device (GDK_DEVICE (core_keyboard),
|
||||
GDK_DEVICE (core_pointer));
|
||||
tablet->logical_device = logical_device;
|
||||
tablet->stylus_device = stylus_device;
|
||||
|
||||
seat = gdk_seat_default_new_for_logical_pair (core_pointer, core_keyboard);
|
||||
_gdk_device_set_associated_device (logical_device, self->logical_keyboard);
|
||||
_gdk_device_set_associated_device (stylus_device, logical_device);
|
||||
|
||||
g_object_unref (core_pointer);
|
||||
g_object_unref (core_keyboard);
|
||||
gdk_seat_device_added (GDK_SEAT (self), logical_device);
|
||||
gdk_seat_device_added (GDK_SEAT (self), stylus_device);
|
||||
|
||||
return g_steal_pointer (&seat);
|
||||
g_free (logical_name);
|
||||
g_free (vid);
|
||||
g_free (pid);
|
||||
|
||||
return tablet;
|
||||
}
|
||||
|
||||
static GdkMacosTabletData *
|
||||
get_tablet_data_from_nsevent (GdkMacosSeat *self,
|
||||
NSEvent *nsevent)
|
||||
{
|
||||
GdkMacosTabletData *tablet = NULL;
|
||||
|
||||
for (guint i = 0; i < self->tablets->len; i++)
|
||||
{
|
||||
GdkMacosTabletData *t = g_ptr_array_index (self->tablets, i);
|
||||
|
||||
if (t->device_id == [nsevent deviceID])
|
||||
{
|
||||
tablet = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!tablet)
|
||||
tablet = create_tablet_data_from_nsevent (self, nsevent);
|
||||
|
||||
return tablet;
|
||||
}
|
||||
|
||||
static void
|
||||
device_tablet_clone_tool_axes (GdkMacosTabletData *tablet,
|
||||
GdkDeviceTool *tool)
|
||||
{
|
||||
int axis_pos;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (tablet->stylus_device));
|
||||
_gdk_device_reset_axes (tablet->stylus_device);
|
||||
|
||||
_gdk_device_add_axis (tablet->stylus_device, GDK_AXIS_X, 0, 0, 0);
|
||||
_gdk_device_add_axis (tablet->stylus_device, GDK_AXIS_Y, 0, 0, 0);
|
||||
|
||||
if (tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT))
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||||
GDK_AXIS_XTILT, -1.0, 1.0, 0);
|
||||
tablet->axis_indices[GDK_AXIS_XTILT] = axis_pos;
|
||||
|
||||
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||||
GDK_AXIS_YTILT, -1.0, 1.0, 0);
|
||||
tablet->axis_indices[GDK_AXIS_YTILT] = axis_pos;
|
||||
}
|
||||
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_PRESSURE)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||||
GDK_AXIS_PRESSURE, 0.0, 1.0, 0);
|
||||
tablet->axis_indices[GDK_AXIS_PRESSURE] = axis_pos;
|
||||
}
|
||||
|
||||
if (tool->tool_axes & GDK_AXIS_FLAG_ROTATION)
|
||||
{
|
||||
axis_pos = _gdk_device_add_axis (tablet->stylus_device,
|
||||
GDK_AXIS_ROTATION, 0.0, 1.0, 0);
|
||||
tablet->axis_indices[GDK_AXIS_ROTATION] = axis_pos;
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (tablet->stylus_device));
|
||||
}
|
||||
|
||||
static void
|
||||
mimic_device_axes (GdkDevice *logical,
|
||||
GdkDevice *physical)
|
||||
{
|
||||
double axis_min, axis_max, axis_resolution;
|
||||
GdkAxisUse axis_use;
|
||||
int axis_count;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (logical));
|
||||
_gdk_device_reset_axes (logical);
|
||||
axis_count = gdk_device_get_n_axes (physical);
|
||||
|
||||
for (int i = 0; i < axis_count; i++)
|
||||
{
|
||||
_gdk_device_get_axis_info (physical, i, &axis_use, &axis_min,
|
||||
&axis_max, &axis_resolution);
|
||||
_gdk_device_add_axis (logical, axis_use, axis_min,
|
||||
axis_max, axis_resolution);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (logical));
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_seat_handle_tablet_tool_event (GdkMacosSeat *seat,
|
||||
NSEvent *nsevent)
|
||||
{
|
||||
GdkDeviceToolType tool_type;
|
||||
GdkMacosTabletData *tablet;
|
||||
GdkDeviceTool *tool;
|
||||
|
||||
g_return_if_fail (GDK_IS_MACOS_SEAT (seat));
|
||||
g_return_if_fail (nsevent != NULL);
|
||||
|
||||
tablet = get_tablet_data_from_nsevent (seat, nsevent);
|
||||
|
||||
tool_type = get_device_tool_type_from_nsevent (nsevent);
|
||||
|
||||
if (tool_type == GDK_DEVICE_TOOL_TYPE_UNKNOWN)
|
||||
{
|
||||
g_warning ("Unknown device tool detected");
|
||||
return;
|
||||
}
|
||||
|
||||
tool = gdk_seat_get_tool (GDK_SEAT (seat), [nsevent tabletID], [nsevent deviceID], tool_type);
|
||||
|
||||
if ([nsevent isEnteringProximity])
|
||||
{
|
||||
if (!tool)
|
||||
{
|
||||
tool = gdk_device_tool_new ([nsevent tabletID], [nsevent vendorID], tool_type,
|
||||
get_device_tool_axes_from_nsevent (nsevent));
|
||||
g_ptr_array_add (seat->tools, tool);
|
||||
}
|
||||
|
||||
gdk_device_update_tool (tablet->stylus_device, tool);
|
||||
tablet->current_tool = tool;
|
||||
device_tablet_clone_tool_axes (tablet, tool);
|
||||
mimic_device_axes (tablet->logical_device, tablet->stylus_device);
|
||||
seat->current_tablet = tablet;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_device_update_tool (tablet->stylus_device, NULL);
|
||||
tablet->current_tool = NULL;
|
||||
seat->current_tablet = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_macos_seat_get_tablet (GdkMacosSeat *seat,
|
||||
GdkDevice **logical_device,
|
||||
GdkDeviceTool **tool)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_MACOS_SEAT (seat), FALSE);
|
||||
|
||||
if (!seat->current_tablet)
|
||||
return FALSE;
|
||||
|
||||
*logical_device = seat->current_tablet->logical_device;
|
||||
*tool = seat->current_tablet->current_tool;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
double *
|
||||
_gdk_macos_seat_get_tablet_axes_from_nsevent (GdkMacosSeat *seat,
|
||||
NSEvent *nsevent)
|
||||
{
|
||||
GdkMacosTabletData *tablet;
|
||||
int axis_index;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_SEAT (seat), NULL);
|
||||
g_return_val_if_fail (nsevent != NULL, NULL);
|
||||
|
||||
tablet = seat->current_tablet;
|
||||
if (!tablet || !tablet->current_tool)
|
||||
return NULL;
|
||||
|
||||
if (tablet->current_tool->tool_axes & (GDK_AXIS_FLAG_XTILT | GDK_AXIS_FLAG_YTILT))
|
||||
{
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
[nsevent tilt].x, &tablet->axes[GDK_AXIS_XTILT]);
|
||||
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
[nsevent tilt].y, &tablet->axes[GDK_AXIS_YTILT]);
|
||||
}
|
||||
|
||||
if (tablet->current_tool->tool_axes & GDK_AXIS_FLAG_PRESSURE)
|
||||
{
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
[nsevent pressure], &tablet->axes[GDK_AXIS_PRESSURE]);
|
||||
}
|
||||
|
||||
if (tablet->current_tool->tool_axes & GDK_AXIS_FLAG_ROTATION)
|
||||
{
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
[nsevent rotation], &tablet->axes[GDK_AXIS_ROTATION]);
|
||||
}
|
||||
|
||||
return g_memdup (tablet->axes,
|
||||
sizeof (double) * GDK_AXIS_LAST);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright © 2021 Amazon.com, Inc. and its affiliates. All Rights Reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_MACOS_SEAT (gdk_macos_seat_get_type ())
|
||||
#define GDK_MACOS_SEAT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MACOS_SEAT, GdkMacosSeat))
|
||||
#define GDK_IS_MACOS_SEAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MACOS_SEAT))
|
||||
|
||||
typedef struct _GdkMacosSeat GdkMacosSeat;
|
||||
typedef struct _GdkMacosSeatClass GdkMacosSeatClass;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_macos_seat_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
@@ -61,6 +61,7 @@ struct _GdkMacosSurface
|
||||
gint64 pending_frame_counter;
|
||||
|
||||
guint did_initial_present : 1;
|
||||
guint geometry_dirty : 1;
|
||||
};
|
||||
|
||||
struct _GdkMacosSurfaceClass
|
||||
|
||||
@@ -150,6 +150,12 @@ _gdk_macos_surface_set_shadow (GdkMacosSurface *surface,
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (self));
|
||||
|
||||
if (self->shadow_top == top &&
|
||||
self->shadow_right == right &&
|
||||
self->shadow_bottom == bottom &&
|
||||
self->shadow_left == left)
|
||||
return;
|
||||
|
||||
self->shadow_top = top;
|
||||
self->shadow_right = right;
|
||||
self->shadow_bottom = bottom;
|
||||
|
||||
@@ -81,7 +81,7 @@ _gdk_macos_toplevel_surface_unmaximize (GdkMacosToplevelSurface *self)
|
||||
[window zoom:window];
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
GdkToplevelLayout *layout)
|
||||
{
|
||||
@@ -107,6 +107,7 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
style_mask = [nswindow styleMask];
|
||||
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
|
||||
if (monitor)
|
||||
{
|
||||
GdkRectangle workarea;
|
||||
@@ -158,13 +159,11 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
[nswindow setStyleMask:style_mask];
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
{
|
||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (surface),
|
||||
size.shadow.top,
|
||||
size.shadow.right,
|
||||
size.shadow.bottom,
|
||||
size.shadow.left);
|
||||
}
|
||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (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);
|
||||
@@ -230,8 +229,6 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
|
||||
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self));
|
||||
|
||||
GDK_MACOS_SURFACE (self)->did_initial_present = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -373,6 +370,87 @@ _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;
|
||||
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
|
||||
GdkToplevelSize size;
|
||||
GdkDisplay *display;
|
||||
GdkMonitor *monitor;
|
||||
int bounds_width, bounds_height;
|
||||
int width, height;
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
NSWindowStyleMask style_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);
|
||||
style_mask = [nswindow styleMask];
|
||||
|
||||
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);
|
||||
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
|
||||
if (style_mask & NSWindowStyleMaskResizable)
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
mask = GDK_HINT_MIN_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.max_width = geometry.min_width = width;
|
||||
geometry.max_height = geometry.min_height = height;
|
||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||
}
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
_gdk_macos_surface_set_shadow (GDK_MACOS_SURFACE (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_resize (GDK_MACOS_SURFACE (self), width, height);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_request_layout (GdkSurface *surface)
|
||||
{
|
||||
GDK_MACOS_SURFACE (surface)->geometry_dirty = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_toplevel_surface_destroy (GdkSurface *surface,
|
||||
gboolean foreign_destroy)
|
||||
@@ -506,6 +584,8 @@ _gdk_macos_toplevel_surface_class_init (GdkMacosToplevelSurfaceClass *klass)
|
||||
|
||||
surface_class->destroy = _gdk_macos_toplevel_surface_destroy;
|
||||
surface_class->hide = _gdk_macos_toplevel_surface_hide;
|
||||
surface_class->compute_size = _gdk_macos_toplevel_surface_compute_size;
|
||||
surface_class->request_layout = _gdk_macos_toplevel_surface_request_layout;
|
||||
|
||||
gdk_toplevel_install_properties (object_class, LAST_PROP);
|
||||
}
|
||||
|
||||
@@ -40,5 +40,36 @@ struct _GdkPoint
|
||||
};
|
||||
typedef struct _GdkPoint GdkPoint;
|
||||
|
||||
static inline NSPoint
|
||||
convert_nspoint_from_screen (NSWindow *window,
|
||||
NSPoint point)
|
||||
{
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER
|
||||
return [window convertPointFromScreen:point];
|
||||
#else
|
||||
/* Apple documentation claims that convertPointFromScreen is available
|
||||
* on 10.12+. However, that doesn't seem to be the case when using it.
|
||||
* Instead, we'll just use it on modern 10.15 systems and fallback to
|
||||
* converting using rects on older systems.
|
||||
*/
|
||||
return [window convertRectFromScreen:NSMakeRect (point.x, point.y, 0, 0)].origin;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline NSPoint
|
||||
convert_nspoint_to_screen (NSWindow *window,
|
||||
NSPoint point)
|
||||
{
|
||||
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_15_AND_LATER
|
||||
return [window convertPointToScreen:point];
|
||||
#else
|
||||
/* Apple documentation claims that convertPointToScreen is available
|
||||
* on 10.12+. However, that doesn't seem to be the case when using it.
|
||||
* Instead, we'll just use it on modern 10.15 systems and fallback to
|
||||
* converting using rects on older systems.
|
||||
*/
|
||||
return [window convertRectToScreen:NSMakeRect (point.x, point.y, 0, 0)].origin;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* __GDK_MACOS_UTILS_PRIVATE_H__ */
|
||||
|
||||
@@ -33,6 +33,7 @@ gdk_macos_public_headers = files([
|
||||
'gdkmacosglcontext.h',
|
||||
'gdkmacoskeymap.h',
|
||||
'gdkmacosmonitor.h',
|
||||
'gdkmacosseat.h',
|
||||
'gdkmacossurface.h',
|
||||
])
|
||||
|
||||
|
||||
@@ -2357,6 +2357,9 @@ touch_handle_down (void *data,
|
||||
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
|
||||
if (!wl_surface)
|
||||
return;
|
||||
|
||||
touch = gdk_wayland_seat_add_touch (seat, id, wl_surface);
|
||||
touch->x = wl_fixed_to_double (x);
|
||||
touch->y = wl_fixed_to_double (y);
|
||||
@@ -2404,6 +2407,9 @@ touch_handle_up (void *data,
|
||||
_gdk_wayland_display_update_serial (display, serial);
|
||||
|
||||
touch = gdk_wayland_seat_get_touch (seat, id);
|
||||
if (!touch)
|
||||
return;
|
||||
|
||||
event = gdk_touch_event_new (GDK_TOUCH_END,
|
||||
GDK_SLOT_TO_EVENT_SEQUENCE (touch->id),
|
||||
touch->surface,
|
||||
@@ -2442,6 +2448,9 @@ touch_handle_motion (void *data,
|
||||
GdkEvent *event;
|
||||
|
||||
touch = gdk_wayland_seat_get_touch (seat, id);
|
||||
if (!touch)
|
||||
return;
|
||||
|
||||
touch->x = wl_fixed_to_double (x);
|
||||
touch->y = wl_fixed_to_double (y);
|
||||
|
||||
@@ -3381,9 +3390,14 @@ tablet_tool_handle_proximity_in (void *data,
|
||||
GdkWaylandTabletData *tablet = zwp_tablet_v2_get_user_data (wp_tablet);
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
||||
GdkSurface *surface = wl_surface_get_user_data (wsurface);
|
||||
GdkSurface *surface;
|
||||
GdkEvent *event;
|
||||
|
||||
if (!wsurface)
|
||||
return;
|
||||
|
||||
surface = wl_surface_get_user_data (wsurface);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
if (!GDK_IS_SURFACE (surface))
|
||||
@@ -3427,6 +3441,9 @@ tablet_tool_handle_proximity_out (void *data,
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
GdkEvent *event;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
GDK_SEAT_NOTE (tool->seat, EVENTS,
|
||||
g_message ("proximity out, seat %p, tool %d", tool->seat,
|
||||
gdk_device_tool_get_tool_type (tool->tool)));
|
||||
@@ -3490,7 +3507,7 @@ tablet_tool_handle_down (void *data,
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tool->seat);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (seat->display);
|
||||
|
||||
if (!tablet->pointer_info.focus)
|
||||
if (!tablet || !tablet->pointer_info.focus)
|
||||
return;
|
||||
|
||||
_gdk_wayland_display_update_serial (display_wayland, serial);
|
||||
@@ -3507,7 +3524,7 @@ tablet_tool_handle_up (void *data,
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
|
||||
if (!tablet->pointer_info.focus)
|
||||
if (!tablet || !tablet->pointer_info.focus)
|
||||
return;
|
||||
|
||||
tablet_create_button_event_frame (tablet, GDK_BUTTON_RELEASE, GDK_BUTTON_PRIMARY);
|
||||
@@ -3524,6 +3541,9 @@ tablet_tool_handle_motion (void *data,
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
GdkEvent *event;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
tablet->pointer_info.surface_x = wl_fixed_to_double (sx);
|
||||
tablet->pointer_info.surface_y = wl_fixed_to_double (sy);
|
||||
|
||||
@@ -3551,7 +3571,12 @@ tablet_tool_handle_pressure (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
int axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
||||
int axis_index;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_PRESSURE];
|
||||
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
pressure, &tablet->axes[GDK_AXIS_PRESSURE]);
|
||||
@@ -3568,7 +3593,12 @@ tablet_tool_handle_distance (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
int axis_index = tablet->axis_indices[GDK_AXIS_DISTANCE];
|
||||
int axis_index;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_DISTANCE];
|
||||
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
distance, &tablet->axes[GDK_AXIS_DISTANCE]);
|
||||
@@ -3586,8 +3616,14 @@ tablet_tool_handle_tilt (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
int xtilt_axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
||||
int ytilt_axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
||||
int xtilt_axis_index;
|
||||
int ytilt_axis_index;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
xtilt_axis_index = tablet->axis_indices[GDK_AXIS_XTILT];
|
||||
ytilt_axis_index = tablet->axis_indices[GDK_AXIS_YTILT];
|
||||
|
||||
_gdk_device_translate_axis (tablet->stylus_device, xtilt_axis_index,
|
||||
wl_fixed_to_double (xtilt),
|
||||
@@ -3614,7 +3650,7 @@ tablet_tool_handle_button (void *data,
|
||||
GdkEventType evtype;
|
||||
guint n_button;
|
||||
|
||||
if (!tablet->pointer_info.focus)
|
||||
if (!tablet || !tablet->pointer_info.focus)
|
||||
return;
|
||||
|
||||
tablet->pointer_info.press_serial = serial;
|
||||
@@ -3645,7 +3681,12 @@ tablet_tool_handle_rotation (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
int axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
||||
int axis_index;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_ROTATION];
|
||||
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
wl_fixed_to_double (degrees),
|
||||
@@ -3664,7 +3705,12 @@ tablet_tool_handle_slider (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
int axis_index = tablet->axis_indices[GDK_AXIS_SLIDER];
|
||||
int axis_index;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
axis_index = tablet->axis_indices[GDK_AXIS_SLIDER];
|
||||
|
||||
_gdk_device_translate_axis (tablet->stylus_device, axis_index,
|
||||
position, &tablet->axes[GDK_AXIS_SLIDER]);
|
||||
@@ -3682,9 +3728,14 @@ tablet_tool_handle_wheel (void *data,
|
||||
{
|
||||
GdkWaylandTabletToolData *tool = data;
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
GdkWaylandSeat *seat = GDK_WAYLAND_SEAT (tablet->seat);
|
||||
GdkWaylandSeat *seat;
|
||||
GdkEvent *event;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
seat = GDK_WAYLAND_SEAT (tablet->seat);
|
||||
|
||||
GDK_SEAT_NOTE (seat, EVENTS,
|
||||
g_message ("tablet tool %d wheel %d/%d",
|
||||
gdk_device_tool_get_tool_type (tool->tool), degrees, clicks));
|
||||
@@ -3724,6 +3775,9 @@ tablet_tool_handle_frame (void *data,
|
||||
GdkWaylandTabletData *tablet = tool->current_tablet;
|
||||
GdkEvent *frame_event;
|
||||
|
||||
if (!tablet)
|
||||
return;
|
||||
|
||||
GDK_SEAT_NOTE (tablet->seat, EVENTS,
|
||||
g_message ("tablet frame, time %d", time));
|
||||
|
||||
@@ -4312,6 +4366,9 @@ pointer_surface_update_scale (GdkDevice *device)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pointer->pointer_surface_outputs)
|
||||
return;
|
||||
|
||||
scale = 1;
|
||||
for (l = pointer->pointer_surface_outputs; l != NULL; l = l->next)
|
||||
{
|
||||
@@ -4319,6 +4376,8 @@ pointer_surface_update_scale (GdkDevice *device)
|
||||
scale = MAX (scale, output_scale);
|
||||
}
|
||||
|
||||
if (pointer->current_output_scale == scale)
|
||||
return;
|
||||
pointer->current_output_scale = scale;
|
||||
|
||||
gdk_wayland_device_update_surface_cursor (device);
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
#define MIN_SYSTEM_BELL_DELAY_MS 20
|
||||
|
||||
#define GTK_SHELL1_VERSION 3
|
||||
#define GTK_SHELL1_VERSION 4
|
||||
#define OUTPUT_VERSION_WITH_DONE 2
|
||||
#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3
|
||||
|
||||
@@ -1350,21 +1350,23 @@ _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
|
||||
data->buffer = NULL;
|
||||
data->scale = scale;
|
||||
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width*scale);
|
||||
stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width * scale);
|
||||
|
||||
data->pool = create_shm_pool (display->shm,
|
||||
height*scale*stride,
|
||||
height * scale * stride,
|
||||
&data->buf_length,
|
||||
&data->buf);
|
||||
if (G_UNLIKELY (data->pool == NULL))
|
||||
g_error ("Unable to create shared memory pool");
|
||||
|
||||
surface = cairo_image_surface_create_for_data (data->buf,
|
||||
CAIRO_FORMAT_ARGB32,
|
||||
width*scale,
|
||||
height*scale,
|
||||
width * scale,
|
||||
height * scale,
|
||||
stride);
|
||||
|
||||
data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
|
||||
width*scale, height*scale,
|
||||
width * scale, height * scale,
|
||||
stride, WL_SHM_FORMAT_ARGB8888);
|
||||
|
||||
cairo_surface_set_user_data (surface, &gdk_wayland_shm_surface_cairo_key,
|
||||
@@ -1836,6 +1838,7 @@ settings_portal_changed (GDBusProxy *proxy,
|
||||
char *a = g_variant_print (value, FALSE);
|
||||
g_debug ("Using changed portal setting %s %s: %s", namespace, name, a);
|
||||
g_free (a);
|
||||
entry->valid = TRUE;
|
||||
apply_portal_setting (entry, value, display);
|
||||
gdk_display_setting_changed (display, entry->setting);
|
||||
}
|
||||
|
||||
@@ -242,14 +242,22 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
gdk_profiler_add_mark (GDK_PROFILER_CURRENT_TIME, 0, "wayland", "swap buffers");
|
||||
if (display_wayland->have_egl_swap_buffers_with_damage)
|
||||
{
|
||||
EGLint stack_rects[4 * 4]; /* 4 rects */
|
||||
EGLint *heap_rects = NULL;
|
||||
int i, j, n_rects = cairo_region_num_rectangles (painted);
|
||||
EGLint *rects = g_new (EGLint, n_rects * 4);
|
||||
cairo_rectangle_int_t rect;
|
||||
int surface_height = gdk_surface_get_height (surface);
|
||||
int scale = gdk_surface_get_scale_factor (surface);
|
||||
EGLint *rects;
|
||||
|
||||
if (n_rects < G_N_ELEMENTS (stack_rects) / 4)
|
||||
rects = (EGLint *)&stack_rects;
|
||||
else
|
||||
heap_rects = rects = g_new (EGLint, n_rects * 4);
|
||||
|
||||
for (i = 0, j = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (painted, i, &rect);
|
||||
rects[j++] = rect.x * scale;
|
||||
rects[j++] = (surface_height - rect.height - rect.y) * scale;
|
||||
@@ -257,7 +265,7 @@ gdk_wayland_gl_context_end_frame (GdkDrawContext *draw_context,
|
||||
rects[j++] = rect.height * scale;
|
||||
}
|
||||
eglSwapBuffersWithDamageEXT (display_wayland->egl_display, egl_surface, rects, n_rects);
|
||||
g_free (rects);
|
||||
g_free (heap_rects);
|
||||
}
|
||||
else
|
||||
eglSwapBuffers (display_wayland->egl_display, egl_surface);
|
||||
@@ -293,27 +301,27 @@ gdk_wayland_get_display (GdkWaylandDisplay *display_wayland)
|
||||
if (epoxy_has_egl_extension (NULL, "EGL_KHR_platform_base"))
|
||||
{
|
||||
PFNEGLGETPLATFORMDISPLAYPROC getPlatformDisplay =
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplay");
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplay");
|
||||
|
||||
if (getPlatformDisplay)
|
||||
dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
|
||||
display_wayland->wl_display,
|
||||
NULL);
|
||||
dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
|
||||
display_wayland->wl_display,
|
||||
NULL);
|
||||
if (dpy)
|
||||
return dpy;
|
||||
return dpy;
|
||||
}
|
||||
|
||||
if (epoxy_has_egl_extension (NULL, "EGL_EXT_platform_base"))
|
||||
{
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay =
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
||||
(void *) eglGetProcAddress ("eglGetPlatformDisplayEXT");
|
||||
|
||||
if (getPlatformDisplay)
|
||||
dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
|
||||
display_wayland->wl_display,
|
||||
NULL);
|
||||
dpy = getPlatformDisplay (EGL_PLATFORM_WAYLAND_EXT,
|
||||
display_wayland->wl_display,
|
||||
NULL);
|
||||
if (dpy)
|
||||
return dpy;
|
||||
return dpy;
|
||||
}
|
||||
|
||||
return eglGetDisplay ((EGLNativeDisplayType) display_wayland->wl_display);
|
||||
@@ -386,7 +394,7 @@ find_eglconfig_for_surface (GdkSurface *surface,
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
EGLint attrs[MAX_EGL_ATTRS];
|
||||
EGLint count;
|
||||
EGLConfig *configs;
|
||||
EGLConfig config;
|
||||
int i = 0;
|
||||
|
||||
attrs[i++] = EGL_SURFACE_TYPE;
|
||||
@@ -407,39 +415,26 @@ find_eglconfig_for_surface (GdkSurface *surface,
|
||||
attrs[i++] = EGL_NONE;
|
||||
g_assert (i < MAX_EGL_ATTRS);
|
||||
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, NULL, 0, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
configs = g_new (EGLConfig, count);
|
||||
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, configs, count, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Pick first valid configuration i guess? */
|
||||
if (!eglChooseConfig (display_wayland->egl_display, attrs, &config, 1, &count) || count < 1)
|
||||
{
|
||||
g_set_error_literal (error, GDK_GL_ERROR,
|
||||
GDK_GL_ERROR_UNSUPPORTED_FORMAT,
|
||||
_("No available configurations for the given pixel format"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (egl_config_out != NULL)
|
||||
*egl_config_out = configs[0];
|
||||
|
||||
g_free (configs);
|
||||
g_assert (egl_config_out);
|
||||
*egl_config_out = config;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkGLContext *
|
||||
gdk_wayland_surface_create_gl_context (GdkSurface *surface,
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
gboolean attached,
|
||||
GdkGLContext *share,
|
||||
GError **error)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
|
||||
@@ -526,10 +521,10 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay *display,
|
||||
else
|
||||
{
|
||||
if (display_wayland->have_egl_surfaceless_context)
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
egl_surface = EGL_NO_SURFACE;
|
||||
else
|
||||
egl_surface = gdk_wayland_surface_get_dummy_egl_surface (surface,
|
||||
context_wayland->egl_config);
|
||||
egl_surface = gdk_wayland_surface_get_dummy_egl_surface (surface,
|
||||
context_wayland->egl_config);
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
|
||||
|
||||
@@ -389,10 +389,13 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
|
||||
int scale)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
gboolean width_changed, height_changed, scale_changed;
|
||||
|
||||
if ((surface->width == width) &&
|
||||
(surface->height == height) &&
|
||||
(impl->scale == scale))
|
||||
width_changed = surface->width != width;
|
||||
height_changed = surface->height != height;
|
||||
scale_changed = impl->scale != scale;
|
||||
|
||||
if (!width_changed && !height_changed && !scale_changed)
|
||||
return;
|
||||
|
||||
surface->width = width;
|
||||
@@ -405,6 +408,13 @@ gdk_wayland_surface_update_size (GdkSurface *surface,
|
||||
wl_surface_set_buffer_scale (impl->display_server.wl_surface, scale);
|
||||
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
|
||||
if (width_changed)
|
||||
g_object_notify (G_OBJECT (surface), "width");
|
||||
if (height_changed)
|
||||
g_object_notify (G_OBJECT (surface), "height");
|
||||
if (scale_changed)
|
||||
g_object_notify (G_OBJECT (surface), "scale-factor");
|
||||
}
|
||||
|
||||
static const char *
|
||||
@@ -2213,6 +2223,24 @@ gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel)
|
||||
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel)
|
||||
{
|
||||
GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (GDK_SURFACE (toplevel)));
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
|
||||
|
||||
g_return_if_fail (GDK_IS_WAYLAND_TOPLEVEL (toplevel));
|
||||
|
||||
if (!display_wayland->server_decoration_manager)
|
||||
return;
|
||||
impl->display_server.server_decoration =
|
||||
org_kde_kwin_server_decoration_manager_create (display_wayland->server_decoration_manager,
|
||||
impl->display_server.wl_surface);
|
||||
if (impl->display_server.server_decoration)
|
||||
org_kde_kwin_server_decoration_request_mode (impl->display_server.server_decoration,
|
||||
ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel)
|
||||
{
|
||||
@@ -2939,7 +2967,11 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
|
||||
|
||||
if (impl->display_server.gtk_surface)
|
||||
{
|
||||
gtk_surface1_destroy (impl->display_server.gtk_surface);
|
||||
if (display_wayland->gtk_shell_version >=
|
||||
GTK_SURFACE1_RELEASE_SINCE_VERSION)
|
||||
gtk_surface1_release (impl->display_server.gtk_surface);
|
||||
else
|
||||
gtk_surface1_destroy (impl->display_server.gtk_surface);
|
||||
impl->display_server.gtk_surface = NULL;
|
||||
impl->application.was_set = FALSE;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ void gdk_wayland_toplevel_set_dbus_properties (GdkTopl
|
||||
const char *unique_bus_name);
|
||||
|
||||
void gdk_wayland_toplevel_announce_csd (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_announce_ssd (GdkToplevel *toplevel);
|
||||
|
||||
gboolean gdk_wayland_toplevel_inhibit_idle (GdkToplevel *toplevel);
|
||||
void gdk_wayland_toplevel_uninhibit_idle (GdkToplevel *toplevel);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<protocol name="gtk">
|
||||
|
||||
<interface name="gtk_shell1" version="3">
|
||||
<interface name="gtk_shell1" version="4">
|
||||
<description summary="gtk specific extensions">
|
||||
gtk_shell is a protocol extension providing additional features for
|
||||
clients implementing it.
|
||||
@@ -35,7 +35,7 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="gtk_surface1" version="3">
|
||||
<interface name="gtk_surface1" version="4">
|
||||
<request name="set_dbus_properties">
|
||||
<arg name="application_id" type="string" allow-null="true"/>
|
||||
<arg name="app_menu_path" type="string" allow-null="true"/>
|
||||
@@ -82,6 +82,9 @@
|
||||
<request name="request_focus" since="3">
|
||||
<arg name="startup_id" type="string" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<!-- Version 4 additions -->
|
||||
<request name="release" type="destructor" since="4"/>
|
||||
</interface>
|
||||
|
||||
</protocol>
|
||||
|
||||
@@ -31,46 +31,6 @@
|
||||
|
||||
G_DEFINE_TYPE (GdkWin32CairoContext, gdk_win32_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
|
||||
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_layered_window (GdkWin32Surface *impl,
|
||||
int width,
|
||||
int height,
|
||||
int scale)
|
||||
{
|
||||
if (width > impl->dib_width ||
|
||||
height > impl->dib_height)
|
||||
{
|
||||
cairo_surface_t *new_cache;
|
||||
|
||||
impl->dib_width = MAX (impl->dib_width, MAX (width, 1));
|
||||
impl->dib_height = MAX (impl->dib_height, MAX (height, 1));
|
||||
/* Create larger cache surface, copy old cache surface over it */
|
||||
new_cache = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_ARGB32,
|
||||
impl->dib_width,
|
||||
impl->dib_height);
|
||||
|
||||
if (impl->cache_surface)
|
||||
{
|
||||
cairo_t *cr = cairo_create (new_cache);
|
||||
cairo_set_source_surface (cr, impl->cache_surface, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_flush (new_cache);
|
||||
|
||||
cairo_surface_destroy (impl->cache_surface);
|
||||
}
|
||||
|
||||
impl->cache_surface = new_cache;
|
||||
|
||||
cairo_surface_set_device_scale (impl->cache_surface,
|
||||
scale,
|
||||
scale);
|
||||
}
|
||||
|
||||
return cairo_surface_reference (impl->cache_surface);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_surface (GdkSurface *surface,
|
||||
int scale)
|
||||
@@ -114,22 +74,11 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
width = MAX (width, 1);
|
||||
height = MAX (height, 1);
|
||||
|
||||
if (self->layered)
|
||||
self->window_surface = create_cairo_surface_for_layered_window (impl, width, height, scale);
|
||||
else
|
||||
self->window_surface = create_cairo_surface_for_surface (surface, scale);
|
||||
self->window_surface = create_cairo_surface_for_surface (surface, scale);
|
||||
|
||||
if (self->layered ||
|
||||
!self->double_buffered)
|
||||
{
|
||||
/* Layered windows paint on the window_surface (which is itself
|
||||
* an in-memory cache that the window maintains, since layered windows
|
||||
* do not support incremental redraws.
|
||||
* Non-double-buffered windows paint on the window surface directly
|
||||
* as well.
|
||||
*/
|
||||
self->paint_surface = cairo_surface_reference (self->window_surface);
|
||||
}
|
||||
if (!self->double_buffered)
|
||||
/* Non-double-buffered windows paint on the window surface directly */
|
||||
self->paint_surface = cairo_surface_reference (self->window_surface);
|
||||
else
|
||||
{
|
||||
if (width > self->db_width ||
|
||||
@@ -153,11 +102,10 @@ gdk_win32_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
}
|
||||
|
||||
/* Clear the paint region.
|
||||
* For non-double-buffered and for layered rendering we must
|
||||
* clear it, otherwise semi-transparent pixels will "add up"
|
||||
* with each repaint.
|
||||
* For double-buffered rendering we must clear the old pixels
|
||||
* from the DB cache surface that we're going to use as a buffer.
|
||||
* For non-double-buffered rendering we must clear it, otherwise
|
||||
* semi-transparent pixels will "add up" with each repaint.
|
||||
* We must also clear the old pixels from the DB cache surface
|
||||
* that we're going to use as a buffer.
|
||||
*/
|
||||
cr = cairo_create (self->paint_surface);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 00);
|
||||
@@ -184,12 +132,10 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
* to be here.
|
||||
*/
|
||||
|
||||
/* Layered windows have their own, special copying section
|
||||
* further down. For double-buffered windows we need to blit
|
||||
/* For double-buffered windows we need to blit
|
||||
* the DB buffer contents into the window itself.
|
||||
*/
|
||||
if (!self->layered &&
|
||||
self->double_buffered)
|
||||
if (self->double_buffered)
|
||||
{
|
||||
cairo_t *cr;
|
||||
|
||||
@@ -207,18 +153,6 @@ gdk_win32_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
|
||||
cairo_surface_flush (self->window_surface);
|
||||
|
||||
/* Update layered window, updating its contents, size and position
|
||||
* in one call.
|
||||
*/
|
||||
if (self->layered)
|
||||
{
|
||||
RECT client_rect;
|
||||
|
||||
/* Get the position/size of the window that GDK wants. */
|
||||
_gdk_win32_get_window_client_area_rect (surface, scale, &client_rect);
|
||||
_gdk_win32_update_layered_window_from_cache (surface, &client_rect, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->paint_surface, cairo_surface_destroy);
|
||||
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
|
||||
}
|
||||
|
||||
@@ -44,10 +44,6 @@ struct _GdkWin32CairoContext
|
||||
* code that is unaffected by this flag.
|
||||
*/
|
||||
guint double_buffered : 1;
|
||||
/* Re-set to the same value as GdkSurfaceImplWin32->layered
|
||||
* every frame (since layeredness can change at runtime).
|
||||
*/
|
||||
guint layered : 1;
|
||||
|
||||
/* The a surface for double-buffering. We keep it
|
||||
* around between repaints, and only re-allocate it
|
||||
@@ -56,12 +52,11 @@ struct _GdkWin32CairoContext
|
||||
int db_width;
|
||||
int db_height;
|
||||
|
||||
/* Surface for the window DC (in non-layered mode).
|
||||
* A reference of the cache surface (in layered mode). */
|
||||
/* Surface for the window DC */
|
||||
cairo_surface_t *window_surface;
|
||||
/* A reference to db_surface (when double-buffering).
|
||||
* When not using double-buffering or in layered mode
|
||||
* this is a reference to window_surface.
|
||||
* When not using double-buffering this is a reference
|
||||
* to window_surface.
|
||||
*/
|
||||
cairo_surface_t *paint_surface;
|
||||
};
|
||||
|
||||
@@ -2113,7 +2113,6 @@ gdk_drag_anim_timeout (gpointer data)
|
||||
(drag->start_y - drag->util_data.last_y) * t -
|
||||
drag->hot_y);
|
||||
gdk_win32_surface_move (drag->drag_surface, x, y);
|
||||
gdk_win32_surface_set_opacity (drag->drag_surface, 1.0 - f);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
@@ -1495,15 +1495,6 @@ handle_dpi_changed (GdkSurface *window,
|
||||
|
||||
monitor = gdk_display_get_monitor_at_surface (display, window);
|
||||
gdk_monitor_set_scale_factor (monitor, impl->surface_scale);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
/* We only need to set the cairo surface device scale here ourselves for layered windows */
|
||||
if (impl->cache_surface != NULL)
|
||||
cairo_surface_set_device_scale (impl->cache_surface,
|
||||
impl->surface_scale,
|
||||
impl->surface_scale);
|
||||
}
|
||||
}
|
||||
|
||||
_gdk_win32_adjust_client_rect (window, rect);
|
||||
@@ -1721,8 +1712,8 @@ _gdk_win32_surface_fill_min_max_info (GdkSurface *window,
|
||||
mmi->ptMaxSize.y = nearest_info.rcWork.bottom - nearest_info.rcWork.top;
|
||||
}
|
||||
|
||||
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->margins_x * impl->surface_scale;
|
||||
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->margins_y * impl->surface_scale;
|
||||
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->shadow_x * impl->surface_scale;
|
||||
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->shadow_y * impl->surface_scale;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -2354,9 +2345,7 @@ gdk_event_translate (MSG *msg,
|
||||
|
||||
|
||||
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
|
||||
{
|
||||
gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
|
||||
}
|
||||
gdk_win32_surface_do_move_resize_drag (window, current_root_x, current_root_y);
|
||||
else if (_gdk_input_ignore_core == 0)
|
||||
{
|
||||
current_x = (gint16) GET_X_LPARAM (msg->lParam) / impl->surface_scale;
|
||||
@@ -2835,6 +2824,16 @@ gdk_event_translate (MSG *msg,
|
||||
else
|
||||
unset_bits |= GDK_TOPLEVEL_STATE_MAXIMIZED;
|
||||
|
||||
/*
|
||||
* If we are minizing, pause all surface layout computations, and re-start the
|
||||
* computation once we are coming out of a minimized state
|
||||
*/
|
||||
if (!(old_state & GDK_TOPLEVEL_STATE_MINIMIZED) && set_bits & GDK_TOPLEVEL_STATE_MINIMIZED)
|
||||
gdk_surface_freeze_updates (window);
|
||||
|
||||
if (old_state & GDK_TOPLEVEL_STATE_MINIMIZED && unset_bits & GDK_TOPLEVEL_STATE_MINIMIZED)
|
||||
gdk_surface_thaw_updates (window);
|
||||
|
||||
gdk_surface_set_is_mapped (window, !!IsWindowVisible (msg->hwnd));
|
||||
gdk_synthesize_surface_state (window, unset_bits, set_bits);
|
||||
|
||||
|
||||
@@ -88,19 +88,6 @@ _gdk_win32_gl_context_dispose (GObject *gobject)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (surface != NULL)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
if (impl->suppress_layered > 0)
|
||||
impl->suppress_layered--;
|
||||
|
||||
/* If we don't have any surface that forces layered windows off,
|
||||
* trigger update_style_bits() to enable layered windows again
|
||||
*/
|
||||
if (impl->suppress_layered == 0)
|
||||
_gdk_win32_surface_update_style_bits (surface);
|
||||
}
|
||||
G_OBJECT_CLASS (gdk_win32_gl_context_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
@@ -1001,17 +988,6 @@ gdk_win32_gl_context_realize (GdkGLContext *context,
|
||||
/* set whether we are using GLES */
|
||||
gdk_gl_context_set_use_es (context, use_es);
|
||||
|
||||
/* OpenGL does not work with WS_EX_LAYERED enabled, so we need to
|
||||
* disable WS_EX_LAYERED when we acquire a valid HGLRC
|
||||
*/
|
||||
impl->suppress_layered++;
|
||||
|
||||
/* if this is the first time a GL context is acquired for the surface,
|
||||
* disable layered windows by triggering update_style_bits()
|
||||
*/
|
||||
if (impl->suppress_layered == 1)
|
||||
_gdk_win32_surface_update_style_bits (surface);
|
||||
|
||||
/* Ensure that any other context is created with a legacy bit set */
|
||||
gdk_gl_context_set_is_legacy (context, legacy_bit);
|
||||
|
||||
|
||||
@@ -351,7 +351,6 @@ _gdk_win32_surface_exstyle_to_string (LONG style)
|
||||
BIT (CONTEXTHELP);
|
||||
BIT (CONTROLPARENT);
|
||||
BIT (DLGMODALFRAME);
|
||||
BIT (LAYERED);
|
||||
BIT (LAYOUTRTL);
|
||||
BIT (LEFTSCROLLBAR);
|
||||
BIT (MDICHILD);
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
#include <math.h>
|
||||
|
||||
static void gdk_surface_win32_finalize (GObject *object);
|
||||
static void compute_toplevel_size (GdkSurface *surface,
|
||||
gboolean update_geometry,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
static gpointer parent_class = NULL;
|
||||
static GSList *modal_window_stack = NULL;
|
||||
@@ -271,7 +275,6 @@ _gdk_win32_adjust_client_rect (GdkSurface *window,
|
||||
gboolean
|
||||
_gdk_win32_surface_enable_transparency (GdkSurface *window)
|
||||
{
|
||||
GdkWin32Surface *impl;
|
||||
DWM_BLURBEHIND blur_behind;
|
||||
HRGN empty_region;
|
||||
HRESULT call_result;
|
||||
@@ -280,12 +283,6 @@ _gdk_win32_surface_enable_transparency (GdkSurface *window)
|
||||
if (window == NULL || GDK_SURFACE_HWND (window) == NULL)
|
||||
return FALSE;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
/* layered windows don't need blurbehind for transparency */
|
||||
if (impl->layered)
|
||||
return TRUE;
|
||||
|
||||
if (!gdk_display_is_composited (gdk_surface_get_display (window)))
|
||||
return FALSE;
|
||||
|
||||
@@ -522,9 +519,6 @@ _gdk_win32_display_create_surface (GdkDisplay *display,
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
impl->layered = FALSE;
|
||||
impl->layered_opacity = 1.0;
|
||||
|
||||
impl->surface_scale = _gdk_win32_display_get_monitor_scale_factor (display_win32, NULL, NULL, NULL);
|
||||
impl->unscaled_width = width * impl->surface_scale;
|
||||
impl->unscaled_height = height * impl->surface_scale;
|
||||
@@ -1100,6 +1094,8 @@ gdk_win32_surface_resize (GdkSurface *window,
|
||||
outer_rect.bottom - outer_rect.top,
|
||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER));
|
||||
window->resize_count += 1;
|
||||
|
||||
gdk_surface_request_layout (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1160,8 +1156,6 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
{
|
||||
GdkWin32Surface *surface = GDK_WIN32_SURFACE (window);
|
||||
|
||||
surface->inhibit_configure = TRUE;
|
||||
|
||||
/* We ignore changes to the window being moved or resized by the
|
||||
user, as we don't want to fight the user */
|
||||
if (GDK_SURFACE_HWND (window) == _modal_move_resize_window)
|
||||
@@ -1186,8 +1180,6 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
|
||||
}
|
||||
|
||||
out:
|
||||
surface->inhibit_configure = FALSE;
|
||||
|
||||
gdk_surface_request_layout (window);
|
||||
}
|
||||
|
||||
@@ -1228,10 +1220,10 @@ gdk_win32_surface_layout_popup (GdkSurface *surface,
|
||||
gdk_surface_layout_popup_helper (surface,
|
||||
width,
|
||||
height,
|
||||
impl->margins.left,
|
||||
impl->margins.right,
|
||||
impl->margins.top,
|
||||
impl->margins.bottom,
|
||||
impl->shadow.left,
|
||||
impl->shadow.right,
|
||||
impl->shadow.top,
|
||||
impl->shadow.bottom,
|
||||
monitor,
|
||||
&bounds,
|
||||
layout,
|
||||
@@ -1256,11 +1248,24 @@ gdk_win32_surface_layout_popup (GdkSurface *surface,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_notify_mapped (GdkSurface *surface)
|
||||
{
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
if (!GDK_SURFACE_IS_MAPPED (surface))
|
||||
{
|
||||
gdk_surface_set_is_mapped (surface, TRUE);
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_popup (GdkSurface *surface)
|
||||
{
|
||||
gdk_win32_surface_raise (surface);
|
||||
gdk_surface_set_is_mapped (surface, TRUE);
|
||||
maybe_notify_mapped (surface);
|
||||
show_window_internal (surface, FALSE, FALSE);
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
}
|
||||
@@ -1746,11 +1751,6 @@ update_single_bit (LONG *style,
|
||||
* Returns TRUE if window has no decorations.
|
||||
* Usually it means CSD windows, because GTK
|
||||
* calls gdk_surface_set_decorations (window, 0);
|
||||
* This is used to decide whether a toplevel should
|
||||
* be made layered, thus it
|
||||
* only returns TRUE for toplevels (until GTK minimal
|
||||
* system requirements are lifted to Windows 8 or newer,
|
||||
* because only toplevels can be layered).
|
||||
*/
|
||||
gboolean
|
||||
_gdk_win32_surface_lacks_wm_decorations (GdkSurface *window)
|
||||
@@ -1844,27 +1844,6 @@ _gdk_win32_surface_update_style_bits (GdkSurface *window)
|
||||
new_exstyle &= ~WS_EX_TOOLWINDOW;
|
||||
}
|
||||
|
||||
/* We can get away with using layered windows
|
||||
* only when no decorations are needed. It can mean
|
||||
* CSD or borderless non-CSD windows (tooltips?).
|
||||
*
|
||||
* If this window cannot use layered windows, disable it always.
|
||||
* This currently applies to windows using OpenGL, which
|
||||
* does not work with layered windows.
|
||||
*/
|
||||
if (impl->suppress_layered == 0)
|
||||
{
|
||||
if (_gdk_win32_surface_lacks_wm_decorations (window))
|
||||
impl->layered = g_strcmp0 (g_getenv ("GDK_WIN32_LAYERED"), "0") != 0;
|
||||
}
|
||||
else
|
||||
impl->layered = FALSE;
|
||||
|
||||
if (impl->layered)
|
||||
new_exstyle |= WS_EX_LAYERED;
|
||||
else
|
||||
new_exstyle &= ~WS_EX_LAYERED;
|
||||
|
||||
if (get_effective_window_decorations (window, &decorations))
|
||||
{
|
||||
all = (decorations & GDK_DECOR_ALL);
|
||||
@@ -2294,6 +2273,7 @@ snap_up (GdkSurface *window)
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
impl->snap_state = GDK_WIN32_AEROSNAP_STATE_FULLUP;
|
||||
impl->resized = FALSE;
|
||||
|
||||
stash_window (window, impl);
|
||||
|
||||
@@ -2304,10 +2284,18 @@ snap_up (GdkSurface *window)
|
||||
y = 0;
|
||||
height = maxysize;
|
||||
|
||||
x = x - impl->margins.left;
|
||||
y = y - impl->margins.top;
|
||||
width += impl->margins_x;
|
||||
height += impl->margins_y;
|
||||
x = x - impl->shadow.left;
|
||||
y = y - impl->shadow.top;
|
||||
width += impl->shadow_x;
|
||||
height += impl->shadow_y;
|
||||
|
||||
/* XXX: FIXME, AeroSnap snap_up() not really working well,
|
||||
*
|
||||
* * The snap_up() puts the window at the top left corner.
|
||||
* * Without the following call, the height maximizes but we see a spew of
|
||||
* "GdkToplevelSize: geometry size (x,y) exceeds bounds" warnings
|
||||
*/
|
||||
compute_toplevel_size (window, TRUE, &width, &height);
|
||||
|
||||
gdk_win32_surface_move_resize (window, x, y, width, height);
|
||||
}
|
||||
@@ -2323,6 +2311,7 @@ snap_left (GdkSurface *window,
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFLEFT;
|
||||
impl->resized = FALSE;
|
||||
|
||||
gdk_win32_monitor_get_workarea (snap_monitor, &rect);
|
||||
|
||||
@@ -2330,10 +2319,10 @@ snap_left (GdkSurface *window,
|
||||
|
||||
rect.width = rect.width / 2;
|
||||
|
||||
rect.x = rect.x - impl->margins.left;
|
||||
rect.y = rect.y - impl->margins.top;
|
||||
rect.width = rect.width + impl->margins_x;
|
||||
rect.height = rect.height + impl->margins_y;
|
||||
rect.x = rect.x - impl->shadow.left;
|
||||
rect.y = rect.y - impl->shadow.top;
|
||||
rect.width = rect.width + impl->shadow_x;
|
||||
rect.height = rect.height + impl->shadow_y;
|
||||
|
||||
gdk_win32_surface_move_resize (window,
|
||||
rect.x, rect.y,
|
||||
@@ -2351,6 +2340,7 @@ snap_right (GdkSurface *window,
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
impl->snap_state = GDK_WIN32_AEROSNAP_STATE_HALFRIGHT;
|
||||
impl->resized = FALSE;
|
||||
|
||||
gdk_win32_monitor_get_workarea (snap_monitor, &rect);
|
||||
|
||||
@@ -2359,10 +2349,10 @@ snap_right (GdkSurface *window,
|
||||
rect.width = rect.width / 2;
|
||||
rect.x += rect.width;
|
||||
|
||||
rect.x = rect.x - impl->margins.left;
|
||||
rect.y = rect.y - impl->margins.top;
|
||||
rect.width = rect.width + impl->margins_x;
|
||||
rect.height = rect.height + impl->margins_y;
|
||||
rect.x = rect.x - impl->shadow.left;
|
||||
rect.y = rect.y - impl->shadow.top;
|
||||
rect.width = rect.width + impl->shadow_x;
|
||||
rect.height = rect.height + impl->shadow_y;
|
||||
|
||||
gdk_win32_surface_move_resize (window,
|
||||
rect.x, rect.y,
|
||||
@@ -3502,10 +3492,10 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
*/
|
||||
if (op == GDK_WIN32_DRAGOP_MOVE && !maximized)
|
||||
{
|
||||
swx += impl->margins.left / impl->surface_scale;
|
||||
swy += impl->margins.top / impl->surface_scale;
|
||||
swwidth -= impl->margins_x;
|
||||
swheight -= impl->margins_y;
|
||||
swx += impl->shadow.left / impl->surface_scale;
|
||||
swy += impl->shadow.top / impl->surface_scale;
|
||||
swwidth -= impl->shadow_x;
|
||||
swheight -= impl->shadow_y;
|
||||
}
|
||||
|
||||
pointer_outside_of_window = root_x < swx || root_x > swx + swwidth ||
|
||||
@@ -3555,23 +3545,23 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
unmax_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left;
|
||||
unmax_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top;
|
||||
|
||||
shadow_unmax_width = unmax_width - impl->margins_x * impl->surface_scale;
|
||||
shadow_unmax_height = unmax_height - impl->margins_y * impl->surface_scale;
|
||||
shadow_unmax_width = unmax_width - impl->shadow_x * impl->surface_scale;
|
||||
shadow_unmax_height = unmax_height - impl->shadow_y * impl->surface_scale;
|
||||
|
||||
if (offsetx * impl->surface_scale < (shadow_unmax_width / 2) &&
|
||||
offsety * impl->surface_scale < (shadow_unmax_height / 2))
|
||||
{
|
||||
placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->surface_scale;
|
||||
placement.rcNormalPosition.top = (root_y - offsety + impl->shadow.top - _gdk_offset_y) * impl->surface_scale;
|
||||
placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
|
||||
|
||||
if (left_half)
|
||||
{
|
||||
placement.rcNormalPosition.left = (root_x - offsetx + impl->margins.left - _gdk_offset_x) * impl->surface_scale;
|
||||
placement.rcNormalPosition.left = (root_x - offsetx + impl->shadow.left - _gdk_offset_x) * impl->surface_scale;
|
||||
placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
placement.rcNormalPosition.right = (root_x + offsetx + impl->margins.right - _gdk_offset_x) * impl->surface_scale;
|
||||
placement.rcNormalPosition.right = (root_x + offsetx + impl->shadow.right - _gdk_offset_x) * impl->surface_scale;
|
||||
placement.rcNormalPosition.left = placement.rcNormalPosition.right - unmax_width;
|
||||
}
|
||||
}
|
||||
@@ -3582,7 +3572,7 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
(_gdk_offset_x * impl->surface_scale);
|
||||
|
||||
if (offsety * impl->surface_scale < shadow_unmax_height / 2)
|
||||
placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * impl->surface_scale;
|
||||
placement.rcNormalPosition.top = (root_y - offsety + impl->shadow.top - _gdk_offset_y) * impl->surface_scale;
|
||||
else
|
||||
placement.rcNormalPosition.top = (root_y * impl->surface_scale) -
|
||||
(unmax_height / 2) -
|
||||
@@ -3609,18 +3599,18 @@ setup_drag_move_resize_context (GdkSurface *window,
|
||||
|
||||
if (op == GDK_WIN32_DRAGOP_MOVE)
|
||||
{
|
||||
snew_pos.width -= impl->margins_x;
|
||||
snew_pos.height -= impl->margins_y;
|
||||
snew_pos.width -= impl->shadow_x;
|
||||
snew_pos.height -= impl->shadow_y;
|
||||
}
|
||||
|
||||
if (offsetx < snew_pos.width / 2 && offsety < snew_pos.height / 2)
|
||||
{
|
||||
new_pos.y = root_y - offsety + impl->margins.top / impl->surface_scale;
|
||||
new_pos.y = root_y - offsety + impl->shadow.top / impl->surface_scale;
|
||||
|
||||
if (left_half)
|
||||
new_pos.x = root_x - offsetx + impl->margins.left / impl->surface_scale;
|
||||
new_pos.x = root_x - offsetx + impl->shadow.left / impl->surface_scale;
|
||||
else
|
||||
new_pos.x = root_x + offsetx + impl->margins.left / impl->surface_scale - new_pos.width;
|
||||
new_pos.x = root_x + offsetx + impl->shadow.left / impl->surface_scale - new_pos.width;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3785,67 +3775,6 @@ gdk_win32_get_window_size_and_position_from_client_rect (GdkSurface *window,
|
||||
window_size->cy = window_rect->bottom - window_rect->top;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_win32_update_layered_window_from_cache (GdkSurface *surface,
|
||||
RECT *client_rect,
|
||||
gboolean do_move,
|
||||
gboolean do_resize,
|
||||
gboolean do_paint)
|
||||
{
|
||||
POINT window_position;
|
||||
SIZE window_size;
|
||||
BLENDFUNCTION blender;
|
||||
HDC hdc;
|
||||
SIZE *window_size_ptr;
|
||||
POINT source_point = { 0, 0 };
|
||||
POINT *source_point_ptr;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (surface,
|
||||
client_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
blender.BlendOp = AC_SRC_OVER;
|
||||
blender.BlendFlags = 0;
|
||||
blender.AlphaFormat = AC_SRC_ALPHA;
|
||||
blender.SourceConstantAlpha = impl->layered_opacity * 255;
|
||||
|
||||
/* Strictly speaking, we don't need to supply hdc, source_point and
|
||||
* window_size to just move the window. However, without these arguments
|
||||
* the window moves but does not update its contents on Windows 7 when
|
||||
* desktop composition is off. This forces us to provide hdc and
|
||||
* source_point. window_size is here to avoid the function
|
||||
* inexplicably failing with error 317.
|
||||
*/
|
||||
hdc = cairo_win32_surface_get_dc (impl->cache_surface);
|
||||
window_size_ptr = &window_size;
|
||||
source_point_ptr = &source_point;
|
||||
|
||||
if (gdk_display_is_composited (gdk_surface_get_display (surface)))
|
||||
{
|
||||
if (!do_paint)
|
||||
hdc = NULL;
|
||||
if (!do_resize)
|
||||
window_size_ptr = NULL;
|
||||
if (!do_move)
|
||||
source_point_ptr = NULL;
|
||||
}
|
||||
|
||||
/* Don't use UpdateLayeredWindow on minimized windows */
|
||||
if (IsIconic (GDK_SURFACE_HWND (surface)))
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (surface),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
window_size.cx, window_size.cy,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
|
||||
else
|
||||
API_CALL (UpdateLayeredWindow, (GDK_SURFACE_HWND (surface), NULL,
|
||||
&window_position, window_size_ptr,
|
||||
hdc, source_point_ptr,
|
||||
0, &blender, ULW_ALPHA));
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
|
||||
int x,
|
||||
@@ -4015,42 +3944,47 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
|
||||
rect.top != new_rect.top ||
|
||||
rect.bottom != new_rect.bottom))
|
||||
{
|
||||
if (GDK_IS_TOPLEVEL (window))
|
||||
{
|
||||
int scale = impl->surface_scale;
|
||||
|
||||
impl->unscaled_width = new_rect.right - new_rect.left;
|
||||
impl->unscaled_height = new_rect.bottom - new_rect.top;
|
||||
impl->next_layout.configured_width = (impl->unscaled_width + scale - 1) / scale;
|
||||
impl->next_layout.configured_height = (impl->unscaled_height + scale - 1) / scale;
|
||||
impl->resized = TRUE;
|
||||
}
|
||||
|
||||
context->native_move_resize_pending = TRUE;
|
||||
gdk_surface_request_layout (window);
|
||||
}
|
||||
else if (context->op == GDK_WIN32_DRAGOP_MOVE &&
|
||||
(rect.left != new_rect.left ||
|
||||
rect.top != new_rect.top))
|
||||
{
|
||||
SIZE window_size;
|
||||
POINT window_position;
|
||||
|
||||
context->native_move_resize_pending = FALSE;
|
||||
|
||||
gdk_surface_request_layout (window);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
_gdk_win32_update_layered_window_from_cache (window, &new_rect, TRUE, FALSE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE window_size;
|
||||
POINT window_position;
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (window,
|
||||
&new_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
gdk_win32_get_window_size_and_position_from_client_rect (window,
|
||||
&new_rect,
|
||||
&window_size,
|
||||
&window_position);
|
||||
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
|
||||
}
|
||||
API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window),
|
||||
SWP_NOZORDER_SPECIFIED,
|
||||
window_position.x, window_position.y,
|
||||
0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
|
||||
}
|
||||
|
||||
if (context->op == GDK_WIN32_DRAGOP_RESIZE ||
|
||||
context->op == GDK_WIN32_DRAGOP_MOVE)
|
||||
handle_aerosnap_move_resize (window, context, x, y);
|
||||
|
||||
gdk_surface_request_layout (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4159,6 +4093,7 @@ gdk_win32_surface_minimize (GdkSurface *window)
|
||||
static void
|
||||
gdk_win32_surface_maximize (GdkSurface *window)
|
||||
{
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (window));
|
||||
|
||||
@@ -4169,6 +4104,9 @@ gdk_win32_surface_maximize (GdkSurface *window)
|
||||
GDK_SURFACE_HWND (window),
|
||||
_gdk_win32_surface_state_to_string (window->state)));
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
impl->resized = FALSE;
|
||||
|
||||
if (GDK_SURFACE_IS_MAPPED (window))
|
||||
GtkShowWindow (window, SW_MAXIMIZE);
|
||||
else
|
||||
@@ -4313,61 +4251,6 @@ gdk_win32_surface_lookup_for_display (GdkDisplay *display,
|
||||
return (GdkSurface*) gdk_win32_handle_table_lookup (anid);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_win32_surface_set_opacity (GdkSurface *window,
|
||||
double opacity)
|
||||
{
|
||||
LONG exstyle;
|
||||
typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes) (HWND, COLORREF, BYTE, DWORD);
|
||||
PFN_SetLayeredWindowAttributes setLayeredWindowAttributes = NULL;
|
||||
GdkWin32Surface *impl;
|
||||
|
||||
g_return_if_fail (GDK_IS_SURFACE (window));
|
||||
|
||||
if (GDK_SURFACE_DESTROYED (window))
|
||||
return;
|
||||
|
||||
if (opacity < 0)
|
||||
opacity = 0;
|
||||
else if (opacity > 1)
|
||||
opacity = 1;
|
||||
|
||||
impl = GDK_WIN32_SURFACE (window);
|
||||
|
||||
if (impl->layered)
|
||||
{
|
||||
if (impl->layered_opacity != opacity)
|
||||
{
|
||||
RECT window_rect;
|
||||
|
||||
impl->layered_opacity = opacity;
|
||||
|
||||
_gdk_win32_get_window_client_area_rect (window, impl->surface_scale, &window_rect);
|
||||
_gdk_win32_update_layered_window_from_cache (window, &window_rect, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
exstyle = GetWindowLong (GDK_SURFACE_HWND (window), GWL_EXSTYLE);
|
||||
|
||||
if (!(exstyle & WS_EX_LAYERED))
|
||||
SetWindowLong (GDK_SURFACE_HWND (window),
|
||||
GWL_EXSTYLE,
|
||||
exstyle | WS_EX_LAYERED);
|
||||
|
||||
setLayeredWindowAttributes =
|
||||
(PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes");
|
||||
|
||||
if (setLayeredWindowAttributes)
|
||||
{
|
||||
API_CALL (setLayeredWindowAttributes, (GDK_SURFACE_HWND (window),
|
||||
0,
|
||||
opacity * 0xff,
|
||||
LWA_ALPHA));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdk_win32_surface_is_win32 (GdkSurface *window)
|
||||
{
|
||||
@@ -4447,9 +4330,6 @@ GtkShowWindow (GdkSurface *window,
|
||||
if (IsWindowVisible (hwnd))
|
||||
break;
|
||||
|
||||
if ((WS_EX_LAYERED & GetWindowLongPtr (hwnd, GWL_EXSTYLE)) != WS_EX_LAYERED)
|
||||
break;
|
||||
|
||||
/* Window was hidden, will be shown. Erase it, GDK will repaint soon,
|
||||
* but not soon enough, so it's possible to see old content before
|
||||
* the next redraw, unless we erase the window first.
|
||||
@@ -4514,17 +4394,17 @@ gdk_win32_surface_set_shadow_width (GdkSurface *window,
|
||||
"left %d, top %d, right %d, bottom %d\n",
|
||||
window, left, top, right, bottom));
|
||||
|
||||
impl->zero_margins = left == 0 && right == 0 && top == 0 && bottom == 0;
|
||||
impl->zero_shadow = left == 0 && right == 0 && top == 0 && bottom == 0;
|
||||
|
||||
if (impl->zero_margins)
|
||||
if (impl->zero_shadow)
|
||||
return;
|
||||
|
||||
impl->margins.left = left;
|
||||
impl->margins.right = right * impl->surface_scale;
|
||||
impl->margins.top = top;
|
||||
impl->margins.bottom = bottom * impl->surface_scale;
|
||||
impl->margins_x = left + right;
|
||||
impl->margins_y = top + bottom;
|
||||
impl->shadow.left = left;
|
||||
impl->shadow.right = right * impl->surface_scale;
|
||||
impl->shadow.top = top;
|
||||
impl->shadow.bottom = bottom * impl->surface_scale;
|
||||
impl->shadow_x = left + right;
|
||||
impl->shadow_y = top + bottom;
|
||||
}
|
||||
|
||||
|
||||
@@ -4597,6 +4477,118 @@ gdk_win32_surface_set_input_region (GdkSurface *window,
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
compute_toplevel_size (GdkSurface *surface,
|
||||
gboolean update_geometry,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkMonitor *monitor;
|
||||
GdkToplevelSize size;
|
||||
int bounds_width, bounds_height;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
if (monitor)
|
||||
{
|
||||
GdkRectangle workarea;
|
||||
|
||||
gdk_win32_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);
|
||||
*width = size.width;
|
||||
*height = size.height;
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
{
|
||||
gdk_win32_surface_set_shadow_width (surface,
|
||||
size.shadow.left,
|
||||
size.shadow.right,
|
||||
size.shadow.top,
|
||||
size.shadow.bottom);
|
||||
}
|
||||
|
||||
if (update_geometry)
|
||||
{
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
GdkToplevelLayout *layout = impl->toplevel_layout;
|
||||
|
||||
if (gdk_toplevel_layout_get_resizable (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 = *width;
|
||||
geometry.max_height = geometry.min_height = *height;
|
||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||
}
|
||||
gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
|
||||
gdk_surface_constrain_size (&geometry, mask, *width, *height, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_win32_surface_request_layout (GdkSurface *surface)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
int scale = impl->surface_scale;
|
||||
RECT rect;
|
||||
|
||||
if (GDK_IS_TOPLEVEL (surface) && impl->resized)
|
||||
{
|
||||
surface->width = impl->next_layout.configured_width;
|
||||
surface->height = impl->next_layout.configured_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gdk_win32_get_window_rect (surface, &rect);
|
||||
|
||||
impl->unscaled_width = rect.right - rect.left;
|
||||
impl->unscaled_height = rect.bottom - rect.top;
|
||||
|
||||
impl->next_layout.configured_width = (impl->unscaled_width + scale - 1) / scale;
|
||||
impl->next_layout.configured_height = (impl->unscaled_height + scale - 1) / scale;
|
||||
surface->x = rect.left / scale;
|
||||
surface->y = rect.top / scale;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gdk_win32_surface_compute_size (GdkSurface *surface)
|
||||
{
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
int width, height;
|
||||
|
||||
if (GDK_IS_TOPLEVEL (surface))
|
||||
compute_toplevel_size (surface, TRUE, &width, &height);
|
||||
|
||||
if (!impl->resized)
|
||||
{
|
||||
surface->width = impl->next_layout.configured_width;
|
||||
surface->height = impl->next_layout.configured_height;
|
||||
|
||||
_gdk_surface_update_size (surface);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
|
||||
{
|
||||
@@ -4623,6 +4615,8 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
|
||||
impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
|
||||
impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
|
||||
impl_class->get_unscaled_size = _gdk_win32_surface_get_unscaled_size;
|
||||
impl_class->request_layout = _gdk_win32_surface_request_layout;
|
||||
impl_class->compute_size = _gdk_win32_surface_compute_size;
|
||||
}
|
||||
|
||||
HGDIOBJ
|
||||
@@ -4912,75 +4906,18 @@ gdk_win32_toplevel_class_init (GdkWin32ToplevelClass *class)
|
||||
}
|
||||
|
||||
static void
|
||||
show_surface (GdkSurface *surface)
|
||||
{
|
||||
gboolean was_mapped;
|
||||
|
||||
if (surface->destroyed)
|
||||
return;
|
||||
|
||||
was_mapped = GDK_SURFACE_IS_MAPPED (surface);
|
||||
|
||||
if (!was_mapped)
|
||||
gdk_surface_set_is_mapped (surface, TRUE);
|
||||
|
||||
gdk_win32_surface_show (surface, FALSE);
|
||||
|
||||
if (!was_mapped)
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_win32_toplevel_present (GdkToplevel *toplevel,
|
||||
GdkToplevelLayout *layout)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
GdkDisplay *display = gdk_surface_get_display (surface);
|
||||
GdkMonitor *monitor;
|
||||
GdkToplevelSize size;
|
||||
int bounds_width, bounds_height;
|
||||
GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
|
||||
int width, height;
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
gboolean maximize;
|
||||
gboolean fullscreen;
|
||||
|
||||
monitor = gdk_display_get_monitor_at_surface (display, surface);
|
||||
if (monitor)
|
||||
{
|
||||
GdkRectangle workarea;
|
||||
|
||||
gdk_win32_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 (toplevel, &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))
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
mask = GDK_HINT_MIN_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
geometry.max_width = geometry.min_width = width;
|
||||
geometry.max_height = geometry.min_height = height;
|
||||
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
|
||||
}
|
||||
gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
|
||||
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
|
||||
g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref);
|
||||
impl->toplevel_layout = gdk_toplevel_layout_copy (layout);
|
||||
compute_toplevel_size (surface, FALSE, &width, &height);
|
||||
gdk_win32_surface_resize (surface, width, height);
|
||||
|
||||
if (gdk_toplevel_layout_get_maximized (layout, &maximize))
|
||||
@@ -4999,18 +4936,8 @@ gdk_win32_toplevel_present (GdkToplevel *toplevel,
|
||||
gdk_win32_surface_unfullscreen (surface);
|
||||
}
|
||||
|
||||
show_surface (surface);
|
||||
|
||||
if (size.shadow.is_valid)
|
||||
{
|
||||
gdk_win32_surface_set_shadow_width (surface,
|
||||
size.shadow.left,
|
||||
size.shadow.right,
|
||||
size.shadow.top,
|
||||
size.shadow.bottom);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
gdk_win32_surface_show (surface, FALSE);
|
||||
maybe_notify_mapped (surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -5093,8 +5020,9 @@ gdk_win32_drag_surface_present (GdkDragSurface *drag_surface,
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (drag_surface);
|
||||
|
||||
gdk_win32_surface_resize (surface, width, height);
|
||||
show_surface (surface);
|
||||
gdk_win32_surface_resize (surface, width, height);
|
||||
gdk_win32_surface_show (surface, FALSE);
|
||||
maybe_notify_mapped (surface);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -5185,7 +5113,6 @@ gdk_win32_surface_apply_queued_move_resize (GdkSurface *surface,
|
||||
RECT
|
||||
gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
|
||||
{
|
||||
GdkWin32CairoContext *cairo_ctx = NULL;
|
||||
GdkSurface *surface;
|
||||
GdkWin32Surface *impl;
|
||||
int scale;
|
||||
@@ -5195,23 +5122,16 @@ gdk_win32_surface_handle_queued_move_resize (GdkDrawContext *draw_context)
|
||||
impl = GDK_WIN32_SURFACE (surface);
|
||||
scale = gdk_surface_get_scale_factor (surface);
|
||||
|
||||
if (GDK_IS_WIN32_CAIRO_CONTEXT (draw_context))
|
||||
{
|
||||
cairo_ctx = GDK_WIN32_CAIRO_CONTEXT (draw_context);
|
||||
cairo_ctx->layered = impl->layered;
|
||||
}
|
||||
|
||||
gdk_win32_surface_get_queued_window_rect (surface, scale, &queued_window_rect);
|
||||
|
||||
/* Apply queued resizes for non-double-buffered and non-layered windows
|
||||
/* Apply queued resizes for non-double-buffered windows
|
||||
* before painting them (we paint on the window DC directly,
|
||||
* it must have the right size).
|
||||
* Due to some poorly-undetstood issue delayed
|
||||
* resizing of double-buffered windows can produce weird
|
||||
* artefacts, so these are also resized before we paint.
|
||||
*/
|
||||
if (impl->drag_move_resize_context.native_move_resize_pending &&
|
||||
(cairo_ctx == NULL || !cairo_ctx->layered))
|
||||
if (impl->drag_move_resize_context.native_move_resize_pending)
|
||||
{
|
||||
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
|
||||
gdk_win32_surface_apply_queued_move_resize (surface, queued_window_rect);
|
||||
|
||||
@@ -265,25 +265,18 @@ struct _GdkWin32Surface
|
||||
int initial_y;
|
||||
|
||||
/* left/right/top/bottom width of the shadow/resize-grip around the window */
|
||||
RECT margins;
|
||||
RECT shadow;
|
||||
|
||||
/* left+right and top+bottom from @margins */
|
||||
int margins_x;
|
||||
int margins_y;
|
||||
/* left+right and top+bottom from @shadow */
|
||||
int shadow_x;
|
||||
int shadow_y;
|
||||
|
||||
/* Set to TRUE when GTK tells us that margins are 0 everywhere.
|
||||
* We don't actually set margins to 0, we just set this bit.
|
||||
/* Set to TRUE when GTK tells us that shadow are 0 everywhere.
|
||||
* We don't actually set shadow to 0, we just set this bit.
|
||||
*/
|
||||
guint zero_margins : 1;
|
||||
guint zero_shadow : 1;
|
||||
guint inhibit_configure : 1;
|
||||
|
||||
/* Set to TRUE if window is using true layered mode adjustments
|
||||
* via UpdateLayeredWindow().
|
||||
* Layered windows that get SetLayeredWindowAttributes() called
|
||||
* on them are not true layered windows.
|
||||
*/
|
||||
guint layered : 1;
|
||||
|
||||
/* If TRUE, the @temp_styles is set to the styles that were temporarily
|
||||
* added to this window.
|
||||
*/
|
||||
@@ -309,12 +302,6 @@ struct _GdkWin32Surface
|
||||
int dib_width;
|
||||
int dib_height;
|
||||
|
||||
/* If the client wants uniformly-transparent window,
|
||||
* we remember the opacity value here and apply it
|
||||
* during UpdateLayredWindow() call, for layered windows.
|
||||
*/
|
||||
double layered_opacity;
|
||||
|
||||
HDC hdc;
|
||||
int hdc_count;
|
||||
HBITMAP saved_dc_bitmap; /* Original bitmap for dc */
|
||||
@@ -340,9 +327,6 @@ struct _GdkWin32Surface
|
||||
/* Enable all decorations? */
|
||||
gboolean decorate_all;
|
||||
|
||||
/* No. of windows to force layered windows off */
|
||||
guint suppress_layered;
|
||||
|
||||
/* Temporary styles that this window got for the purpose of
|
||||
* handling WM_SYSMENU.
|
||||
* They are removed at the first opportunity (usually WM_INITMENU).
|
||||
@@ -354,6 +338,13 @@ struct _GdkWin32Surface
|
||||
int unscaled_width;
|
||||
int unscaled_height;
|
||||
|
||||
GdkToplevelLayout *toplevel_layout;
|
||||
struct {
|
||||
int configured_width;
|
||||
int configured_height;
|
||||
} next_layout;
|
||||
gboolean resized;
|
||||
|
||||
#ifdef GDK_WIN32_ENABLE_EGL
|
||||
EGLSurface egl_surface;
|
||||
EGLSurface egl_dummy_surface;
|
||||
@@ -375,11 +366,6 @@ int _gdk_win32_surface_get_scale_factor (GdkSurface *window);
|
||||
void _gdk_win32_get_window_client_area_rect (GdkSurface *window,
|
||||
int scale,
|
||||
RECT *rect);
|
||||
void _gdk_win32_update_layered_window_from_cache (GdkSurface *window,
|
||||
RECT *client_rect,
|
||||
gboolean do_move,
|
||||
gboolean do_resize,
|
||||
gboolean do_paint);
|
||||
|
||||
void gdk_win32_surface_move (GdkSurface *surface,
|
||||
int x,
|
||||
|
||||
@@ -63,12 +63,6 @@ gdk_win32_vulkan_context_create_surface (GdkVulkanContext *context,
|
||||
NULL,
|
||||
surface);
|
||||
|
||||
if (result == VK_SUCCESS)
|
||||
win32_surface->suppress_layered ++;
|
||||
|
||||
if (win32_surface->suppress_layered == 1)
|
||||
_gdk_win32_surface_update_style_bits (window);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1097,15 +1097,16 @@ handle_property_change (GdkX11DeviceManagerXI2 *device_manager,
|
||||
if (ev->what != XIPropertyDeleted &&
|
||||
device_get_tool_serial_and_id (device, &serial_id, &tool_id))
|
||||
{
|
||||
GdkDeviceToolType tool_type;
|
||||
|
||||
seat = gdk_device_get_seat (device);
|
||||
tool = gdk_seat_get_tool (seat, serial_id, tool_id);
|
||||
tool_type = device_get_tool_type (device);
|
||||
|
||||
if (!tool && serial_id > 0)
|
||||
if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
|
||||
{
|
||||
GdkDeviceToolType tool_type;
|
||||
tool = gdk_seat_get_tool (seat, serial_id, tool_id, tool_type);
|
||||
|
||||
tool_type = device_get_tool_type (device);
|
||||
if (tool_type != GDK_DEVICE_TOOL_TYPE_UNKNOWN)
|
||||
if (!tool && serial_id > 0)
|
||||
{
|
||||
tool = gdk_device_tool_new (serial_id, tool_id, tool_type, 0);
|
||||
gdk_seat_default_add_tool (GDK_SEAT_DEFAULT (seat), tool);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "gdkscreen-x11.h"
|
||||
#include "gdkselectioninputstream-x11.h"
|
||||
#include "gdkselectionoutputstream-x11.h"
|
||||
#include "gdktextlistconverter-x11.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
@@ -103,6 +104,49 @@ static const struct {
|
||||
|
||||
G_DEFINE_TYPE (GdkX11Drop, gdk_x11_drop, GDK_TYPE_DROP)
|
||||
|
||||
static GInputStream *
|
||||
text_list_convert (GdkDisplay *display,
|
||||
GInputStream *stream,
|
||||
const char *encoding,
|
||||
int format)
|
||||
{
|
||||
GInputStream *converter_stream;
|
||||
GConverter *converter;
|
||||
|
||||
converter = gdk_x11_text_list_converter_to_utf8_new (display, encoding, format);
|
||||
converter_stream = g_converter_input_stream_new (stream, converter);
|
||||
|
||||
g_object_unref (converter);
|
||||
g_object_unref (stream);
|
||||
|
||||
return converter_stream;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
no_convert (GdkDisplay *display,
|
||||
GInputStream *stream,
|
||||
const char *encoding,
|
||||
int format)
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *x_target;
|
||||
const char *mime_type;
|
||||
GInputStream * (* convert) (GdkDisplay *, GInputStream *, const char *, int);
|
||||
const char *type;
|
||||
int format;
|
||||
} special_targets[] = {
|
||||
{ "UTF8_STRING", "text/plain;charset=utf-8", no_convert, "UTF8_STRING", 8 },
|
||||
{ "COMPOUND_TEXT", "text/plain;charset=utf-8", text_list_convert, "COMPOUND_TEXT", 8 },
|
||||
{ "TEXT", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
|
||||
{ "STRING", "text/plain;charset=utf-8", text_list_convert, "STRING", 8 },
|
||||
{ "TARGETS", NULL, NULL, "ATOM", 32 },
|
||||
{ "TIMESTAMP", NULL, NULL, "INTEGER", 32 },
|
||||
{ "SAVE_TARGETS", NULL, NULL, "NULL", 32 }
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_x11_drop_read_got_stream (GObject *source,
|
||||
GAsyncResult *res,
|
||||
@@ -145,9 +189,9 @@ gdk_x11_drop_read_got_stream (GObject *source,
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
gsize i;
|
||||
const char *mime_type = ((GSList *) g_task_get_task_data (task))->data;
|
||||
GdkDrop *drop = GDK_DROP (g_task_get_source_object (task));
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (special_targets); i++)
|
||||
{
|
||||
@@ -155,15 +199,12 @@ gdk_x11_drop_read_got_stream (GObject *source,
|
||||
{
|
||||
g_assert (special_targets[i].mime_type != NULL);
|
||||
|
||||
GDK_DISPLAY_NOTE (CLIPBOARD, g_printerr ("%s: reading with converter from %s to %s\n",
|
||||
cb->selection, mime_type, special_targets[i].mime_type));
|
||||
mime_type = g_intern_string (special_targets[i].mime_type);
|
||||
g_task_set_task_data (task, g_slist_prepend (NULL, (gpointer) mime_type), (GDestroyNotify) g_slist_free);
|
||||
stream = special_targets[i].convert (cb, stream, type, format);
|
||||
stream = special_targets[i].convert (gdk_drop_get_display (drop), stream, type, format);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
GDK_NOTE (DND, g_printerr ("reading DND as %s now\n",
|
||||
(const char *)((GSList *) g_task_get_task_data (task))->data));
|
||||
|
||||
@@ -1383,7 +1383,7 @@ gdk_x11_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
|
||||
tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
|
||||
group, state,
|
||||
level, effective_group);
|
||||
effective_group, level);
|
||||
}
|
||||
|
||||
if (consumed_modifiers)
|
||||
|
||||
@@ -291,7 +291,7 @@ compute_toplevel_size (GdkSurface *surface,
|
||||
GdkGeometry geometry;
|
||||
GdkSurfaceHints mask;
|
||||
|
||||
if (gdk_toplevel_layout_get_resizable (impl->toplevel_layout))
|
||||
if (!impl->toplevel_layout || gdk_toplevel_layout_get_resizable (impl->toplevel_layout))
|
||||
{
|
||||
geometry.min_width = size.min_width;
|
||||
geometry.min_height = size.min_height;
|
||||
@@ -2013,6 +2013,8 @@ _gdk_x11_surface_set_surface_scale (GdkSurface *surface,
|
||||
surface->height * impl->surface_scale);
|
||||
|
||||
gdk_surface_invalidate_rect (surface, NULL);
|
||||
|
||||
g_object_notify (G_OBJECT (surface), "scale-factor");
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -149,10 +149,10 @@ render_glyph (GlyphCacheKey *key,
|
||||
glyph_info.glyph = key->data.glyph;
|
||||
glyph_info.geometry.width = value->draw_width * 1024;
|
||||
if (glyph_info.glyph & PANGO_GLYPH_UNKNOWN_FLAG)
|
||||
glyph_info.geometry.x_offset = 0;
|
||||
glyph_info.geometry.x_offset = 250 * key->data.xshift;
|
||||
else
|
||||
glyph_info.geometry.x_offset = - value->draw_x * 1024;
|
||||
glyph_info.geometry.y_offset = - value->draw_y * 1024;
|
||||
glyph_info.geometry.x_offset = 250 * key->data.xshift - value->draw_x * 1024;
|
||||
glyph_info.geometry.y_offset = 250 * key->data.yshift - value->draw_y * 1024;
|
||||
|
||||
glyph_string.num_glyphs = 1;
|
||||
glyph_string.glyphs = &glyph_info;
|
||||
|
||||
@@ -1452,6 +1452,7 @@ render_linear_gradient_node (GskGLRenderer *self,
|
||||
ops_set_linear_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
|
||||
builder->dx + start->x,
|
||||
builder->dy + start->y,
|
||||
builder->dx + end->x,
|
||||
@@ -1485,6 +1486,7 @@ render_radial_gradient_node (GskGLRenderer *self,
|
||||
ops_set_radial_gradient (builder,
|
||||
n_color_stops,
|
||||
stops,
|
||||
gsk_render_node_get_node_type (node) == GSK_REPEATING_RADIAL_GRADIENT_NODE,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
start, end,
|
||||
@@ -1510,7 +1512,7 @@ render_conic_gradient_node (GskGLRenderer *self,
|
||||
{
|
||||
const GskColorStop *stops = gsk_conic_gradient_node_get_color_stops (node, NULL);
|
||||
const graphene_point_t *center = gsk_conic_gradient_node_get_center (node);
|
||||
const float rotation = gsk_conic_gradient_node_get_rotation (node);
|
||||
const float angle = gsk_conic_gradient_node_get_angle (node);
|
||||
|
||||
ops_set_program (builder, &self->programs->conic_gradient_program);
|
||||
ops_set_conic_gradient (builder,
|
||||
@@ -1518,7 +1520,7 @@ render_conic_gradient_node (GskGLRenderer *self,
|
||||
stops,
|
||||
builder->dx + center->x,
|
||||
builder->dy + center->y,
|
||||
rotation);
|
||||
angle);
|
||||
|
||||
load_vertex_data (ops_draw (builder, NULL), &node->bounds, builder);
|
||||
}
|
||||
@@ -1554,7 +1556,7 @@ rounded_inner_rect_contains_rect (const GskRoundedRect *rounded,
|
||||
MAX (rounded->corner[GSK_CORNER_BOTTOM_LEFT].height,
|
||||
rounded->corner[GSK_CORNER_BOTTOM_RIGHT].height);
|
||||
|
||||
return graphene_rect_contains_rect (&inner, rect);
|
||||
return _graphene_rect_contains_rect (&inner, rect);
|
||||
}
|
||||
|
||||
/* Current clip is NOT rounded but new one is definitely! */
|
||||
@@ -1644,8 +1646,8 @@ render_clipped_child (GskGLRenderer *self,
|
||||
/* well fuck */
|
||||
const float scale_x = builder->scale_x;
|
||||
const float scale_y = builder->scale_y;
|
||||
const GskRoundedRect scaled_clip = GSK_ROUNDED_RECT_INIT (clip->origin.x * scale_x,
|
||||
clip->origin.y * scale_y,
|
||||
const GskRoundedRect scaled_clip = GSK_ROUNDED_RECT_INIT ((builder->dx + clip->origin.x) * scale_x,
|
||||
(builder->dy + clip->origin.y) * scale_y,
|
||||
clip->size.width * scale_x,
|
||||
clip->size.height * scale_y);
|
||||
gboolean is_offscreen;
|
||||
@@ -1746,7 +1748,6 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
GskRoundedRect scaled_clip;
|
||||
gboolean is_offscreen;
|
||||
TextureRegion region;
|
||||
/* NOTE: We are *not* transforming the clip by the current modelview here.
|
||||
@@ -1755,19 +1756,7 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
*
|
||||
* We do, however, apply the scale factor to the child clip of course.
|
||||
*/
|
||||
scaled_clip.bounds.origin.x = clip->bounds.origin.x * scale_x;
|
||||
scaled_clip.bounds.origin.y = clip->bounds.origin.y * scale_y;
|
||||
scaled_clip.bounds.size.width = clip->bounds.size.width * scale_x;
|
||||
scaled_clip.bounds.size.height = clip->bounds.size.height * scale_y;
|
||||
|
||||
/* Increase corner radius size by scale factor */
|
||||
for (i = 0; i < 4; i ++)
|
||||
{
|
||||
scaled_clip.corner[i].width = clip->corner[i].width * scale_x;
|
||||
scaled_clip.corner[i].height = clip->corner[i].height * scale_y;
|
||||
}
|
||||
|
||||
ops_push_clip (builder, &scaled_clip);
|
||||
ops_push_clip (builder, &transformed_clip);
|
||||
if (!add_offscreen_ops (self, builder, &node->bounds,
|
||||
child,
|
||||
®ion, &is_offscreen,
|
||||
@@ -1779,7 +1768,8 @@ render_rounded_clip_node (GskGLRenderer *self,
|
||||
ops_set_program (builder, &self->programs->blit_program);
|
||||
ops_set_texture (builder, region.texture_id);
|
||||
|
||||
load_offscreen_vertex_data (ops_draw (builder, NULL), node, builder);
|
||||
load_vertex_data_with_region (ops_draw (builder, NULL), &node->bounds, builder,
|
||||
®ion, is_offscreen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3053,14 +3043,19 @@ apply_linear_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform2f (program->linear_gradient.start_point_location, op->start_point[0], op->start_point[1]);
|
||||
glUniform2f (program->linear_gradient.end_point_location, op->end_point[0], op->end_point[1]);
|
||||
glUniform4f (program->linear_gradient.points_location,
|
||||
op->start_point[0], op->start_point[1],
|
||||
op->end_point[0] - op->start_point[0], op->end_point[1] - op->start_point[1]);
|
||||
glUniform1i (program->linear_gradient.repeat_location, op->repeat);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_radial_gradient_op (const Program *program,
|
||||
const OpRadialGradient *op)
|
||||
{
|
||||
float scale;
|
||||
float bias;
|
||||
|
||||
OP_PRINT (" -> Radial gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->radial_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
@@ -3070,16 +3065,23 @@ apply_radial_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->radial_gradient.start_location, op->start);
|
||||
glUniform1f (program->radial_gradient.end_location, op->end);
|
||||
glUniform2f (program->radial_gradient.radius_location, op->radius[0], op->radius[1]);
|
||||
glUniform2f (program->radial_gradient.center_location, op->center[0], op->center[1]);
|
||||
scale = 1.0f / (op->end - op->start);
|
||||
bias = -op->start * scale;
|
||||
|
||||
glUniform1i (program->radial_gradient.repeat_location, op->repeat);
|
||||
glUniform2f (program->radial_gradient.range_location, scale, bias);
|
||||
glUniform4f (program->radial_gradient.geometry_location,
|
||||
op->center[0], op->center[1],
|
||||
1.0f / op->radius[0], 1.0f / op->radius[1]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
apply_conic_gradient_op (const Program *program,
|
||||
const OpConicGradient *op)
|
||||
{
|
||||
float bias;
|
||||
float scale;
|
||||
|
||||
OP_PRINT (" -> Conic gradient");
|
||||
if (op->n_color_stops.send)
|
||||
glUniform1i (program->conic_gradient.num_color_stops_location, op->n_color_stops.value);
|
||||
@@ -3089,8 +3091,9 @@ apply_conic_gradient_op (const Program *program,
|
||||
op->n_color_stops.value * 5,
|
||||
(float *)op->color_stops.value);
|
||||
|
||||
glUniform1f (program->conic_gradient.rotation_location, op->rotation);
|
||||
glUniform2f (program->conic_gradient.center_location, op->center[0], op->center[1]);
|
||||
scale = 0.5f * M_1_PI;
|
||||
bias = op->angle * scale + 2.0f;
|
||||
glUniform4f (program->conic_gradient.geometry_location, op->center[0], op->center[1], scale, bias);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -3380,22 +3383,20 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
|
||||
/* linear gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, start_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, end_point);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, repeat);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient, points);
|
||||
|
||||
/* radial gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, start);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, end);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, radius);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, repeat);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, geometry);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (radial_gradient, range);
|
||||
|
||||
/* conic gradient */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, num_color_stops);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, center);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, rotation);
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (conic_gradient, geometry);
|
||||
|
||||
/* blur */
|
||||
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
|
||||
@@ -3741,10 +3742,12 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
break;
|
||||
|
||||
case GSK_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
render_linear_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_RADIAL_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
render_radial_gradient_node (self, node, builder);
|
||||
break;
|
||||
|
||||
@@ -3811,8 +3814,6 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
|
||||
render_gl_shader_node (self, node, builder);
|
||||
break;
|
||||
|
||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||
case GSK_REPEATING_RADIAL_GRADIENT_NODE:
|
||||
case GSK_CAIRO_NODE:
|
||||
default:
|
||||
{
|
||||
@@ -3830,9 +3831,9 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
gboolean *is_offscreen,
|
||||
guint flags)
|
||||
{
|
||||
float width, height;
|
||||
const float dx = builder->dx;
|
||||
const float dy = builder->dy;
|
||||
float scaled_width, scaled_height;
|
||||
float scale_x;
|
||||
float scale_y;
|
||||
int render_target;
|
||||
@@ -3888,8 +3889,6 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
width = bounds->size.width;
|
||||
height = bounds->size.height;
|
||||
scale_x = builder->scale_x;
|
||||
scale_y = builder->scale_y;
|
||||
|
||||
@@ -3900,23 +3899,23 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
{
|
||||
const int max_texture_size = gsk_gl_driver_get_max_texture_size (self->gl_driver);
|
||||
|
||||
width = ceilf (width * scale_x);
|
||||
if (width > max_texture_size)
|
||||
scaled_width = ceilf (bounds->size.width * scale_x);
|
||||
if (scaled_width > max_texture_size)
|
||||
{
|
||||
scale_x *= (float)max_texture_size / width;
|
||||
width = max_texture_size;
|
||||
scale_x *= (float)max_texture_size / scaled_width;
|
||||
scaled_width = max_texture_size;
|
||||
}
|
||||
|
||||
height = ceilf (height * scale_y);
|
||||
if (height > max_texture_size)
|
||||
scaled_height = ceilf (bounds->size.height * scale_y);
|
||||
if (scaled_height > max_texture_size)
|
||||
{
|
||||
scale_y *= (float)max_texture_size / height;
|
||||
height = max_texture_size;
|
||||
scale_y *= (float)max_texture_size / scaled_height;
|
||||
scaled_height = max_texture_size;
|
||||
}
|
||||
}
|
||||
|
||||
gsk_gl_driver_create_render_target (self->gl_driver,
|
||||
width, height,
|
||||
scaled_width, scaled_height,
|
||||
filter, filter,
|
||||
&texture_id, &render_target);
|
||||
if (gdk_gl_context_has_debug (self->gl_context))
|
||||
@@ -3931,9 +3930,11 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
render_target);
|
||||
}
|
||||
|
||||
viewport = GRAPHENE_RECT_INIT (bounds->origin.x * scale_x,
|
||||
bounds->origin.y * scale_y,
|
||||
width, height);
|
||||
ops_transform_bounds_modelview (builder, bounds, &viewport);
|
||||
/* Code above will scale the size with the scale we use in the render ops,
|
||||
* but for the viewport size, we need our own size limited by the texture size */
|
||||
viewport.size.width = scaled_width;
|
||||
viewport.size.height = scaled_height;
|
||||
|
||||
init_projection_matrix (&item_proj, &viewport);
|
||||
prev_render_target = ops_set_render_target (builder, render_target);
|
||||
@@ -3945,8 +3946,8 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
if (flags & RESET_CLIP)
|
||||
ops_push_clip (builder, &GSK_ROUNDED_RECT_INIT_FROM_RECT (viewport));
|
||||
|
||||
builder->dx = 0;
|
||||
builder->dy = 0;
|
||||
builder->dx = dx;
|
||||
builder->dy = dy;
|
||||
|
||||
prev_opacity = ops_set_opacity (builder, 1.0);
|
||||
|
||||
@@ -3961,7 +3962,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
g_type_name_from_instance ((GTypeInstance *) child_node),
|
||||
child_node,
|
||||
k ++),
|
||||
width, height);
|
||||
scaled_width, scaled_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -859,6 +859,7 @@ void
|
||||
ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float start_x,
|
||||
float start_y,
|
||||
float end_x,
|
||||
@@ -912,6 +913,7 @@ ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
sizeof (GskColorStop) * real_n_color_stops);
|
||||
}
|
||||
|
||||
op->repeat = repeat;
|
||||
op->start_point[0] = start_x;
|
||||
op->start_point[1] = start_y;
|
||||
op->end_point[0] = end_x;
|
||||
@@ -922,6 +924,7 @@ void
|
||||
ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
@@ -945,6 +948,7 @@ ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
op->radius[1] = vradius;
|
||||
op->start = start;
|
||||
op->end = end;
|
||||
op->repeat = repeat;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -953,7 +957,7 @@ ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float rotation)
|
||||
float angle)
|
||||
{
|
||||
const guint real_n_color_stops = MIN (GL_MAX_GRADIENT_STOPS, n_color_stops);
|
||||
OpConicGradient *op;
|
||||
@@ -967,6 +971,6 @@ ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
op->color_stops.send = true;
|
||||
op->center[0] = center_x;
|
||||
op->center[1] = center_y;
|
||||
op->rotation = rotation;
|
||||
op->angle = angle;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,22 +118,20 @@ struct _Program
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int start_point_location;
|
||||
int end_point_location;
|
||||
int points_location;
|
||||
int repeat_location;
|
||||
} linear_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int start_location;
|
||||
int end_location;
|
||||
int radius_location;
|
||||
int geometry_location;
|
||||
int range_location;
|
||||
int repeat_location;
|
||||
} radial_gradient;
|
||||
struct {
|
||||
int num_color_stops_location;
|
||||
int color_stops_location;
|
||||
int center_location;
|
||||
int rotation_location;
|
||||
int geometry_location;
|
||||
} conic_gradient;
|
||||
struct {
|
||||
int blur_radius_location;
|
||||
@@ -319,6 +317,7 @@ void ops_set_unblurred_outset_shadow (RenderOpBuilder *se
|
||||
void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float start_x,
|
||||
float start_y,
|
||||
float end_x,
|
||||
@@ -326,6 +325,7 @@ void ops_set_linear_gradient (RenderOpBuilder *self,
|
||||
void ops_set_radial_gradient (RenderOpBuilder *self,
|
||||
guint n_color_stops,
|
||||
const GskColorStop *color_stops,
|
||||
gboolean repeat,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float start,
|
||||
@@ -337,7 +337,7 @@ void ops_set_conic_gradient (RenderOpBuilder *self,
|
||||
const GskColorStop *color_stops,
|
||||
float center_x,
|
||||
float center_y,
|
||||
float rotation);
|
||||
float angle);
|
||||
|
||||
GskQuadVertex * ops_draw (RenderOpBuilder *builder,
|
||||
const GskQuadVertex vertex_data[GL_N_VERTICES]);
|
||||
|
||||
@@ -64,8 +64,10 @@ prepend_line_numbers (char *code,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_shader_error (int shader_id,
|
||||
GError **error)
|
||||
check_shader_error (int shader_id,
|
||||
int shader_type,
|
||||
const char *resource_path,
|
||||
GError **error)
|
||||
{
|
||||
int status;
|
||||
int log_len;
|
||||
@@ -91,7 +93,9 @@ check_shader_error (int shader_id,
|
||||
prepend_line_numbers (code, s);
|
||||
|
||||
g_set_error (error, GDK_GL_ERROR, GDK_GL_ERROR_COMPILATION_FAILED,
|
||||
"Compilation failure in shader.\nSource Code: %s\n\nError Message:\n%s\n\n",
|
||||
"Compilation failure in %s shader %s.\nSource Code:\n%s\n\nError Message:\n%s\n\n",
|
||||
(shader_type == GL_FRAGMENT_SHADER ? "fragment" : "vertex"),
|
||||
resource_path,
|
||||
s->str,
|
||||
buffer);
|
||||
|
||||
@@ -184,7 +188,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
});
|
||||
glCompileShader (vertex_id);
|
||||
|
||||
if (!check_shader_error (vertex_id, error))
|
||||
if (!check_shader_error (vertex_id, GL_VERTEX_SHADER, resource_path, error))
|
||||
{
|
||||
glDeleteShader (vertex_id);
|
||||
goto out;
|
||||
@@ -218,20 +222,22 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
});
|
||||
glCompileShader (fragment_id);
|
||||
|
||||
if (!check_shader_error (fragment_id, error))
|
||||
if (!check_shader_error (fragment_id, GL_FRAGMENT_SHADER, resource_path, error))
|
||||
{
|
||||
glDeleteShader (fragment_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
print_shader_info ("Fragment shader", vertex_id, resource_path);
|
||||
print_shader_info ("Fragment shader", fragment_id, resource_path);
|
||||
|
||||
program_id = glCreateProgram ();
|
||||
glAttachShader (program_id, vertex_id);
|
||||
glAttachShader (program_id, fragment_id);
|
||||
glBindAttribLocation (program_id, 0, "aPosition");
|
||||
glBindAttribLocation (program_id, 1, "vUv");
|
||||
glBindAttribLocation (program_id, 1, "aUv");
|
||||
glLinkProgram (program_id);
|
||||
glDetachShader (program_id, vertex_id);
|
||||
glDetachShader (program_id, fragment_id);
|
||||
|
||||
glGetProgramiv (program_id, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE)
|
||||
@@ -252,14 +258,9 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder *self,
|
||||
|
||||
glDeleteProgram (program_id);
|
||||
program_id = -1;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
glDetachShader (program_id, vertex_id);
|
||||
glDeleteShader (vertex_id);
|
||||
|
||||
glDetachShader (program_id, fragment_id);
|
||||
glDeleteShader (fragment_id);
|
||||
|
||||
out:
|
||||
|
||||
@@ -146,6 +146,7 @@ typedef struct
|
||||
IntUniformValue n_color_stops;
|
||||
float start_point[2];
|
||||
float end_point[2];
|
||||
gboolean repeat;
|
||||
} OpLinearGradient;
|
||||
|
||||
typedef struct
|
||||
@@ -156,6 +157,7 @@ typedef struct
|
||||
float end;
|
||||
float radius[2];
|
||||
float center[2];
|
||||
gboolean repeat;
|
||||
} OpRadialGradient;
|
||||
|
||||
typedef struct
|
||||
@@ -163,7 +165,7 @@ typedef struct
|
||||
ColorStopUniformValue color_stops;
|
||||
IntUniformValue n_color_stops;
|
||||
float center[2];
|
||||
float rotation;
|
||||
float angle;
|
||||
} OpConicGradient;
|
||||
|
||||
typedef struct
|
||||
|
||||
@@ -22,7 +22,7 @@ static guint gsk_debug_flags;
|
||||
static void
|
||||
init_debug_flags (void)
|
||||
{
|
||||
static volatile gsize gsk_debug_flags__set;
|
||||
static gsize gsk_debug_flags__set;
|
||||
|
||||
if (g_once_init_enter (&gsk_debug_flags__set))
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static volatile gsize g_define_type_id__volatile = 0;
|
||||
static gsize g_define_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_define_type_id__volatile))
|
||||
{
|
||||
|
||||
@@ -184,7 +184,7 @@ gsk_render_node_init (GskRenderNode *self)
|
||||
GType
|
||||
gsk_render_node_get_type (void)
|
||||
{
|
||||
static volatile gsize render_node_type__volatile;
|
||||
static gsize render_node_type__volatile;
|
||||
|
||||
if (g_once_init_enter (&render_node_type__volatile))
|
||||
{
|
||||
|
||||
@@ -257,6 +257,8 @@ const graphene_point_t * gsk_conic_gradient_node_get_center (GskRenderNo
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_conic_gradient_node_get_rotation (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
float gsk_conic_gradient_node_get_angle (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gsize gsk_conic_gradient_node_get_n_color_stops (GskRenderNode *node);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const GskColorStop * gsk_conic_gradient_node_get_color_stops (GskRenderNode *node,
|
||||
|
||||
@@ -782,6 +782,7 @@ struct _GskConicGradientNode
|
||||
|
||||
graphene_point_t center;
|
||||
float rotation;
|
||||
float angle;
|
||||
|
||||
gsize n_stops;
|
||||
GskColorStop *stops;
|
||||
@@ -1023,6 +1024,12 @@ gsk_conic_gradient_node_new (const graphene_rect_t *bounds,
|
||||
self->stops = g_malloc_n (n_color_stops, sizeof (GskColorStop));
|
||||
memcpy (self->stops, color_stops, n_color_stops * sizeof (GskColorStop));
|
||||
|
||||
self->angle = 90.f - self->rotation;
|
||||
self->angle = G_PI * self->angle / 180.f;
|
||||
self->angle = fmodf (self->angle, 2.f * G_PI);
|
||||
if (self->angle < 0.f)
|
||||
self->angle += 2.f * G_PI;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1095,6 +1102,26 @@ gsk_conic_gradient_node_get_rotation (GskRenderNode *node)
|
||||
return self->rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_conic_gradient_node_get_angle:
|
||||
* @node: (type GskConicGradientNode): a #GskRenderNode for a conic gradient
|
||||
*
|
||||
* Retrieves the angle for the gradient in radians, normalized in [0, 2 * PI]
|
||||
*
|
||||
* The angle is starting at the top and going clockwise, as expressed
|
||||
* in the css specification:
|
||||
* angle = 90 - gsk_conic_gradient_node_get_rotation()
|
||||
*
|
||||
* Returns: the angle for the gradient
|
||||
*/
|
||||
float
|
||||
gsk_conic_gradient_node_get_angle (GskRenderNode *node)
|
||||
{
|
||||
GskConicGradientNode *self = (GskConicGradientNode *) node;
|
||||
|
||||
return self->angle;
|
||||
}
|
||||
|
||||
/*** GSK_BORDER_NODE ***/
|
||||
|
||||
/**
|
||||
@@ -5649,7 +5676,7 @@ gsk_render_node_init_types_once (void)
|
||||
void
|
||||
gsk_render_node_init_types (void)
|
||||
{
|
||||
static volatile gsize register_types__volatile;
|
||||
static gsize register_types__volatile;
|
||||
|
||||
if (g_once_init_enter (®ister_types__volatile))
|
||||
{
|
||||
|
||||
@@ -689,14 +689,16 @@ create_ascii_glyphs (PangoFont *font)
|
||||
for (i = MIN_ASCII_GLYPH; i < MAX_ASCII_GLYPH; i++)
|
||||
{
|
||||
const char text[2] = { i, 0 };
|
||||
PangoShapeFlags flags = 0;
|
||||
|
||||
pango_shape_with_flags (text,
|
||||
1,
|
||||
text,
|
||||
1,
|
||||
if (cairo_version () < CAIRO_VERSION_ENCODE (1, 17, 4))
|
||||
flags = PANGO_SHAPE_ROUND_POSITIONS;
|
||||
|
||||
pango_shape_with_flags (text, 1,
|
||||
text, 1,
|
||||
¬_a_hack,
|
||||
glyph_string,
|
||||
PANGO_SHAPE_ROUND_POSITIONS);
|
||||
flags);
|
||||
|
||||
if (glyph_string->num_glyphs != 1)
|
||||
{
|
||||
|
||||
@@ -1,34 +1,17 @@
|
||||
// VERTEX_SHADER
|
||||
uniform vec2 u_center;
|
||||
uniform float u_rotation;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec4 u_geometry;
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ float rotation;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _OUT_ vec2 coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
// The -90 is because conics point to the top by default
|
||||
rotation = mod (u_rotation - 90.0, 360.0);
|
||||
if (rotation < 0.0)
|
||||
rotation += 360.0;
|
||||
rotation = PI / 180.0 * rotation;
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_geometry.xy;
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
coord = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -38,32 +21,53 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops; // Why? Because it works like this.
|
||||
#endif
|
||||
|
||||
const float PI = 3.1415926535897932384626433832795;
|
||||
uniform vec4 u_geometry;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ float rotation;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _IN_ vec2 coord;
|
||||
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Position relative to center
|
||||
vec2 pos = gsk_get_frag_coord() - center;
|
||||
|
||||
// direction of point in range [-PI, PI]
|
||||
float angle = atan (pos.y, pos.x);
|
||||
// rotate, it's now [-2 * PI, PI]
|
||||
angle -= rotation;
|
||||
vec2 pos = floor(coord);
|
||||
float angle = atan(pos.y, pos.x);
|
||||
|
||||
// fract() does the modulo here, so now we have progress
|
||||
// into the current conic
|
||||
float offset = fract (angle / 2.0 / PI + 2.0);
|
||||
float offset = fract(angle * u_geometry.z + u_geometry.w);
|
||||
|
||||
vec4 color = color_stops[0];
|
||||
for (int i = 1; i < u_num_color_stops; i ++) {
|
||||
if (offset >= color_offsets[i - 1]) {
|
||||
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
|
||||
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
// VERTEX_SHADER
|
||||
uniform vec2 u_start_point;
|
||||
uniform vec2 u_end_point;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec4 u_points;
|
||||
|
||||
_OUT_ vec2 startPoint;
|
||||
_OUT_ vec2 endPoint;
|
||||
_OUT_ float maxDist;
|
||||
_OUT_ vec2 gradient;
|
||||
_OUT_ float gradientLength;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_NOPERSPECTIVE_ _OUT_ vec4 info;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
|
||||
endPoint = (u_modelview * vec4(u_end_point, 0, 1)).xy;
|
||||
maxDist = length(endPoint - startPoint);
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_points.xy;
|
||||
vec2 coord = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
|
||||
// Gradient direction
|
||||
gradient = endPoint - startPoint;
|
||||
gradientLength = length(gradient);
|
||||
// Original equation:
|
||||
// VS | maxDist = length(end - start);
|
||||
// VS | gradient = end - start;
|
||||
// VS | gradientLength = length(gradient);
|
||||
// FS | pos = frag_coord - start
|
||||
// FS | proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient
|
||||
// FS | offset = length(proj) / maxDist
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
// Simplified formula derivation:
|
||||
// 1. Notice that maxDist = gradientLength:
|
||||
// offset = length(proj) / gradientLength
|
||||
// 2. Let gnorm = gradient / gradientLength, then:
|
||||
// proj = (dot(gnorm * gradientLength, pos) / (gradientLength * gradientLength)) * (gnorm * gradientLength) =
|
||||
// = dot(gnorm, pos) * gnorm
|
||||
// 3. Since gnorm is unit length then:
|
||||
// length(proj) = length(dot(gnorm, pos) * gnorm) = dot(gnorm, pos)
|
||||
// 4. We can avoid the FS division by passing a scaled pos from the VS:
|
||||
// offset = dot(gnorm, pos) / gradientLength = dot(gnorm, pos / gradientLength)
|
||||
// 5. 1.0 / length(gradient) is inversesqrt(dot(gradient, gradient)) in GLSL
|
||||
vec2 gradient = vec2(dot(mv0, u_points.zw),
|
||||
dot(mv1, u_points.zw));
|
||||
float rcp_gradient_length = inversesqrt(dot(gradient, gradient));
|
||||
|
||||
info = rcp_gradient_length * vec4(coord, gradient);
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -39,32 +45,51 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops; // Why? Because it works like this.
|
||||
#endif
|
||||
|
||||
_IN_ vec2 startPoint;
|
||||
_IN_ vec2 endPoint;
|
||||
_IN_ float maxDist;
|
||||
_IN_ vec2 gradient;
|
||||
_IN_ float gradientLength;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform bool u_repeat;
|
||||
|
||||
_NOPERSPECTIVE_ _IN_ vec4 info;
|
||||
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Position relative to startPoint
|
||||
vec2 pos = gsk_get_frag_coord() - startPoint;
|
||||
float offset = dot(info.xy, info.zw);
|
||||
|
||||
// Current pixel, projected onto the line between the start point and the end point
|
||||
// The projection will be relative to the start point!
|
||||
vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;
|
||||
if (u_repeat) {
|
||||
offset = fract(offset);
|
||||
}
|
||||
|
||||
// Offset of the current pixel
|
||||
float offset = length(proj) / maxDist;
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 color = color_stops[0];
|
||||
for (int i = 1; i < u_num_color_stops; i ++) {
|
||||
if (offset >= color_offsets[i - 1]) {
|
||||
float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
|
||||
color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ precision highp float;
|
||||
#if defined(GSK_GLES) || defined(GSK_LEGACY)
|
||||
#define _OUT_ varying
|
||||
#define _IN_ varying
|
||||
#define _NOPERSPECTIVE_
|
||||
#define _GSK_ROUNDED_RECT_UNIFORM_ vec4[3]
|
||||
#else
|
||||
#define _OUT_ out
|
||||
#define _IN_ in
|
||||
#define _NOPERSPECTIVE_ noperspective
|
||||
#define _GSK_ROUNDED_RECT_UNIFORM_ GskRoundedRect
|
||||
#endif
|
||||
|
||||
@@ -39,3 +41,11 @@ gsk_create_rect(vec4[3] data)
|
||||
vec4 gsk_premultiply(vec4 c) {
|
||||
return vec4(c.rgb * c.a, c.a);
|
||||
}
|
||||
|
||||
vec4 gsk_scaled_premultiply(vec4 c, float s) {
|
||||
// Fast version of gsk_premultiply(c) * s
|
||||
// 4 muls instead of 7
|
||||
float a = s * c.a;
|
||||
|
||||
return vec4(c.rgb * a, a);
|
||||
}
|
||||
|
||||
@@ -1,31 +1,18 @@
|
||||
// VERTEX_SHADER
|
||||
uniform float u_start;
|
||||
uniform float u_end;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
uniform int u_num_color_stops;
|
||||
uniform vec2 u_radius;
|
||||
uniform vec2 u_center;
|
||||
uniform vec4 u_geometry;
|
||||
|
||||
_OUT_ vec2 center;
|
||||
_OUT_ vec4 color_stops[6];
|
||||
_OUT_ float color_offsets[6];
|
||||
_OUT_ float start;
|
||||
_OUT_ float end;
|
||||
_NOPERSPECTIVE_ _OUT_ vec2 coord;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
|
||||
gl_Position = u_projection * (u_modelview * vec4(aPosition, 0.0, 1.0));
|
||||
|
||||
center = (u_modelview * vec4(u_center, 0, 1)).xy;
|
||||
start = u_start;
|
||||
end = u_end;
|
||||
vec2 mv0 = u_modelview[0].xy;
|
||||
vec2 mv1 = u_modelview[1].xy;
|
||||
vec2 offset = aPosition - u_geometry.xy;
|
||||
vec2 dir = vec2(dot(mv0, offset),
|
||||
dot(mv1, offset));
|
||||
|
||||
for (int i = 0; i < u_num_color_stops; i ++) {
|
||||
color_offsets[i] = u_color_stops[(i * 5) + 0];
|
||||
color_stops[i] = gsk_premultiply(vec4(u_color_stops[(i * 5) + 1],
|
||||
u_color_stops[(i * 5) + 2],
|
||||
u_color_stops[(i * 5) + 3],
|
||||
u_color_stops[(i * 5) + 4]));
|
||||
}
|
||||
coord = dir * u_geometry.zw;
|
||||
}
|
||||
|
||||
// FRAGMENT_SHADER:
|
||||
@@ -35,50 +22,53 @@ uniform int u_num_color_stops;
|
||||
uniform highp int u_num_color_stops;
|
||||
#endif
|
||||
|
||||
uniform vec2 u_radius;
|
||||
uniform float u_end;
|
||||
uniform bool u_repeat;
|
||||
uniform vec2 u_range;
|
||||
uniform float u_color_stops[6 * 5];
|
||||
|
||||
_IN_ vec2 center;
|
||||
_IN_ vec4 color_stops[6];
|
||||
_IN_ float color_offsets[6];
|
||||
_IN_ float start;
|
||||
_IN_ float end;
|
||||
_NOPERSPECTIVE_ _IN_ vec2 coord;
|
||||
|
||||
// The offsets in the color stops are relative to the
|
||||
// start and end values of the gradient.
|
||||
float abs_offset(float offset) {
|
||||
return start + ((end - start) * offset);
|
||||
float get_offset(int index) {
|
||||
return u_color_stops[5 * index];
|
||||
}
|
||||
|
||||
vec4 get_color(int index) {
|
||||
int base = 5 * index + 1;
|
||||
|
||||
return vec4(u_color_stops[base],
|
||||
u_color_stops[base + 1],
|
||||
u_color_stops[base + 2],
|
||||
u_color_stops[base + 3]);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 pixel = gsk_get_frag_coord();
|
||||
vec2 rel = (center - pixel) / (u_radius);
|
||||
float d = sqrt(dot(rel, rel));
|
||||
// Reverse scale
|
||||
float offset = length(coord) * u_range.x + u_range.y;
|
||||
|
||||
if (d < abs_offset (color_offsets[0])) {
|
||||
gskSetOutputColor(color_stops[0] * u_alpha);
|
||||
if (u_repeat) {
|
||||
offset = fract(offset);
|
||||
}
|
||||
|
||||
if (offset < get_offset(0)) {
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(0), u_alpha));
|
||||
return;
|
||||
}
|
||||
|
||||
if (d > end) {
|
||||
gskSetOutputColor(color_stops[u_num_color_stops - 1] * u_alpha);
|
||||
return;
|
||||
}
|
||||
int n = u_num_color_stops - 1;
|
||||
for (int i = 0; i < n; i++) {
|
||||
float curr_offset = get_offset(i);
|
||||
float next_offset = get_offset(i + 1);
|
||||
|
||||
vec4 color = vec4(0, 0, 0, 0);
|
||||
for (int i = 1; i < u_num_color_stops; i++) {
|
||||
float last_offset = abs_offset(color_offsets[i - 1]);
|
||||
float this_offset = abs_offset(color_offsets[i]);
|
||||
if (offset >= curr_offset && offset < next_offset) {
|
||||
float f = (offset - curr_offset) / (next_offset - curr_offset);
|
||||
vec4 curr_color = gsk_premultiply(get_color(i));
|
||||
vec4 next_color = gsk_premultiply(get_color(i + 1));
|
||||
vec4 color = mix(curr_color, next_color, f);
|
||||
|
||||
// We have color_stops[i - 1] at last_offset and color_stops[i] at this_offset.
|
||||
// We now need to map `d` between those two offsets and simply mix linearly between them
|
||||
if (d >= last_offset && d <= this_offset) {
|
||||
float f = (d - last_offset) / (this_offset - last_offset);
|
||||
|
||||
color = mix(color_stops[i - 1], color_stops[i], f);
|
||||
break;
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gskSetOutputColor(color * u_alpha);
|
||||
gskSetOutputColor(gsk_scaled_premultiply(get_color(n), u_alpha));
|
||||
}
|
||||
|
||||
@@ -718,7 +718,7 @@ gsk_vulkan_image_upload_regions (GskVulkanImage *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (gsize r = 0; r < regions[i].height; i++)
|
||||
for (gsize r = 0; r < regions[i].height; r++)
|
||||
memcpy (m + r * regions[i].width * 4, regions[i].data + r * regions[i].stride, regions[i].width * 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,11 +51,36 @@ any license fees or royalties.</description>
|
||||
<gnome:userid>matthiasc</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Tim Janik</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:timj@gtk.org"/>
|
||||
<gnome:userid>timj</gnome:userid>
|
||||
<foaf:name>Emmanuele Bassi</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:ebassi@gnome.org"/>
|
||||
<gnome:userid>ebassi</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Timm Baeder</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:mail@baedert.org"/>
|
||||
<gnome:userid>baedert</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Benjamin Otte</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:otte@gnome.org"/>
|
||||
<gnome:userid>otte</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Carlos Garnacho</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:carlosg@gnome.org"/>
|
||||
<gnome:userid>carlosg</gnome:userid>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
|
||||
@@ -68,10 +68,8 @@ action_handle_method (GtkAtSpiContext *self,
|
||||
|
||||
g_variant_get (parameters, "(i)", &idx);
|
||||
|
||||
const Action *action = &actions[idx];
|
||||
|
||||
if (idx >= 0 && idx < n_actions)
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->name));
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].name));
|
||||
else
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_IO_ERROR,
|
||||
@@ -129,10 +127,8 @@ action_handle_method (GtkAtSpiContext *self,
|
||||
|
||||
g_variant_get (parameters, "(i)", &idx);
|
||||
|
||||
const Action *action = &actions[idx];
|
||||
|
||||
if (idx >= 0 && idx < n_actions)
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", action->keybinding));
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", actions[idx].keybinding));
|
||||
else
|
||||
g_dbus_method_invocation_return_error (invocation,
|
||||
G_IO_ERROR,
|
||||
|
||||
@@ -58,6 +58,9 @@ struct _GtkAtSpiCache
|
||||
|
||||
/* HashTable<GtkAtSpiContext, str> */
|
||||
GHashTable *contexts_to_path;
|
||||
|
||||
/* Re-entrancy guard */
|
||||
gboolean in_get_items;
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -250,10 +253,17 @@ handle_cache_method (GDBusConnection *connection,
|
||||
{
|
||||
GVariantBuilder builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(" GET_ITEMS_SIGNATURE ")"));
|
||||
|
||||
/* Prevent the emission os signals while collecting accessible
|
||||
* objects as the result of walking the accessible tree
|
||||
*/
|
||||
self->in_get_items = TRUE;
|
||||
|
||||
g_variant_builder_open (&builder, G_VARIANT_TYPE (GET_ITEMS_SIGNATURE));
|
||||
collect_cached_objects (self, &builder);
|
||||
g_variant_builder_close (&builder);
|
||||
|
||||
self->in_get_items = FALSE;
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
|
||||
}
|
||||
}
|
||||
@@ -371,7 +381,11 @@ gtk_at_spi_cache_add_context (GtkAtSpiCache *self,
|
||||
|
||||
GTK_NOTE (A11Y, g_message ("Adding context '%s' to cache", path_key));
|
||||
|
||||
emit_add_accessible (self, context);
|
||||
/* GetItems is safe from re-entrancy, but we still don't want to
|
||||
* emit an unnecessary signal while we're collecting ATContexts
|
||||
*/
|
||||
if (!self->in_get_items)
|
||||
emit_add_accessible (self, context);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -667,11 +667,21 @@ gtk_at_spi_root_constructed (GObject *gobject)
|
||||
{
|
||||
const char *program_name = g_get_prgname ();
|
||||
|
||||
char *base_name = NULL;
|
||||
if (program_name == NULL || *program_name == 0)
|
||||
base_name = g_strdup ("unknown");
|
||||
else if (*program_name == '/')
|
||||
base_name = g_path_get_basename (program_name);
|
||||
else
|
||||
base_name = g_strdup (program_name);
|
||||
|
||||
self->base_path = g_strconcat ("/org/gtk/application/",
|
||||
program_name != NULL ? program_name : "unknown",
|
||||
base_name,
|
||||
"/a11y",
|
||||
NULL);
|
||||
|
||||
g_free (base_name);
|
||||
|
||||
/* Turn potentially invalid program names into something that can be
|
||||
* used as a DBus path
|
||||
*/
|
||||
|
||||