Compare commits
469 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 20422f98ab | |||
| ebfdd71a3e | |||
| 56069698b1 | |||
| c86a4222a9 | |||
| 16d09f154e | |||
| 67fdc4f533 | |||
| 7e2fceebca | |||
| 1e00c887ec | |||
| 561d3c68a0 | |||
| 03601cb794 | |||
| 3108b8b4d3 | |||
| d1afe32762 | |||
| 603dd72b09 | |||
| e81ba8924a | |||
| 8832ab45d9 | |||
| 87d6e17bc7 | |||
| a5033cd79b | |||
| 44cbf3d605 | |||
| fb6288791e | |||
| 2160f52cbf | |||
| 8825e621c9 | |||
| e22abd73f2 | |||
| f77d4d7fc0 | |||
| 8243133ca7 | |||
| 63a4345d2c | |||
| 56685a483d | |||
| b23f793753 | |||
| 2b19e2fc1f | |||
| 703f8b8136 | |||
| 5b18968867 | |||
| e8c4e1205a | |||
| bf5c540357 | |||
| c03383d3e5 | |||
| eaaa287078 | |||
| 554defaf1a | |||
| 659fe52b7b | |||
| 0970077af9 | |||
| 814c88fbc1 | |||
| 3b24c8a0a4 | |||
| e34c7e6796 | |||
| 8c608e9c1c | |||
| 283c3b70dd | |||
| 93599c2c48 | |||
| 080e625090 | |||
| 26696a741e | |||
| a209e54b8f | |||
| 8921dadaa1 | |||
| 47232acbd8 | |||
| cbad8ec2e4 | |||
| 800170b47d | |||
| 97c5cb3514 | |||
| 081afc0477 | |||
| e807fc3be0 | |||
| a1bd3389ed | |||
| 03a3b5a0b1 | |||
| 1ee2d9a5fa | |||
| 2e07fcd680 | |||
| d3365d5a60 | |||
| 9dbf99d91a | |||
| 0154a7f528 | |||
| add47bebc6 | |||
| 514b62223d | |||
| 7884ab6161 | |||
| bc542c5304 | |||
| d66ac4981e | |||
| 9b647a47d1 | |||
| b67ffe9650 | |||
| 2c519b006d | |||
| 852429d163 | |||
| ee9c6bbf75 | |||
| d9ece94377 | |||
| 486fbce42b | |||
| ed92026632 | |||
| 05e614feb7 | |||
| 14059afdf1 | |||
| 9b294eb94e | |||
| 96d42cf1cc | |||
| 4786a16696 | |||
| 14bb12125f | |||
| 07e8dafcea | |||
| ab67a81f11 | |||
| aa76f7e210 | |||
| 0c15463e41 | |||
| 5df1356295 | |||
| 95fc81c565 | |||
| 378e594f75 | |||
| 86c7fceb09 | |||
| b5e20a3e37 | |||
| 75a30b1f98 | |||
| c64a021af4 | |||
| 9b64635925 | |||
| 7b76be5360 | |||
| 2e2336ffce | |||
| 76d80ef516 | |||
| 287d80bd36 | |||
| 77072b3eaa | |||
| c7833bb090 | |||
| 899024cef7 | |||
| 4da3edd42e | |||
| 6b59626817 | |||
| 7c02ae00c2 | |||
| 80e29a3627 | |||
| 26163a4f30 | |||
| dbd88fc210 | |||
| 2de31e4cac | |||
| 1bff328895 | |||
| facf78a5b6 | |||
| 6b19fcd859 | |||
| ca784e3e1a | |||
| 314c8558d7 | |||
| af30a7fe06 | |||
| 9ffd7d1970 | |||
| cb906c80eb | |||
| 96ce0eb600 | |||
| 0e476c1f28 | |||
| f2924988db | |||
| 671435e07f | |||
| b17cfb9b65 | |||
| 0385f1aaf4 | |||
| 8611faf338 | |||
| 7e19911d3f | |||
| c1f5153f6d | |||
| 2bd87ce771 | |||
| de0547ede7 | |||
| 14589c2a59 | |||
| f678b3804d | |||
| 720c298786 | |||
| f721d2de15 | |||
| 11f07cb5ad | |||
| 37d7ab88dc | |||
| 6cde64072d | |||
| 6a60b0f591 | |||
| 339d9f05e4 | |||
| 4e4207457f | |||
| 46bb3e3046 | |||
| 34008e6aab | |||
| d6b3ac850d | |||
| 9742200ff6 | |||
| ec10857b84 | |||
| 353d4d161c | |||
| bcd650f169 | |||
| 72d66dfcdd | |||
| 5e97df5058 | |||
| 059d131e2b | |||
| 8f7c207c7c | |||
| b9e8935037 | |||
| 5f33f4ae8e | |||
| adf0e8b1e6 | |||
| 7500f9b255 | |||
| a8d433dd26 | |||
| ecaf6fced0 | |||
| 31a7cac4a6 | |||
| 5eec736b07 | |||
| cf4a8e2152 | |||
| 31bb969cce | |||
| f4a7c7f6bf | |||
| 495069c868 | |||
| dfe470475b | |||
| de56e892aa | |||
| e518c1f2f3 | |||
| c5ea59d7d1 | |||
| 22eccbdbb6 | |||
| 58e85c85e4 | |||
| 6b89148487 | |||
| ddb9e428ec | |||
| b7fa353db2 | |||
| 87b5eadb7c | |||
| 60a09e59e8 | |||
| 6f8e9bf3a9 | |||
| 90b7b84337 | |||
| 088b5fc57f | |||
| a4cd974912 | |||
| 65359dcc59 | |||
| ac8b398c50 | |||
| aac2417893 | |||
| ad8892df10 | |||
| edc7977c4e | |||
| 8bf8ac5076 | |||
| c36cbd5140 | |||
| ee96bc7185 | |||
| f94f325636 | |||
| 6c1217dd93 | |||
| edb792503b | |||
| 3a43859286 | |||
| c55dd104d4 | |||
| 497d137fb8 | |||
| df01c5c7a4 | |||
| 2d1135fba6 | |||
| f54ed6f7dc | |||
| b7efd896b6 | |||
| 46eb51bc30 | |||
| 500dbaabc3 | |||
| 594ec3d822 | |||
| f280508209 | |||
| 480b88c776 | |||
| a4e63905b1 | |||
| 5666127dbc | |||
| c1c110ba65 | |||
| eb2a839892 | |||
| 1c537a6d2e | |||
| c12261a6ec | |||
| 5af7d6bff3 | |||
| de0f4b0f5b | |||
| 966ab1152d | |||
| 74a4432688 | |||
| 115d0cdc07 | |||
| d0ec616fba | |||
| 38cce2bb18 | |||
| 9cb7002b98 | |||
| eb9c91c0a9 | |||
| be07153efa | |||
| 627ec82e60 | |||
| ccc34ca06c | |||
| 2b5dd0082d | |||
| 7b36b339aa | |||
| b7eb663b82 | |||
| 1b28353be5 | |||
| a07c030d02 | |||
| 339cccdf53 | |||
| 577126e99c | |||
| 125ea5ee4a | |||
| 3c5afc06d1 | |||
| f87c15f4f9 | |||
| fe5c0e2fe3 | |||
| c8421cfd82 | |||
| fbf99b8d65 | |||
| 57312c9b79 | |||
| 35d2539ef8 | |||
| 08a4f4552c | |||
| 6502d3669f | |||
| 53831e67a7 | |||
| e742fc1206 | |||
| 4ef5ee23e6 | |||
| 4a8330fda0 | |||
| b4096cee64 | |||
| 032302c358 | |||
| a888e1cb65 | |||
| c80b33b2ad | |||
| f32239df1f | |||
| 22c1b541df | |||
| 78a59c95fe | |||
| 7583d48266 | |||
| f1188aaeac | |||
| 4dac5c222f | |||
| 0145809a94 | |||
| 2e6b8810c0 | |||
| d8abcdb5a1 | |||
| 65ecfa20dd | |||
| aa5ab02166 | |||
| 7ddbbb50ff | |||
| f2eb036119 | |||
| 8a8b96bf4b | |||
| bdcda2d8f0 | |||
| ef3f997d55 | |||
| b41d380230 | |||
| 0210850e86 | |||
| 053223bf65 | |||
| 746b84cc0f | |||
| f1ad883e00 | |||
| 191e0e8d5e | |||
| 55217e2181 | |||
| 7c8cd23c5f | |||
| 6aafb81702 | |||
| 0578422612 | |||
| ad04da84c9 | |||
| 333b013f7f | |||
| b3dc517565 | |||
| 70e4dabe89 | |||
| d3443d6f2a | |||
| a508f68044 | |||
| f191b64bbc | |||
| e9efe77839 | |||
| d98c0d32f2 | |||
| dfa2dcceb8 | |||
| d441e7106b | |||
| 4cd92f979c | |||
| d1a068e5b1 | |||
| 4d90846182 | |||
| 986f721938 | |||
| 7903246355 | |||
| 0252ae2be3 | |||
| fa90e42a38 | |||
| 2d36109565 | |||
| de8258171a | |||
| 2ed6224778 | |||
| e1a0171094 | |||
| 395521f3d3 | |||
| 8c95a84ea4 | |||
| 75db19c789 | |||
| f00d2b30bb | |||
| c0c5ce2f9b | |||
| ee9f9ae05e | |||
| 387649ded4 | |||
| be12131d74 | |||
| 896ebdc9d7 | |||
| bc58bd0b83 | |||
| 8d4c87876b | |||
| cebc99ddc7 | |||
| 1b62203f18 | |||
| 06dd8c2cfd | |||
| 5da21ca4dc | |||
| 3e16ef33b0 | |||
| 2746a2d929 | |||
| e31bacf7be | |||
| 911ae64931 | |||
| 99a0b35705 | |||
| 89bf8af878 | |||
| f3744c991a | |||
| dcee15c0f1 | |||
| 2321e9de05 | |||
| 73dcda460f | |||
| 0f8bc67a98 | |||
| 379d830123 | |||
| bc8bc68b80 | |||
| 8c4df51a14 | |||
| 06d67d2384 | |||
| cc8bb5fc54 | |||
| 8fb1e33d0f | |||
| 0dc946da63 | |||
| 26a23d3e56 | |||
| 766f4bc8fe | |||
| 3d008d5929 | |||
| 0546e26434 | |||
| e6d8eedc00 | |||
| 13b37b0ba4 | |||
| 779c71b66d | |||
| 8e73d007f5 | |||
| e376d638fb | |||
| 52982a88aa | |||
| 422c1d9c0d | |||
| ccc8ad8700 | |||
| 6b0eb970d8 | |||
| 775e35865c | |||
| 49ce680d53 | |||
| 463f3d3a52 | |||
| f6347f18b0 | |||
| 2e959fe300 | |||
| 56f771ba29 | |||
| 32e96215b4 | |||
| 86f800e11d | |||
| 4d371b2b16 | |||
| 7e97c2513f | |||
| 2bf5a150e6 | |||
| 18c87faaa5 | |||
| fdeda388bf | |||
| ea2c27c640 | |||
| dfc04a590d | |||
| fe5b364675 | |||
| 9b73c55559 | |||
| 0b38a0663d | |||
| e5c0716293 | |||
| 54a3293cad | |||
| 818287a7ce | |||
| 59119cd898 | |||
| 817da34f7e | |||
| 8fa44fc3e6 | |||
| c7e94151b2 | |||
| 729ba44297 | |||
| 2a2a6879c5 | |||
| e7b773b031 | |||
| 57a225681c | |||
| ea07a92366 | |||
| 76290e8ddb | |||
| 26d83b1ab7 | |||
| 2bba856206 | |||
| bf3382a89e | |||
| 3162e25671 | |||
| 3d931b4fe2 | |||
| fc770a383a | |||
| 62c385a9dd | |||
| 7c4ad1a5c4 | |||
| ac524bb13a | |||
| 66fa9380b5 | |||
| b64eb6ca13 | |||
| 9b2d8ac362 | |||
| 2a90bc1a9b | |||
| d4b868d9bc | |||
| b54f6710a7 | |||
| 6bb7caf155 | |||
| 202348f9d0 | |||
| 1a613de2f6 | |||
| 665df37703 | |||
| acad5e4e3d | |||
| 6267c8469b | |||
| 5a2f791bdd | |||
| 286a00a1db | |||
| 11dd602b28 | |||
| 35988d659d | |||
| be3449b3ce | |||
| 2d8fddc1e9 | |||
| 644d522d19 | |||
| a8b0125da1 | |||
| acccac516e | |||
| d65214fa4e | |||
| 1d96fc8237 | |||
| 882a87ca19 | |||
| 1dbb8df95f | |||
| f6c2c2edbd | |||
| c4e4de36f6 | |||
| 67cbb2a7d3 | |||
| a979daa8ea | |||
| fb14f50ec1 | |||
| 6099fbafc1 | |||
| 6f2f828bce | |||
| 795d3122cc | |||
| 5080730728 | |||
| f75a3a0e95 | |||
| b75db7d1c6 | |||
| b03069bdf6 | |||
| 1c71e56e75 | |||
| 9332d0dcc8 | |||
| 9ad37583e6 | |||
| 69975627e9 | |||
| b74a489aba | |||
| 599b807726 | |||
| 6510ca8bdd | |||
| be20a04e04 | |||
| 92e5536335 | |||
| c2da2f7ecd | |||
| 130bd5937c | |||
| 54bfd380a8 | |||
| f01d695e6c | |||
| 619b2465c1 | |||
| cc18191a8e | |||
| 1f8e7c8aab | |||
| 671daea262 | |||
| 76533513c2 | |||
| 0d3988365b | |||
| 0966636803 | |||
| 7c3b30036e | |||
| 988901294d | |||
| 43b9fc6981 | |||
| 25f670faae | |||
| d0068a036f | |||
| fae014eb45 | |||
| f0ea0be15d | |||
| 9650236b23 | |||
| c0e2d7c62f | |||
| cc072eb7cd | |||
| 613213f597 | |||
| e25c25fcb5 | |||
| 52666d6fe5 | |||
| 56b3669411 | |||
| e3b5b76cdd | |||
| bbb28196e5 | |||
| 72d3a9042c | |||
| f2853ffa8e | |||
| fca2ba963d | |||
| 806779769e | |||
| 82aa0d1f7c | |||
| 72f1d34eca | |||
| c267a75eef | |||
| 2fb755e0c9 | |||
| cd096819d8 | |||
| 83543423e2 | |||
| d0bb72a2aa | |||
| 8cc2a44268 | |||
| 4800dd3f95 | |||
| 2534310ce9 | |||
| 3a4fbc5e50 | |||
| 89a67ac719 | |||
| 21b84b1890 | |||
| 20935f678b | |||
| c41b4130c6 | |||
| f1b010af66 | |||
| ec1133d6e1 | |||
| 8fcf1b78a4 | |||
| 21f9148155 | |||
| d4f0593b37 |
+18
-2
@@ -19,8 +19,8 @@ variables:
|
||||
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true -Dvulkan=yes"
|
||||
FEATURE_FLAGS: "-Dcloudproviders=true"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 2
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v17"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v20"
|
||||
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
|
||||
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
|
||||
|
||||
@@ -180,6 +180,22 @@ static-scan:
|
||||
- _scan_build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
# Run tests with the address sanitizer. We need to turn off introspection,
|
||||
# since it is incompatible with asan
|
||||
asan-build:
|
||||
image: $FEDORA_IMAGE
|
||||
tags: [ asan ]
|
||||
stage: analysis
|
||||
variables:
|
||||
script:
|
||||
- CC=clang meson --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=false _build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
artifacts:
|
||||
paths:
|
||||
- _build/meson-logs
|
||||
allow_failure: true
|
||||
|
||||
reference:
|
||||
image: $DOCS_IMAGE
|
||||
stage: docs
|
||||
|
||||
@@ -35,4 +35,13 @@ branch, as well as their available versions.
|
||||
- [ ] Add the new job to `.gitlab-ci.yml` referencing the image
|
||||
- [ ] Open a merge request with your changes and let it run
|
||||
|
||||
### Checklist for Adding a new dependency to a CI image
|
||||
|
||||
Our images are layered, and the base (called fedora-base) contains
|
||||
all the rpm payload. Therefore, adding a new dependency is a 2-step
|
||||
process:
|
||||
|
||||
1. [ ] Build and upload fedora-base:$version+1
|
||||
1. [ ] Build and upload fedora:$version+1 based on fedora-base:version+1
|
||||
|
||||
[registry]: https://gitlab.gnome.org/GNOME/gtk/container_registry
|
||||
|
||||
@@ -41,12 +41,14 @@ RUN dnf -y install \
|
||||
itstool \
|
||||
json-glib-devel \
|
||||
lcov \
|
||||
libasan \
|
||||
libattr-devel \
|
||||
libepoxy-devel \
|
||||
libffi-devel \
|
||||
libmount-devel \
|
||||
librsvg2 \
|
||||
libselinux-devel \
|
||||
libubsan \
|
||||
libXcomposite-devel \
|
||||
libXcursor-devel \
|
||||
libXcursor-devel \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v19
|
||||
FROM registry.gitlab.gnome.org/gnome/gtk/fedora-base:v20
|
||||
|
||||
ARG HOST_USER_ID=5555
|
||||
ENV HOST_USER_ID ${HOST_USER_ID}
|
||||
|
||||
@@ -7,10 +7,14 @@ srcdir=$( pwd )
|
||||
builddir=$1
|
||||
backend=$2
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp
|
||||
|
||||
case "${backend}" in
|
||||
x11)
|
||||
xvfb-run -a -s "-screen 0 1024x768x24" \
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -30,6 +34,7 @@ case "${backend}" in
|
||||
export WAYLAND_DISPLAY=wayland-5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -48,6 +53,7 @@ case "${backend}" in
|
||||
export BROADWAY_DISPLAY=:5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
|
||||
@@ -1,3 +1,89 @@
|
||||
Overview of Changes in GTK 3.99.0
|
||||
=================================
|
||||
|
||||
* Add GtkEditableLabel, a label that can be edited
|
||||
|
||||
* Add GtkBookmarkList, a list model for bookmarks
|
||||
|
||||
* Add GtkStringList, a list model for strings
|
||||
|
||||
* Add GtkBitset, and use it for representing selections
|
||||
|
||||
* GtkTreeView:
|
||||
- Make cell editing work again
|
||||
|
||||
* GtkSpinButton:
|
||||
- Make autosizing work again
|
||||
|
||||
* Printing:
|
||||
- Use GtkDropDown in the print dialog
|
||||
|
||||
* GtkApplication
|
||||
- Support opening files on OS X
|
||||
|
||||
* GtkFileChooser:
|
||||
- Fix libcloudproviders support
|
||||
- Turn GtkFileFilter into a GtkFilter
|
||||
- Simplify the api
|
||||
|
||||
* GtkGridView, GtkListView:
|
||||
- Improve scrolling behavior
|
||||
- Autoscroll and autoexpand during DND
|
||||
|
||||
* GtkScrolledWindow:
|
||||
- Make autoscrolling work again
|
||||
|
||||
* GtkFilterListModel:
|
||||
- Add incremental filtering
|
||||
|
||||
* GtkSortListModel:
|
||||
- Use timsort
|
||||
- Add various tweaks that massively speed up sorting
|
||||
- Add incremental sorting
|
||||
|
||||
* GtkWidget:
|
||||
- Massively speed up action handling
|
||||
|
||||
* GtkEntry:
|
||||
- Make entry completion work again
|
||||
- Drop action support from GtkEntryCompletion
|
||||
|
||||
* Inspector:
|
||||
- Improve list model support
|
||||
- Add direct navigation between objects
|
||||
|
||||
* GDK:
|
||||
- Compress scroll events
|
||||
- Keep a scroll history
|
||||
- Clean up GdkDevice api
|
||||
- Improve frame clock accuracy
|
||||
- Add a new macOS backend
|
||||
|
||||
* GSK:
|
||||
- Use GL_ARB_framebuffer_object
|
||||
|
||||
* gtk-demo:
|
||||
- Add incremental refill to the color grid
|
||||
- Improve performance of the color grid
|
||||
- Add an incrementally filtering word list
|
||||
- Improve the sidebar
|
||||
|
||||
* Install print-editor as another demo
|
||||
|
||||
* Translation updates
|
||||
Basque
|
||||
Catalan
|
||||
Chinese
|
||||
Japanese
|
||||
Kazakh
|
||||
Lithuanian
|
||||
Polish
|
||||
Romanian
|
||||
Spanish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in GTK 3.98.5
|
||||
=================================
|
||||
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
{
|
||||
"app-id": "org.gtk.WidgetFactory4",
|
||||
"runtime": "org.gnome.Platform",
|
||||
"runtime-version": "master",
|
||||
"sdk": "org.gnome.Sdk",
|
||||
"command": "gtk4-widget-factory",
|
||||
"tags": ["devel", "development", "nightly"],
|
||||
"desktop-file-name-prefix": "(Development) ",
|
||||
"finish-args": [
|
||||
"app-id" : "org.gtk.WidgetFactory4",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "master",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"command" : "gtk4-widget-factory",
|
||||
"tags" : [
|
||||
"devel",
|
||||
"development",
|
||||
"nightly"
|
||||
],
|
||||
"desktop-file-name-prefix" : "(Development) ",
|
||||
"finish-args" : [
|
||||
"--device=dri",
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*"
|
||||
"--talk-name=org.gtk.vfs",
|
||||
"--talk-name=org.gtk.vfs.*"
|
||||
],
|
||||
"cleanup": [
|
||||
"cleanup" : [
|
||||
"/include",
|
||||
"/lib/pkgconfig", "/share/pkgconfig",
|
||||
"/lib/pkgconfig",
|
||||
"/share/pkgconfig",
|
||||
"/share/aclocal",
|
||||
"/man", "/share/man", "/share/gtk-doc",
|
||||
"*.la", ".a",
|
||||
"/man",
|
||||
"/share/man",
|
||||
"/share/gtk-doc",
|
||||
"*.la",
|
||||
".a",
|
||||
"/lib/girepository-1.0",
|
||||
"/share/gir-1.0",
|
||||
"/share/doc"
|
||||
],
|
||||
"modules": [
|
||||
"modules" : [
|
||||
{
|
||||
"name" : "wayland",
|
||||
"buildsystem" : "autotools",
|
||||
@@ -39,18 +48,18 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "graphene",
|
||||
"buildsystem": "meson",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"name" : "graphene",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib",
|
||||
"-Dtests=false",
|
||||
"-Dbenchmarks=false"
|
||||
],
|
||||
"sources": [
|
||||
"sources" : [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/ebassi/graphene.git"
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/ebassi/graphene.git"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -58,7 +67,7 @@
|
||||
"name" : "libsass",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
@@ -73,7 +82,7 @@
|
||||
"name" : "sassc",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts": [
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources" : [
|
||||
@@ -85,18 +94,23 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "gtk",
|
||||
"buildsystem": "meson",
|
||||
"builddir": true,
|
||||
"config-opts": [
|
||||
"name" : "gtk",
|
||||
"buildsystem" : "meson",
|
||||
"builddir" : true,
|
||||
"config-opts" : [
|
||||
"--libdir=/app/lib"
|
||||
],
|
||||
"sources": [
|
||||
"sources" : [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://gitlab.gnome.org/GNOME/gtk.git"
|
||||
"type" : "git",
|
||||
"url" : "https://gitlab.gnome.org/GNOME/gtk.git"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"build-options" : {
|
||||
"env" : {
|
||||
"DBUS_SESSION_BUS_ADDRESS" : "''"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,13 @@ if 'DESTDIR' not in os.environ:
|
||||
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
|
||||
|
||||
print('Compiling GSettings schemas...')
|
||||
subprocess.call(['glib-compile-schemas',
|
||||
glib_compile_schemas = subprocess.check_output(['pkg-config',
|
||||
'--variable=glib_compile_schemas',
|
||||
'gio-2.0']).strip()
|
||||
if not os.path.exists(glib_compile_schemas):
|
||||
# pkg-config variables only available since GLib 2.62.0.
|
||||
glib_compile_schemas = 'glib-compile-schemas'
|
||||
subprocess.call([glib_compile_schemas,
|
||||
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
|
||||
|
||||
print('Updating icon cache...')
|
||||
@@ -24,8 +30,14 @@ if 'DESTDIR' not in os.environ:
|
||||
|
||||
print('Updating module cache for print backends...')
|
||||
os.makedirs(gtk_printmodule_dir, exist_ok=True)
|
||||
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
|
||||
gio_querymodules = subprocess.check_output(['pkg-config',
|
||||
'--variable=gio_querymodules',
|
||||
'gio-2.0']).strip()
|
||||
if not os.path.exists(gio_querymodules):
|
||||
# pkg-config variables only available since GLib 2.62.0.
|
||||
gio_querymodules = 'gio-querymodules'
|
||||
subprocess.call([gio_querymodules, gtk_printmodule_dir])
|
||||
|
||||
print('Updating module cache for input methods...')
|
||||
os.makedirs(gtk_immodule_dir, exist_ok=True)
|
||||
subprocess.call(['gio-querymodules', gtk_immodule_dir])
|
||||
subprocess.call([gio_querymodules, gtk_immodule_dir])
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -188,7 +188,7 @@ constraint_view_init (ConstraintView *self)
|
||||
g_list_store_append (list, children);
|
||||
g_list_store_append (list, guides);
|
||||
g_list_store_append (list, constraints);
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_TYPE_OBJECT, G_LIST_MODEL (list)));
|
||||
self->model = G_LIST_MODEL (gtk_flatten_list_model_new (G_LIST_MODEL (list)));
|
||||
g_object_unref (children);
|
||||
g_object_unref (guides);
|
||||
g_object_unref (constraints);
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
</gresource>
|
||||
<gresource prefix="/listview_colors">
|
||||
<file compressed="true">color.names.txt</file>
|
||||
<file>listview_colors.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
@@ -225,6 +226,7 @@
|
||||
<file>listview_minesweeper.c</file>
|
||||
<file>listview_settings.c</file>
|
||||
<file>listview_weather.c</file>
|
||||
<file>listview_words.c</file>
|
||||
<file>list_store.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>modelbutton.c</file>
|
||||
|
||||
+78
-12
@@ -597,6 +597,83 @@ css_button_new (const char *class)
|
||||
return button;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
GdkRGBA color;
|
||||
} ColorSwatch;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
} ColorSwatchClass;
|
||||
|
||||
G_DEFINE_TYPE (ColorSwatch, color_swatch, GTK_TYPE_WIDGET)
|
||||
|
||||
static GdkContentProvider *
|
||||
color_swatch_drag_prepare (GtkDragSource *source,
|
||||
double x,
|
||||
double y,
|
||||
ColorSwatch *swatch)
|
||||
{
|
||||
return gdk_content_provider_new_typed (GDK_TYPE_RGBA, &swatch->color);
|
||||
}
|
||||
|
||||
static void
|
||||
color_swatch_init (ColorSwatch *swatch)
|
||||
{
|
||||
GtkDragSource *source = gtk_drag_source_new ();
|
||||
g_signal_connect (source, "prepare", G_CALLBACK (color_swatch_drag_prepare), swatch);
|
||||
gtk_widget_add_controller (GTK_WIDGET (swatch), GTK_EVENT_CONTROLLER (source));
|
||||
}
|
||||
|
||||
static void
|
||||
color_swatch_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
ColorSwatch *swatch = (ColorSwatch *)widget;
|
||||
float w = gtk_widget_get_width (widget);
|
||||
float h = gtk_widget_get_height (widget);
|
||||
|
||||
gtk_snapshot_append_color (snapshot, &swatch->color,
|
||||
&GRAPHENE_RECT_INIT(0, 0, w, h));
|
||||
}
|
||||
|
||||
void
|
||||
color_swatch_measure (GtkWidget *widget,
|
||||
GtkOrientation orientation,
|
||||
int for_size,
|
||||
int *minimum_size,
|
||||
int *natural_size,
|
||||
int *minimum_baseline,
|
||||
int *natural_baseline)
|
||||
{
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
*minimum_size = *natural_size = 48;
|
||||
else
|
||||
*minimum_size = *natural_size = 32;
|
||||
}
|
||||
|
||||
static void
|
||||
color_swatch_class_init (ColorSwatchClass *class)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
|
||||
widget_class->snapshot = color_swatch_snapshot;
|
||||
widget_class->measure = color_swatch_measure;
|
||||
gtk_widget_class_set_css_name (widget_class, "colorswatch");
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
color_swatch_new (const char *color)
|
||||
{
|
||||
ColorSwatch *swatch = g_object_new (color_swatch_get_type (), NULL);
|
||||
|
||||
gdk_rgba_parse (&swatch->color, color);
|
||||
|
||||
return GTK_WIDGET (swatch);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
@@ -670,18 +747,7 @@ do_dnd (GtkWidget *do_widget)
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), box3);
|
||||
|
||||
for (i = 0; colors[i]; i++)
|
||||
{
|
||||
GdkRGBA rgba;
|
||||
GtkWidget *swatch;
|
||||
|
||||
gdk_rgba_parse (&rgba, colors[i]);
|
||||
|
||||
swatch = g_object_new (g_type_from_name ("GtkColorSwatch"),
|
||||
"rgba", &rgba,
|
||||
"selectable", FALSE,
|
||||
NULL);
|
||||
gtk_box_append (GTK_BOX (box3), swatch);
|
||||
}
|
||||
gtk_box_append (GTK_BOX (box3), color_swatch_new (colors[i]));
|
||||
|
||||
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow1"));
|
||||
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow2"));
|
||||
|
||||
+244
-29
@@ -1,13 +1,15 @@
|
||||
/* Drop Downs
|
||||
/* Lists/Selections
|
||||
*
|
||||
* The GtkDropDown widget is a modern alternative to GtkComboBox.
|
||||
* It uses list models instead of tree models, and the content is
|
||||
* displayed using widgets instead of cell renderers.
|
||||
* The GtkDropDown and GtkSuggestionEntry widgets are modern
|
||||
* alternatives to GtkComboBox and GtkEntryCompletion.
|
||||
*
|
||||
* They use list models instead of tree models, and the content
|
||||
* is displayed using widgets instead of cell renderers.
|
||||
*
|
||||
* The examples here demonstrate how to use different kinds of
|
||||
* list models with GtkDropDown, how to use search and how to
|
||||
* display the selected item differently from the presentation
|
||||
* in the popup.
|
||||
* list models with GtkDropDown and GtkSuggestionEntry, how to
|
||||
* use search and how to display the selected item differently
|
||||
* from the presentation in the popup.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@@ -92,7 +94,7 @@ strings_setup_item_full (GtkSignalListItemFactory *factory,
|
||||
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
|
||||
description = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (description), "dim-label");
|
||||
gtk_widget_add_css_class (description, "dim-label");
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
@@ -218,13 +220,110 @@ get_title (gpointer item)
|
||||
return g_strdup (STRING_HOLDER (item)->title);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_file_name (gpointer item)
|
||||
{
|
||||
return g_strdup (g_file_info_get_display_name (G_FILE_INFO (item)));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *icon;
|
||||
GtkWidget *label;
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
|
||||
icon = gtk_image_new ();
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_box_append (GTK_BOX (box), icon);
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
gtk_list_item_set_child (item, box);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkMatchObject *match = GTK_MATCH_OBJECT (gtk_list_item_get_item (item));
|
||||
GFileInfo *info = G_FILE_INFO (gtk_match_object_get_item (match));
|
||||
GtkWidget *box = gtk_list_item_get_child (item);
|
||||
GtkWidget *icon = gtk_widget_get_first_child (box);
|
||||
GtkWidget *label = gtk_widget_get_last_child (box);
|
||||
|
||||
gtk_image_set_from_gicon (GTK_IMAGE (icon), g_file_info_get_icon (info));
|
||||
gtk_label_set_label (GTK_LABEL (label), g_file_info_get_display_name (info));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_highlight_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_list_item_set_child (item, label);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_highlight_item (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkMatchObject *obj;
|
||||
GtkWidget *label;
|
||||
PangoAttrList *attrs;
|
||||
PangoAttribute *attr;
|
||||
const char *str;
|
||||
|
||||
obj = GTK_MATCH_OBJECT (gtk_list_item_get_item (item));
|
||||
label = gtk_list_item_get_child (item);
|
||||
|
||||
str = gtk_match_object_get_string (obj);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (label), str);
|
||||
attrs = pango_attr_list_new ();
|
||||
attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
|
||||
attr->start_index = gtk_match_object_get_match_start (obj);
|
||||
attr->end_index = gtk_match_object_get_match_end (obj);
|
||||
pango_attr_list_insert (attrs, attr);
|
||||
gtk_label_set_attributes (GTK_LABEL (label), attrs);
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
|
||||
static void
|
||||
match_func (GtkMatchObject *obj,
|
||||
const char *search,
|
||||
gpointer user_data)
|
||||
{
|
||||
char *tmp1, *tmp2;
|
||||
char *p;
|
||||
|
||||
tmp1 = g_utf8_normalize (gtk_match_object_get_string (obj), -1, G_NORMALIZE_ALL);
|
||||
tmp2 = g_utf8_normalize (search, -1, G_NORMALIZE_ALL);
|
||||
|
||||
if ((p = strstr (tmp1, tmp2)) != NULL)
|
||||
gtk_match_object_set_match (obj,
|
||||
p - tmp1,
|
||||
(p - tmp1) + g_utf8_strlen (search, -1),
|
||||
1);
|
||||
else
|
||||
gtk_match_object_set_match (obj, 0, 0, 0);
|
||||
|
||||
g_free (tmp1);
|
||||
g_free (tmp2);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_dropdown (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *button, *box, *spin, *check;
|
||||
GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
|
||||
GListModel *model;
|
||||
GtkExpression *expression;
|
||||
GtkListItemFactory *factory;
|
||||
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
|
||||
const char * const many_times[] = {
|
||||
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
|
||||
@@ -237,23 +336,51 @@ do_dropdown (GtkWidget *do_widget)
|
||||
const char * const device_descriptions[] = {
|
||||
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
|
||||
};
|
||||
char *cwd;
|
||||
GFile *file;
|
||||
GListModel *dir;
|
||||
GtkStringList *strings;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Drop Downs");
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Selections");
|
||||
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_widget_set_margin_start (box, 10);
|
||||
gtk_widget_set_margin_end (box, 10);
|
||||
gtk_widget_set_margin_top (box, 10);
|
||||
gtk_widget_set_margin_bottom (box, 10);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
|
||||
|
||||
gtk_widget_set_margin_start (hbox, 20);
|
||||
gtk_widget_set_margin_end (hbox, 20);
|
||||
gtk_widget_set_margin_top (hbox, 20);
|
||||
gtk_widget_set_margin_bottom (hbox, 20);
|
||||
gtk_window_set_child (GTK_WINDOW (window), hbox);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_box_append (GTK_BOX (hbox), box);
|
||||
|
||||
label = gtk_label_new ("Dropdowns");
|
||||
gtk_widget_add_css_class (label, "title-4");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
/* A basic dropdown */
|
||||
button = drop_down_new_from_strings (times, NULL, NULL);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown using an expression to obtain strings */
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown using a non-trivial model, and search */
|
||||
button = gtk_drop_down_new ();
|
||||
|
||||
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
|
||||
@@ -270,30 +397,118 @@ do_dropdown (GtkWidget *do_widget)
|
||||
|
||||
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
|
||||
gtk_widget_set_halign (spin, GTK_ALIGN_START);
|
||||
gtk_widget_set_margin_start (spin, 20);
|
||||
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), spin);
|
||||
|
||||
check = gtk_check_button_new_with_label ("Enable search");
|
||||
gtk_widget_set_margin_start (check, 20);
|
||||
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
|
||||
gtk_box_append (GTK_BOX (box), check);
|
||||
|
||||
g_object_unref (model);
|
||||
|
||||
button = drop_down_new_from_strings (times, NULL, NULL);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
button = drop_down_new_from_strings (many_times, NULL, NULL);
|
||||
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_title,
|
||||
NULL, NULL);
|
||||
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
|
||||
gtk_expression_unref (expression);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
/* A dropdown with a separate list factory */
|
||||
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
|
||||
gtk_box_append (GTK_BOX (box), button);
|
||||
|
||||
gtk_box_append (GTK_BOX (hbox), gtk_separator_new (GTK_ORIENTATION_VERTICAL));
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
|
||||
gtk_box_append (GTK_BOX (hbox), box);
|
||||
|
||||
label = gtk_label_new ("Suggestions");
|
||||
gtk_widget_add_css_class (label, "title-4");
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
||||
/* A basic suggestion entry */
|
||||
entry = gtk_suggestion_entry_new ();
|
||||
g_object_set (entry, "placeholder-text", "Words with T or G…", NULL);
|
||||
strings = gtk_string_list_new ((const char *[]){
|
||||
"GNOME",
|
||||
"gnominious",
|
||||
"Gnomonic projection",
|
||||
"total",
|
||||
"totally",
|
||||
"toto",
|
||||
"tottery",
|
||||
"totterer",
|
||||
"Totten trust",
|
||||
"totipotent",
|
||||
"totipotency",
|
||||
"totemism",
|
||||
"totem pole",
|
||||
"Totara",
|
||||
"totalizer",
|
||||
"totalizator",
|
||||
"totalitarianism",
|
||||
"total parenteral nutrition",
|
||||
"total hysterectomy",
|
||||
"total eclipse",
|
||||
"Totipresence",
|
||||
"Totipalmi",
|
||||
"Tomboy",
|
||||
"zombie",
|
||||
NULL});
|
||||
gtk_suggestion_entry_set_model (GTK_SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
|
||||
g_object_unref (strings);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
/* A suggestion entry using a custom model, and no filtering */
|
||||
entry = gtk_suggestion_entry_new ();
|
||||
|
||||
cwd = g_get_current_dir ();
|
||||
file = g_file_new_for_path (cwd);
|
||||
dir = G_LIST_MODEL (gtk_directory_list_new ("standard::display-name,standard::content-type,standard::icon,standard::size", file));
|
||||
gtk_suggestion_entry_set_model (GTK_SUGGESTION_ENTRY (entry), dir);
|
||||
g_object_unref (dir);
|
||||
g_object_unref (file);
|
||||
g_free (cwd);
|
||||
|
||||
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
|
||||
0, NULL,
|
||||
(GCallback)get_file_name,
|
||||
NULL, NULL);
|
||||
gtk_suggestion_entry_set_expression (GTK_SUGGESTION_ENTRY (entry), expression);
|
||||
gtk_expression_unref (expression);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_item), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_item), NULL);
|
||||
|
||||
gtk_suggestion_entry_set_factory (GTK_SUGGESTION_ENTRY (entry), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
gtk_suggestion_entry_set_use_filter (GTK_SUGGESTION_ENTRY (entry), FALSE);
|
||||
gtk_suggestion_entry_set_show_arrow (GTK_SUGGESTION_ENTRY (entry), TRUE);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
/* A suggestion entry with match highlighting */
|
||||
entry = gtk_suggestion_entry_new ();
|
||||
g_object_set (entry, "placeholder-text", "Destination", NULL);
|
||||
|
||||
strings = gtk_string_list_new ((const char *[]){
|
||||
"app-mockups",
|
||||
"settings-mockups",
|
||||
"os-mockups",
|
||||
"software-mockups",
|
||||
"mocktails",
|
||||
NULL});
|
||||
gtk_suggestion_entry_set_model (GTK_SUGGESTION_ENTRY (entry), G_LIST_MODEL (strings));
|
||||
g_object_unref (strings);
|
||||
|
||||
gtk_box_append (GTK_BOX (box), entry);
|
||||
|
||||
gtk_suggestion_entry_set_match_func (GTK_SUGGESTION_ENTRY (entry), match_func, NULL, NULL);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_highlight_item), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_highlight_item), NULL);
|
||||
gtk_suggestion_entry_set_factory (GTK_SUGGESTION_ENTRY (entry), factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<property name="title">Font Explorer</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="reset">
|
||||
<property name="receives-default">1</property>
|
||||
|
||||
@@ -30,7 +30,6 @@ do_headerbar (GtkWidget *do_widget)
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
|
||||
button = gtk_button_new ();
|
||||
icon = g_themed_icon_new ("mail-send-receive-symbolic");
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">500</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -627,6 +627,23 @@ setup_listitem_cb (GtkListItemFactory *factory,
|
||||
gtk_expression_unref (color_expression);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_selection_listitem_cb (GtkListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *picture;
|
||||
GtkExpression *color_expression, *expression;
|
||||
|
||||
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
|
||||
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
|
||||
|
||||
picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (picture, 8, 8);
|
||||
gtk_expression_bind (color_expression, picture, "paintable", NULL);
|
||||
|
||||
gtk_list_item_set_child (list_item, picture);
|
||||
}
|
||||
|
||||
static void
|
||||
set_title (gpointer item,
|
||||
const char *title)
|
||||
@@ -645,7 +662,6 @@ create_color_grid (void)
|
||||
{
|
||||
GtkWidget *gridview;
|
||||
GtkListItemFactory *factory;
|
||||
GListModel *model, *selection;
|
||||
|
||||
gridview = gtk_grid_view_new ();
|
||||
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
|
||||
@@ -659,13 +675,6 @@ create_color_grid (void)
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
|
||||
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
|
||||
|
||||
model = G_LIST_MODEL (gtk_sort_list_model_new (gtk_color_list_new (0), NULL));
|
||||
|
||||
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
|
||||
g_object_unref (selection);
|
||||
g_object_unref (model);
|
||||
|
||||
return gridview;
|
||||
}
|
||||
|
||||
@@ -777,6 +786,63 @@ bind_number_item (GtkSignalListItemFactory *factory,
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_count (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
char *text;
|
||||
text = g_strdup_printf ("%u", g_list_model_get_n_items (model));
|
||||
gtk_label_set_label (GTK_LABEL (data), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_average (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
guint n = g_list_model_get_n_items (model);
|
||||
GdkRGBA c = { 0, 0, 0, 1 };
|
||||
guint i;
|
||||
GtkColor *color;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
color = g_list_model_get_item (model, i);
|
||||
|
||||
c.red += color->color.red;
|
||||
c.green += color->color.green;
|
||||
c.blue += color->color.blue;
|
||||
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
color = gtk_color_new ("", c.red / n, c.green / n, c.blue / n);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (data), GDK_PAINTABLE (color));
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
static void
|
||||
update_progress_cb (GtkSortListModel *model,
|
||||
GParamSpec *pspec,
|
||||
GtkProgressBar *progress)
|
||||
{
|
||||
guint total;
|
||||
guint pending;
|
||||
|
||||
total = g_list_model_get_n_items (G_LIST_MODEL (model));
|
||||
total = MAX (total, 1); /* avoid div by 0 below */
|
||||
pending = gtk_sort_list_model_get_pending (model);
|
||||
|
||||
gtk_widget_set_visible (GTK_WIDGET (progress), pending != 0);
|
||||
gtk_progress_bar_set_fraction (progress, (total - pending) / (double) total);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
@@ -784,10 +850,11 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *header, *gridview, *sw, *box, *dropdown;
|
||||
GtkMultiSelection *selection;
|
||||
GtkSortListModel *sort_model;
|
||||
GtkWidget *header, *overlay, *gridview, *sw, *box, *dropdown;
|
||||
GtkListItemFactory *factory;
|
||||
GListStore *factories;
|
||||
GListModel *model;
|
||||
GtkSorter *sorter;
|
||||
GtkSorter *multi_sorter;
|
||||
GListStore *sorters;
|
||||
@@ -797,11 +864,31 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
PangoAttrList *attrs;
|
||||
char *string;
|
||||
guint len;
|
||||
GtkWidget *selection_view;
|
||||
GListModel *selection_filter;
|
||||
GListModel *no_selection;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *selection_size_label;
|
||||
GtkWidget *selection_average_picture;
|
||||
GtkWidget *selection_info_toggle;
|
||||
GtkWidget *selection_info_revealer;
|
||||
GtkWidget *progress;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/listview_colors/listview_colors.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
g_object_unref (provider);
|
||||
|
||||
sort_model = gtk_sort_list_model_new (gtk_color_list_new (0), NULL);
|
||||
gtk_sort_list_model_set_incremental (sort_model, TRUE);
|
||||
selection = GTK_MULTI_SELECTION (gtk_multi_selection_new (G_LIST_MODEL (sort_model)));
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Colors");
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
@@ -809,18 +896,96 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), overlay);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_overlay_set_child (GTK_OVERLAY (overlay), box);
|
||||
|
||||
progress = gtk_progress_bar_new ();
|
||||
gtk_widget_set_hexpand (progress, TRUE);
|
||||
gtk_widget_set_valign (progress, GTK_ALIGN_START);
|
||||
g_signal_connect (sort_model, "notify::pending", G_CALLBACK (update_progress_cb), progress);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), progress);
|
||||
|
||||
selection_info_revealer = gtk_revealer_new ();
|
||||
gtk_box_append (GTK_BOX (box), selection_info_revealer);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_revealer_set_child (GTK_REVEALER (selection_info_revealer), grid);
|
||||
gtk_widget_set_margin_start (grid, 10);
|
||||
gtk_widget_set_margin_end (grid, 10);
|
||||
gtk_widget_set_margin_top (grid, 10);
|
||||
gtk_widget_set_margin_bottom (grid, 10);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
|
||||
|
||||
label = gtk_label_new ("Selection");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_widget_add_css_class (label, "title-3");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 5, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Size:"), 0, 2, 1, 1);
|
||||
|
||||
selection_size_label = gtk_label_new ("0");
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_size_label, 1, 2, 1, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Average:"), 2, 2, 1, 1);
|
||||
|
||||
selection_average_picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (selection_average_picture, 32, 32);
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_average_picture, 3, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 4, 2, 1, 1);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), sw, 0, 1, 5, 1);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_selection_listitem_cb), NULL);
|
||||
selection_view = gtk_grid_view_new_with_factory (factory);
|
||||
gtk_widget_add_css_class (selection_view, "compact");
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (selection_view), 200);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), selection_view);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
gridview = create_color_grid ();
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), G_LIST_MODEL (selection));
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), gridview);
|
||||
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
|
||||
g_object_get (model, "model", &model, NULL);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
|
||||
selection_filter = G_LIST_MODEL (gtk_selection_filter_model_new (GTK_SELECTION_MODEL (selection)));
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_count), selection_size_label);
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_average), selection_average_picture);
|
||||
|
||||
no_selection = G_LIST_MODEL (gtk_no_selection_new (selection_filter));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (selection_view), no_selection);
|
||||
g_object_unref (selection_filter);
|
||||
g_object_unref (no_selection);
|
||||
|
||||
selection_info_toggle = gtk_toggle_button_new ();
|
||||
gtk_button_set_icon_name (GTK_BUTTON (selection_info_toggle), "emblem-important-symbolic");
|
||||
gtk_widget_set_tooltip_text (selection_info_toggle, "Show selection info");
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), selection_info_toggle);
|
||||
|
||||
g_object_bind_property (selection_info_toggle, "active",
|
||||
selection_info_revealer, "reveal-child",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Refill");
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (refill),
|
||||
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
|
||||
gtk_sort_list_model_get_model (sort_model));
|
||||
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
|
||||
|
||||
@@ -835,15 +1000,14 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
gtk_label_set_width_chars (GTK_LABEL (label), len + 2);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1);
|
||||
|
||||
g_signal_connect (gtk_grid_view_get_model (GTK_GRID_VIEW (gridview)),
|
||||
"items-changed", G_CALLBACK (items_changed_cb), label);
|
||||
g_signal_connect (selection, "items-changed", G_CALLBACK (items_changed_cb), label);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), label);
|
||||
|
||||
dropdown = gtk_drop_down_new ();
|
||||
gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), (const char *[]) { "8", "64", "512", "4096", "32768", "262144", "2097152", "16777216", NULL });
|
||||
g_signal_connect (dropdown, "notify::selected",
|
||||
G_CALLBACK (limit_changed_cb),
|
||||
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
|
||||
gtk_sort_list_model_get_model (sort_model));
|
||||
g_signal_connect (dropdown, "notify::selected",
|
||||
G_CALLBACK (limit_changed_cb2),
|
||||
label);
|
||||
@@ -935,7 +1099,7 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (sorters));
|
||||
g_object_unref (sorters);
|
||||
|
||||
g_object_bind_property (dropdown, "selected-item", model, "sorter", G_BINDING_SYNC_CREATE);
|
||||
g_object_bind_property (dropdown, "selected-item", sort_model, "sorter", G_BINDING_SYNC_CREATE);
|
||||
|
||||
factories = g_list_store_new (GTK_TYPE_LIST_ITEM_FACTORY);
|
||||
|
||||
@@ -967,7 +1131,6 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
g_object_unref (factories);
|
||||
|
||||
g_object_bind_property (dropdown, "selected-item", gridview, "factory", G_BINDING_SYNC_CREATE);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.view.compact > child {
|
||||
padding: 1px;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
list.viewswitcher {
|
||||
listview.viewswitcher {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
list.viewswitcher > row {
|
||||
listview.viewswitcher > row {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
list.viewswitcher row:selected {
|
||||
listview.viewswitcher row:selected {
|
||||
background: gray;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">go-up-symbolic</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="title" translatable="yes">Minesweeper</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">New Game</property>
|
||||
|
||||
@@ -215,7 +215,6 @@ transform_settings_to_keys (GBinding *binding,
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkFilter *filter;
|
||||
GtkNoSelection *selection_model;
|
||||
GtkExpression *expression;
|
||||
char **keys;
|
||||
guint i;
|
||||
|
||||
@@ -246,11 +245,8 @@ transform_settings_to_keys (GBinding *binding,
|
||||
gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data)));
|
||||
g_object_unref (store);
|
||||
|
||||
expression = gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name");
|
||||
filter = gtk_string_filter_new ();
|
||||
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
|
||||
filter = gtk_string_filter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
|
||||
gtk_expression_unref (expression);
|
||||
g_object_unref (sort_model);
|
||||
|
||||
g_set_object (¤t_filter, filter);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">480</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="search_button">
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
|
||||
@@ -194,8 +194,8 @@ create_weather_model (void)
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
setup_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
|
||||
@@ -218,8 +218,8 @@ setup_widget (GtkListItem *list_item,
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
bind_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GtkWeatherInfo *info;
|
||||
@@ -282,11 +282,12 @@ create_weather_view (void)
|
||||
{
|
||||
GtkWidget *listview;
|
||||
GListModel *model, *selection;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_functions_list_item_factory_new (setup_widget,
|
||||
bind_widget,
|
||||
NULL, NULL));
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_widget), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_widget), NULL);
|
||||
listview = gtk_list_view_new_with_factory (factory);
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
|
||||
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
|
||||
model = create_weather_model ();
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/* Lists/Words
|
||||
*
|
||||
* This demo shows filtering a long list - of words.
|
||||
*
|
||||
* You should have the file `/usr/share/dict/words` installed for
|
||||
* this demo to work.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
static GtkWidget *progress;
|
||||
|
||||
const char *factory_text =
|
||||
"<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||
"<interface>\n"
|
||||
" <template class='GtkListItem'>\n"
|
||||
" <property name='child'>\n"
|
||||
" <object class='GtkLabel'>\n"
|
||||
" <property name='ellipsize'>end</property>\n"
|
||||
" <property name='xalign'>0</property>\n"
|
||||
" <binding name='label'>\n"
|
||||
" <lookup name='string' type='GtkStringObject'>\n"
|
||||
" <lookup name='item'>GtkListItem</lookup>\n"
|
||||
" </lookup>\n"
|
||||
" </binding>\n"
|
||||
" </object>\n"
|
||||
" </property>\n"
|
||||
" </template>\n"
|
||||
"</interface>\n";
|
||||
|
||||
static void
|
||||
update_title_cb (GtkFilterListModel *model)
|
||||
{
|
||||
guint total;
|
||||
char *title;
|
||||
guint pending;
|
||||
|
||||
total = g_list_model_get_n_items (gtk_filter_list_model_get_model (model));
|
||||
pending = gtk_filter_list_model_get_pending (model);
|
||||
|
||||
title = g_strdup_printf ("%u lines", g_list_model_get_n_items (G_LIST_MODEL (model)));
|
||||
|
||||
gtk_widget_set_visible (progress, pending != 0);
|
||||
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), (total - pending) / (double) total);
|
||||
gtk_window_set_title (GTK_WINDOW (window), title);
|
||||
g_free (title);
|
||||
}
|
||||
|
||||
static void
|
||||
read_lines_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (object);
|
||||
GtkStringList *stringlist = data;
|
||||
GError *error = NULL;
|
||||
gsize size;
|
||||
GPtrArray *lines;
|
||||
gssize n_filled;
|
||||
const char *buffer, *newline;
|
||||
|
||||
n_filled = g_buffered_input_stream_fill_finish (stream, result, &error);
|
||||
if (n_filled < 0)
|
||||
{
|
||||
g_print ("Could not read data: %s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = g_buffered_input_stream_peek_buffer (stream, &size);
|
||||
|
||||
if (n_filled == 0)
|
||||
{
|
||||
if (size)
|
||||
gtk_string_list_take (stringlist, g_utf8_make_valid (buffer, size));
|
||||
return;
|
||||
}
|
||||
|
||||
lines = NULL;
|
||||
while ((newline = memchr (buffer, '\n', size)))
|
||||
{
|
||||
if (newline > buffer)
|
||||
{
|
||||
if (lines == NULL)
|
||||
lines = g_ptr_array_new_with_free_func (g_free);
|
||||
g_ptr_array_add (lines, g_utf8_make_valid (buffer, newline - buffer));
|
||||
}
|
||||
if (g_input_stream_skip (G_INPUT_STREAM (stream), newline - buffer + 1, NULL, &error) < 0)
|
||||
{
|
||||
g_clear_error (&error);
|
||||
break;
|
||||
}
|
||||
buffer = g_buffered_input_stream_peek_buffer (stream, &size);
|
||||
}
|
||||
if (lines == NULL)
|
||||
{
|
||||
g_buffered_input_stream_set_buffer_size (stream, g_buffered_input_stream_get_buffer_size (stream) + 4096);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_ptr_array_add (lines, NULL);
|
||||
gtk_string_list_splice (stringlist, g_list_model_get_n_items (G_LIST_MODEL (stringlist)), 0, (const char **) lines->pdata);
|
||||
g_ptr_array_free (lines, TRUE);
|
||||
}
|
||||
|
||||
g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data);
|
||||
}
|
||||
|
||||
static void
|
||||
file_is_open_cb (GObject *file,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GFileInputStream *file_stream;
|
||||
GBufferedInputStream *stream;
|
||||
|
||||
file_stream = g_file_read_finish (G_FILE (file), result, &error);
|
||||
if (file_stream == NULL)
|
||||
{
|
||||
g_print ("Could not open file: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
stream = G_BUFFERED_INPUT_STREAM (g_buffered_input_stream_new (G_INPUT_STREAM (file_stream)));
|
||||
g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
load_file (GtkStringList *list,
|
||||
GFile *file)
|
||||
{
|
||||
gtk_string_list_splice (list, 0, g_list_model_get_n_items (G_LIST_MODEL (list)), NULL);
|
||||
g_file_read_async (file, G_PRIORITY_HIGH_IDLE, NULL, file_is_open_cb, list);
|
||||
}
|
||||
|
||||
static void
|
||||
file_selected_cb (GtkWidget *button,
|
||||
GtkStringList *stringlist)
|
||||
{
|
||||
GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button));
|
||||
|
||||
if (file)
|
||||
{
|
||||
load_file (stringlist, file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_words (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkWidget *header, *listview, *sw, *vbox, *search_entry, *open_button, *overlay;
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkNoSelection *selection;
|
||||
GtkStringList *stringlist;
|
||||
GtkFilter *filter;
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_path ("/usr/share/dict/words");
|
||||
if (g_file_query_exists (file, NULL))
|
||||
{
|
||||
stringlist = gtk_string_list_new (NULL);
|
||||
load_file (stringlist, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
char **words;
|
||||
words = g_strsplit ("lorem ipsum dolor sit amet consectetur adipisci elit sed eiusmod tempor incidunt labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat", " ", -1);
|
||||
stringlist = gtk_string_list_new ((const char **) words);
|
||||
g_strfreev (words);
|
||||
}
|
||||
|
||||
filter = gtk_string_filter_new (gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string"));
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (stringlist), filter);
|
||||
gtk_filter_list_model_set_incremental (filter_model, TRUE);
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
open_button = gtk_file_chooser_button_new ("_Open", GTK_FILE_CHOOSER_ACTION_OPEN);
|
||||
g_signal_connect (open_button, "file-set", G_CALLBACK (file_selected_cb), stringlist);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), open_button);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), vbox);
|
||||
|
||||
search_entry = gtk_search_entry_new ();
|
||||
g_object_bind_property (search_entry, "text", filter, "search", 0);
|
||||
gtk_box_append (GTK_BOX (vbox), search_entry);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
gtk_box_append (GTK_BOX (vbox), overlay);
|
||||
|
||||
progress = gtk_progress_bar_new ();
|
||||
gtk_widget_set_halign (progress, GTK_ALIGN_FILL);
|
||||
gtk_widget_set_valign (progress, GTK_ALIGN_START);
|
||||
gtk_widget_set_hexpand (progress, TRUE);
|
||||
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), progress);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
gtk_overlay_set_child (GTK_OVERLAY (overlay), sw);
|
||||
|
||||
listview = gtk_list_view_new_with_factory (
|
||||
gtk_builder_list_item_factory_new_from_bytes (NULL,
|
||||
g_bytes_new_static (factory_text, strlen (factory_text))));
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
|
||||
selection = gtk_no_selection_new (G_LIST_MODEL (filter_model));
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
|
||||
g_signal_connect (filter_model, "items-changed", G_CALLBACK (update_title_cb), progress);
|
||||
g_signal_connect (filter_model, "notify::pending", G_CALLBACK (update_title_cb), progress);
|
||||
update_title_cb (filter_model);
|
||||
|
||||
g_object_unref (filter_model);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show (window);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
||||
+113
-4
@@ -18,6 +18,7 @@ static gchar *current_file = NULL;
|
||||
static GtkWidget *notebook;
|
||||
static GtkSingleSelection *selection;
|
||||
static GtkWidget *toplevel;
|
||||
static char **search_needle;
|
||||
|
||||
typedef struct _GtkDemo GtkDemo;
|
||||
struct _GtkDemo
|
||||
@@ -945,7 +946,18 @@ selection_cb (GtkSingleSelection *sel,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTreeListRow *row = gtk_single_selection_get_selected_item (sel);
|
||||
GtkDemo *demo = gtk_tree_list_row_get_item (row);
|
||||
GtkDemo *demo;
|
||||
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (notebook), !!row);
|
||||
|
||||
if (!row)
|
||||
{
|
||||
gtk_window_set_title (GTK_WINDOW (toplevel), "No match");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
demo = gtk_tree_list_row_get_item (row);
|
||||
|
||||
if (demo->filename)
|
||||
load_file (demo->name, demo->filename);
|
||||
@@ -953,6 +965,84 @@ selection_cb (GtkSingleSelection *sel,
|
||||
gtk_window_set_title (GTK_WINDOW (toplevel), demo->title);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
filter_demo (GtkDemo *demo)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Show only if the name maches every needle */
|
||||
for (i = 0; search_needle[i]; i++)
|
||||
{
|
||||
if (!demo->title)
|
||||
return FALSE;
|
||||
|
||||
if (g_str_match_string (search_needle[i], demo->title, TRUE))
|
||||
continue;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demo_filter_by_name (GtkTreeListRow *row,
|
||||
GtkFilterListModel *model)
|
||||
{
|
||||
GListModel *children;
|
||||
GtkDemo *demo;
|
||||
guint i, n;
|
||||
|
||||
/* Show all items if search is empty */
|
||||
if (!search_needle || !search_needle[0] || !*search_needle[0])
|
||||
return TRUE;
|
||||
|
||||
g_assert (GTK_IS_TREE_LIST_ROW (row));
|
||||
g_assert (GTK_IS_FILTER_LIST_MODEL (model));
|
||||
|
||||
children = gtk_tree_list_row_get_children (row);
|
||||
if (children)
|
||||
{
|
||||
n = g_list_model_get_n_items (children);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
demo = g_list_model_get_item (children, i);
|
||||
g_assert (GTK_IS_DEMO (demo));
|
||||
|
||||
if (filter_demo (demo))
|
||||
{
|
||||
g_object_unref (demo);
|
||||
return TRUE;
|
||||
}
|
||||
g_object_unref (demo);
|
||||
}
|
||||
}
|
||||
|
||||
demo = gtk_tree_list_row_get_item (row);
|
||||
g_assert (GTK_IS_DEMO (demo));
|
||||
|
||||
return filter_demo (demo);
|
||||
}
|
||||
|
||||
static void
|
||||
demo_search_changed_cb (GtkSearchEntry *entry,
|
||||
GtkFilter *filter)
|
||||
{
|
||||
const char *text;
|
||||
|
||||
g_assert (GTK_IS_SEARCH_ENTRY (entry));
|
||||
g_assert (GTK_IS_FILTER (filter));
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (entry));
|
||||
|
||||
g_clear_pointer (&search_needle, g_strfreev);
|
||||
|
||||
if (text && *text)
|
||||
search_needle = g_strsplit (text, " ", 0);
|
||||
|
||||
gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT);
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_demo_model (void)
|
||||
{
|
||||
@@ -1007,13 +1097,25 @@ get_child_model (gpointer item,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_search (GtkSearchBar *bar)
|
||||
{
|
||||
if (!gtk_search_bar_get_search_mode (bar))
|
||||
{
|
||||
GtkWidget *entry = gtk_search_bar_get_child (GTK_SEARCH_BAR (bar));
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
activate (GApplication *app)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GListModel *listmodel;
|
||||
GtkTreeListModel *treemodel;
|
||||
GtkWidget *window, *listview;
|
||||
GtkWidget *window, *listview, *search_entry, *search_bar;
|
||||
GtkFilterListModel *filter_model;
|
||||
GtkFilter *filter;
|
||||
|
||||
static GActionEntry win_entries[] = {
|
||||
{ "run", activate_run, NULL, NULL, NULL }
|
||||
@@ -1034,6 +1136,8 @@ activate (GApplication *app)
|
||||
toplevel = GTK_WIDGET (window);
|
||||
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
|
||||
g_signal_connect (listview, "activate", G_CALLBACK (activate_cb), window);
|
||||
search_bar = GTK_WIDGET (gtk_builder_get_object (builder, "searchbar"));
|
||||
g_signal_connect (search_bar, "notify::search-mode-enabled", G_CALLBACK (clear_search), NULL);
|
||||
|
||||
listmodel = create_demo_model ();
|
||||
treemodel = gtk_tree_list_model_new (FALSE,
|
||||
@@ -1042,7 +1146,13 @@ activate (GApplication *app)
|
||||
get_child_model,
|
||||
NULL,
|
||||
NULL);
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
|
||||
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (treemodel), NULL);
|
||||
filter = gtk_custom_filter_new ((GtkCustomFilterFunc)demo_filter_by_name, filter_model, NULL);
|
||||
gtk_filter_list_model_set_filter (filter_model, filter);
|
||||
search_entry = GTK_WIDGET (gtk_builder_get_object (builder, "search-entry"));
|
||||
g_signal_connect (search_entry, "search-changed", G_CALLBACK (demo_search_changed_cb), filter);
|
||||
|
||||
selection = gtk_single_selection_new (G_LIST_MODEL (filter_model));
|
||||
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
|
||||
|
||||
@@ -1139,7 +1249,6 @@ out:
|
||||
demo = (func) (window);
|
||||
|
||||
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
|
||||
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
|
||||
|
||||
g_signal_connect_swapped (G_OBJECT (demo), "destroy", G_CALLBACK (g_application_quit), app);
|
||||
}
|
||||
|
||||
+22
-6
@@ -24,7 +24,6 @@
|
||||
<property name="default-height">600</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="valign">center</property>
|
||||
@@ -56,12 +55,29 @@
|
||||
<property name="hscrollbar-policy">never</property>
|
||||
<property name="min-content-width">150</property>
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/ui/main-listitem.ui</property>
|
||||
<object class="GtkBox">
|
||||
<property name="width-request">220</property>
|
||||
<property name="orientation">vertical</property>
|
||||
|
||||
<child>
|
||||
<object class="GtkSearchBar" id="searchbar">
|
||||
<property name="key-capture-widget">window</property>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="search-entry"/>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="resource">/ui/main-listitem.ui</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
||||
@@ -69,7 +69,6 @@ do_markup (GtkWidget *do_widget)
|
||||
g_signal_connect (show_source, "toggled", G_CALLBACK (source_toggled), stack);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), show_source);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ demos = files([
|
||||
'cursors.c',
|
||||
'dialog.c',
|
||||
'drawingarea.c',
|
||||
'dropdown.c',
|
||||
'dnd.c',
|
||||
'editable_cells.c',
|
||||
'entry_completion.c',
|
||||
@@ -47,8 +46,10 @@ demos = files([
|
||||
'listview_colors.c',
|
||||
'listview_filebrowser.c',
|
||||
'listview_minesweeper.c',
|
||||
'dropdown.c',
|
||||
'listview_settings.c',
|
||||
'listview_weather.c',
|
||||
'listview_words.c',
|
||||
'markup.c',
|
||||
'modelbutton.c',
|
||||
'overlay.c',
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
<property name="title" translatable="yes">Model Button</property>
|
||||
<property name="resizable">0</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
</object>
|
||||
<object class="GtkHeaderBar"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
||||
@@ -392,7 +392,6 @@ do_paint (GtkWidget *toplevel)
|
||||
gtk_window_set_child (GTK_WINDOW (window), draw_area);
|
||||
|
||||
headerbar = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (headerbar), TRUE);
|
||||
|
||||
colorbutton = gtk_color_button_new ();
|
||||
g_signal_connect (colorbutton, "color-set",
|
||||
|
||||
@@ -276,7 +276,6 @@ do_peg_solitaire (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
|
||||
@@ -40,7 +40,6 @@ do_sidebar (GtkWidget *do_widget)
|
||||
gtk_widget_set_size_request (window, 500, 350);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR(header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW(window), header);
|
||||
gtk_window_set_title (GTK_WINDOW(window), "Stack Sidebar");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
@@ -470,7 +470,6 @@ do_sliding_puzzle (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (reshuffle), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), tweak);
|
||||
window = gtk_window_new ();
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
<property name="resizable">0</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkToggleButton" id="toggle">
|
||||
<property name="label">Cycle</property>
|
||||
|
||||
@@ -73,7 +73,6 @@ do_video_player (GtkWidget *do_widget)
|
||||
gtk_window_set_child (GTK_WINDOW (window), video);
|
||||
|
||||
title = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (title), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), title);
|
||||
|
||||
open_button = gtk_button_new_with_mnemonic ("_Open");
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="43.000351" x2="85.000351" y1="39.000164" y2="39.000164">
|
||||
<stop offset="0" stop-color="#26a269"/>
|
||||
<stop offset="0.0934161" stop-color="#84e3b7"/>
|
||||
<stop offset="0.330831" stop-color="#26a269"/>
|
||||
<stop offset="0.686952" stop-color="#26a269"/>
|
||||
<stop offset="0.89736" stop-color="#175e3c"/>
|
||||
<stop offset="1" stop-color="#26a269"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.154754" stop-color="#ffffff"/>
|
||||
<stop offset="0.433722" stop-color="#bdbbb5"/>
|
||||
<stop offset="0.650505" stop-color="#c1c0ba"/>
|
||||
<stop offset="0.825253" stop-color="#ffffff"/>
|
||||
<stop offset="1" stop-color="#c0bfbc"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" gradientTransform="matrix(0.0811899 -0.046875 0.069079 0.119648 307.03142 127.069456)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
|
||||
<linearGradient id="d" gradientTransform="matrix(-0.0811899 -0.046875 -0.069079 0.119648 -177.242852 127.069447)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
|
||||
<linearGradient id="e" gradientUnits="userSpaceOnUse" x1="14" x2="56" y1="94.999964" y2="94.999964">
|
||||
<stop offset="0" stop-color="#813d9c"/>
|
||||
<stop offset="0.109119" stop-color="#b378ca"/>
|
||||
<stop offset="0.241583" stop-color="#813d9c"/>
|
||||
<stop offset="0.731841" stop-color="#813d9c"/>
|
||||
<stop offset="0.872163" stop-color="#4d255d"/>
|
||||
<stop offset="1" stop-color="#813d9c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="72" x2="114" y1="94.999964" y2="94.999964">
|
||||
<stop offset="0" stop-color="#e66100"/>
|
||||
<stop offset="0.0678478" stop-color="#ff903e"/>
|
||||
<stop offset="0.168852" stop-color="#e66100"/>
|
||||
<stop offset="0.886626" stop-color="#e66100"/>
|
||||
<stop offset="1" stop-color="#9d4200"/>
|
||||
</linearGradient>
|
||||
<clipPath id="g">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="h">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<filter id="i" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="j">
|
||||
<g clip-path="url(#h)" filter="url(#i)">
|
||||
<g clip-path="url(#g)">
|
||||
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
|
||||
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
|
||||
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
|
||||
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
|
||||
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
|
||||
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
|
||||
</g>
|
||||
</g>
|
||||
</mask>
|
||||
<mask id="k">
|
||||
<g filter="url(#i)">
|
||||
<rect fill-opacity="0.8" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<linearGradient id="l" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235">
|
||||
<stop offset="0" stop-color="#f9f06b"/>
|
||||
<stop offset="1" stop-color="#f5c211"/>
|
||||
</linearGradient>
|
||||
<clipPath id="m">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="n">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
|
||||
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
|
||||
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
|
||||
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
|
||||
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
|
||||
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
|
||||
<g clip-path="url(#n)" mask="url(#j)">
|
||||
<g clip-path="url(#m)" mask="url(#k)">
|
||||
<path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#l)"/>
|
||||
<path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="43.000351" x2="85.000351" y1="39.000164" y2="39.000164">
|
||||
<stop offset="0" stop-color="#26a269"/>
|
||||
<stop offset="0.0934161" stop-color="#84e3b7"/>
|
||||
<stop offset="0.330831" stop-color="#26a269"/>
|
||||
<stop offset="0.686952" stop-color="#26a269"/>
|
||||
<stop offset="0.89736" stop-color="#175e3c"/>
|
||||
<stop offset="1" stop-color="#26a269"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.154754" stop-color="#ffffff"/>
|
||||
<stop offset="0.433722" stop-color="#bdbbb5"/>
|
||||
<stop offset="0.650505" stop-color="#c1c0ba"/>
|
||||
<stop offset="0.825253" stop-color="#ffffff"/>
|
||||
<stop offset="1" stop-color="#c0bfbc"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" gradientTransform="matrix(0.0811899 -0.046875 0.069079 0.119648 307.03142 127.069456)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
|
||||
<linearGradient id="d" gradientTransform="matrix(-0.0811899 -0.046875 -0.069079 0.119648 -177.242852 127.069447)" x1="-1710.210571" x2="-1774.45166" xlink:href="#b" y1="-1202.376709" y2="-1202.376709"/>
|
||||
<linearGradient id="e" gradientUnits="userSpaceOnUse" x1="14" x2="56" y1="94.999964" y2="94.999964">
|
||||
<stop offset="0" stop-color="#813d9c"/>
|
||||
<stop offset="0.109119" stop-color="#b378ca"/>
|
||||
<stop offset="0.241583" stop-color="#813d9c"/>
|
||||
<stop offset="0.731841" stop-color="#813d9c"/>
|
||||
<stop offset="0.872163" stop-color="#4d255d"/>
|
||||
<stop offset="1" stop-color="#813d9c"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="72" x2="114" y1="94.999964" y2="94.999964">
|
||||
<stop offset="0" stop-color="#e66100"/>
|
||||
<stop offset="0.0678478" stop-color="#ff903e"/>
|
||||
<stop offset="0.168852" stop-color="#e66100"/>
|
||||
<stop offset="0.886626" stop-color="#e66100"/>
|
||||
<stop offset="1" stop-color="#9d4200"/>
|
||||
</linearGradient>
|
||||
<path d="m 51 18 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 51 12 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#57e389"/>
|
||||
<path d="m 76.976562 55.453125 c 1.480469 -0.855469 3.371094 -0.347656 4.226563 1.132813 l 6.742187 11.679687 c 0.855469 1.480469 0.347657 3.371094 -1.132812 4.226563 c -1.480469 0.851562 -3.371094 0.347656 -4.226562 -1.132813 l -6.742188 -11.679687 c -0.855469 -1.480469 -0.347656 -3.371094 1.132812 -4.226563 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 52.8125 55.453125 c -1.480469 -0.855469 -3.371094 -0.347656 -4.226562 1.132813 l -6.742188 11.679687 c -0.855469 1.480469 -0.347656 3.371094 1.132812 4.226563 c 1.480469 0.851562 3.371094 0.347656 4.226563 -1.132813 l 6.742187 -11.679687 c 0.855469 -1.480469 0.347657 -3.371094 -1.132812 -4.226563 z m 0 0" fill="url(#d)"/>
|
||||
<path d="m 22 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#e)"/>
|
||||
<path d="m 22 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#dc8add"/>
|
||||
<path d="m 80 74 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="url(#f)"/>
|
||||
<path d="m 80 68 h 26 c 4.417969 0 8 3.582031 8 8 v 26 c 0 4.417969 -3.582031 8 -8 8 h -26 c -4.417969 0 -8 -3.582031 -8 -8 v -26 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#ffa348"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m 5.75 1 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 0.191406 l -1 2 h -3.191406 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 4.5 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 h -0.191406 l 1 -2 h 1.882812 l 1 2 h -0.191406 c -0.414062 0 -0.75 0.335938 -0.75 0.75 v 4.5 c 0 0.414062 0.335938 0.75 0.75 0.75 h 4.5 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 h -3.191406 l -1 -2 h 0.191406 c 0.414062 0 0.75 -0.335938 0.75 -0.75 v -4.5 c 0 -0.414062 -0.335938 -0.75 -0.75 -0.75 z m 0 0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 801 B |
@@ -19,3 +19,12 @@ executable('gtk4-node-editor',
|
||||
gui_app: true,
|
||||
link_args: extra_demo_ldflags,
|
||||
install: false)
|
||||
|
||||
# icons
|
||||
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
|
||||
|
||||
foreach size: ['scalable', 'symbolic']
|
||||
install_subdir('data/' + size,
|
||||
install_dir: icontheme_dir
|
||||
)
|
||||
endforeach
|
||||
|
||||
@@ -101,7 +101,7 @@ activate_about (GSimpleAction *action,
|
||||
"website", "http://www.gtk.org",
|
||||
"comments", "Program to test GTK rendering",
|
||||
"authors", (const char *[]){ "Benjamin Otte", "Timm Bäder", NULL},
|
||||
"logo-icon-name", "text-editor-symbolic",
|
||||
"logo-icon-name", "org.gtk.gtk4.NodeEditor.Devel",
|
||||
"title", "About GTK Node Editor",
|
||||
"system-information", s->str,
|
||||
NULL);
|
||||
|
||||
@@ -103,7 +103,6 @@
|
||||
<property name="focus-widget">text_view</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<linearGradient id="a" gradientTransform="matrix(0.232143 0 0 0.328947 -7.567033 263.82666)" gradientUnits="userSpaceOnUse" x1="88.595886" x2="536.595886" y1="-449.394012" y2="-449.394012">
|
||||
<stop offset="0" stop-color="#acabae"/>
|
||||
<stop offset="0.0384615" stop-color="#deddda"/>
|
||||
<stop offset="0.0768555" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.923077" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.961538" stop-color="#deddda"/>
|
||||
<stop offset="1" stop-color="#9a9996"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="26.999876" x2="100.999876" y1="32.999688" y2="32.999688">
|
||||
<stop offset="0" stop-color="#7e7c77"/>
|
||||
<stop offset="0.3" stop-color="#9a9996"/>
|
||||
<stop offset="1" stop-color="#9a9996"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="67.467916" x2="67.467916" y1="83.999688" y2="36.782906">
|
||||
<stop offset="0" stop-color="#deddda"/>
|
||||
<stop offset="1" stop-color="#c0bfbc"/>
|
||||
</linearGradient>
|
||||
<clipPath id="d">
|
||||
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
|
||||
</clipPath>
|
||||
<clipPath id="e">
|
||||
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
|
||||
</clipPath>
|
||||
<linearGradient id="f" gradientTransform="matrix(0 0.126951 0.126951 0 76.460862 36.359884)" gradientUnits="userSpaceOnUse" x1="344" x2="340" y1="76" y2="72">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#ffffff"/>
|
||||
</linearGradient>
|
||||
<filter id="g" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="h">
|
||||
<g filter="url(#g)">
|
||||
<rect fill-opacity="0.396" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<linearGradient id="i" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#1c71d8"/>
|
||||
<stop offset="0.323117" stop-color="#62a0ea"/>
|
||||
<stop offset="0.59387" stop-color="#1b5aa6"/>
|
||||
<stop offset="1" stop-color="#1c71d8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="j" gradientTransform="matrix(1.597748 1.597748 -1.06066 1.06066 -56.853041 -543.720139)" x1="224.504562" x2="231.453873" xlink:href="#i" y1="282.5" y2="282.5"/>
|
||||
<radialGradient id="k" cx="227.599915" cy="201.029724" gradientTransform="matrix(4.072817 4.073078 -5.940048 5.939073 373.883117 -2098.049112)" gradientUnits="userSpaceOnUse" r="2.5">
|
||||
<stop offset="0" stop-color="#93bdf1"/>
|
||||
<stop offset="1" stop-color="#1a5fb4"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="l" gradientTransform="matrix(2.121328 2.121328 -2.174353 2.174353 181.766074 -1021.145947)" gradientUnits="userSpaceOnUse" x1="226.90625" x2="228.86203" y1="288.75" y2="288.767151">
|
||||
<stop offset="0" stop-color="#77767b"/>
|
||||
<stop offset="0.443872" stop-color="#f6f5f4"/>
|
||||
<stop offset="1" stop-color="#5e5c64"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="m" gradientTransform="matrix(1.258421 1.258421 -1.06066 1.06066 57.381892 -503.024312)" gradientUnits="userSpaceOnUse" x1="223.1875" x2="233.0625" y1="278" y2="278">
|
||||
<stop offset="0" stop-color="#ffa348"/>
|
||||
<stop offset="0.265823" stop-color="#ffd7af"/>
|
||||
<stop offset="0.734177" stop-color="#ff8d1c"/>
|
||||
<stop offset="1" stop-color="#ffa348"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="n" gradientTransform="matrix(1.573027 1.573027 -1.06066 1.06066 -14.348129 -574.754333)" x1="224.504562" x2="231.453873" xlink:href="#i" y1="282.5" y2="282.5"/>
|
||||
<clipPath id="o">
|
||||
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
|
||||
</clipPath>
|
||||
<clipPath id="p">
|
||||
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
|
||||
</clipPath>
|
||||
<mask id="q">
|
||||
<g filter="url(#g)">
|
||||
<rect fill-opacity="0.396" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="r">
|
||||
<rect height="152" width="192"/>
|
||||
</clipPath>
|
||||
<g id="s" clip-path="url(#r)">
|
||||
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
|
||||
</g>
|
||||
<clipPath id="t">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="u">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<mask id="v">
|
||||
<g clip-path="url(#u)" filter="url(#g)">
|
||||
<g clip-path="url(#t)">
|
||||
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
|
||||
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
|
||||
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
|
||||
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac" fill-opacity="0.984252"/>
|
||||
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1" fill-opacity="0.984252"/>
|
||||
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda" fill-opacity="0.984252"/>
|
||||
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
|
||||
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
|
||||
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
|
||||
<g clip-path="url(#o)">
|
||||
<g clip-path="url(#p)">
|
||||
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
|
||||
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
|
||||
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
|
||||
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
|
||||
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
|
||||
<use mask="url(#q)" transform="matrix(1 0 0 1 -8 -16)" xlink:href="#s"/>
|
||||
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
|
||||
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
|
||||
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
|
||||
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#j)"/>
|
||||
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#k)"/>
|
||||
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
|
||||
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
|
||||
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#l)"/>
|
||||
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#m)"/>
|
||||
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#n)"/>
|
||||
</g>
|
||||
</g>
|
||||
</mask>
|
||||
<mask id="w">
|
||||
<g filter="url(#g)">
|
||||
<rect fill-opacity="0.8" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<linearGradient id="x" gradientTransform="matrix(0 0.37 -0.98462 0 295.38501 -30.360001)" gradientUnits="userSpaceOnUse" x1="300" x2="428" y1="235" y2="235">
|
||||
<stop offset="0" stop-color="#f9f06b"/>
|
||||
<stop offset="1" stop-color="#f5c211"/>
|
||||
</linearGradient>
|
||||
<clipPath id="y">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
<clipPath id="z">
|
||||
<rect height="128" width="128"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
|
||||
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
|
||||
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
|
||||
<g fill-opacity="0.984252">
|
||||
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac"/>
|
||||
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1"/>
|
||||
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda"/>
|
||||
</g>
|
||||
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
|
||||
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
|
||||
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
|
||||
<g clip-path="url(#d)">
|
||||
<g clip-path="url(#e)">
|
||||
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
|
||||
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
|
||||
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
|
||||
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
|
||||
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
|
||||
<use mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)" xlink:href="#s"/>
|
||||
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
|
||||
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
|
||||
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
|
||||
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#j)"/>
|
||||
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#k)"/>
|
||||
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
|
||||
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
|
||||
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#l)"/>
|
||||
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#m)"/>
|
||||
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#n)"/>
|
||||
<g clip-path="url(#z)" mask="url(#v)">
|
||||
<g clip-path="url(#y)" mask="url(#w)">
|
||||
<path d="m 128 80.640625 v 47.359375 h -128 v -47.359375 z m 0 0" fill="url(#x)"/>
|
||||
<path d="m 13.308594 80.640625 l 47.355468 47.359375 h 21.214844 l -47.359375 -47.359375 z m 42.421875 0 l 47.363281 47.359375 h 21.214844 l -47.363282 -47.359375 z m 42.429687 0 l 29.839844 29.839844 v -21.210938 l -8.628906 -8.628906 z m -98.160156 7.90625 v 21.214844 l 18.238281 18.238281 h 21.214844 z m 0 0"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<linearGradient id="a" gradientTransform="matrix(0.232143 0 0 0.328947 -7.567033 263.82666)" gradientUnits="userSpaceOnUse" x1="88.595886" x2="536.595886" y1="-449.394012" y2="-449.394012">
|
||||
<stop offset="0" stop-color="#acabae"/>
|
||||
<stop offset="0.0384615" stop-color="#deddda"/>
|
||||
<stop offset="0.0768555" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.923077" stop-color="#c0bfbc"/>
|
||||
<stop offset="0.961538" stop-color="#deddda"/>
|
||||
<stop offset="1" stop-color="#9a9996"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="26.999876" x2="100.999876" y1="32.999688" y2="32.999688">
|
||||
<stop offset="0" stop-color="#7e7c77"/>
|
||||
<stop offset="0.3" stop-color="#9a9996"/>
|
||||
<stop offset="1" stop-color="#9a9996"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="67.467916" x2="67.467916" y1="83.999688" y2="36.782906">
|
||||
<stop offset="0" stop-color="#deddda"/>
|
||||
<stop offset="1" stop-color="#c0bfbc"/>
|
||||
</linearGradient>
|
||||
<clipPath id="d">
|
||||
<path d="m 79 72 h 15 v 16 h -15 z m 0 0"/>
|
||||
</clipPath>
|
||||
<clipPath id="e">
|
||||
<path d="m 93.21875 72.921875 l -14.21875 14.21875 h -4.0625 v -18.28125 h 18.28125 z m 0 0"/>
|
||||
</clipPath>
|
||||
<linearGradient id="f" gradientTransform="matrix(0 0.126951 0.126951 0 76.460862 36.359884)" gradientUnits="userSpaceOnUse" x1="344" x2="340" y1="76" y2="72">
|
||||
<stop offset="0" stop-color="#d5d3cf"/>
|
||||
<stop offset="1" stop-color="#ffffff"/>
|
||||
</linearGradient>
|
||||
<filter id="g" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="h">
|
||||
<g filter="url(#g)">
|
||||
<rect fill-opacity="0.396" height="128" width="128"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="i">
|
||||
<rect height="152" width="192"/>
|
||||
</clipPath>
|
||||
<linearGradient id="j" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#1c71d8"/>
|
||||
<stop offset="0.323117" stop-color="#62a0ea"/>
|
||||
<stop offset="0.59387" stop-color="#1b5aa6"/>
|
||||
<stop offset="1" stop-color="#1c71d8"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="k" gradientTransform="matrix(1.597748 1.597748 -1.06066 1.06066 -56.853041 -543.720139)" x1="224.504562" x2="231.453873" xlink:href="#j" y1="282.5" y2="282.5"/>
|
||||
<radialGradient id="l" cx="227.599915" cy="201.029724" gradientTransform="matrix(4.072817 4.073078 -5.940048 5.939073 373.883117 -2098.049112)" gradientUnits="userSpaceOnUse" r="2.5">
|
||||
<stop offset="0" stop-color="#93bdf1"/>
|
||||
<stop offset="1" stop-color="#1a5fb4"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="m" gradientTransform="matrix(2.121328 2.121328 -2.174353 2.174353 181.766074 -1021.145947)" gradientUnits="userSpaceOnUse" x1="226.90625" x2="228.86203" y1="288.75" y2="288.767151">
|
||||
<stop offset="0" stop-color="#77767b"/>
|
||||
<stop offset="0.443872" stop-color="#f6f5f4"/>
|
||||
<stop offset="1" stop-color="#5e5c64"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="n" gradientTransform="matrix(1.258421 1.258421 -1.06066 1.06066 57.381892 -503.024312)" gradientUnits="userSpaceOnUse" x1="223.1875" x2="233.0625" y1="278" y2="278">
|
||||
<stop offset="0" stop-color="#ffa348"/>
|
||||
<stop offset="0.265823" stop-color="#ffd7af"/>
|
||||
<stop offset="0.734177" stop-color="#ff8d1c"/>
|
||||
<stop offset="1" stop-color="#ffa348"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="o" gradientTransform="matrix(1.573027 1.573027 -1.06066 1.06066 -14.348129 -574.754333)" x1="224.504562" x2="231.453873" xlink:href="#j" y1="282.5" y2="282.5"/>
|
||||
<path d="m 21 16 c -4.433594 0 -8 3.566406 -8 8 v 84 c 0 4.433594 3.566406 8 8 8 h 4 v -4 h 80 v 4 h 4 c 4.433594 0 8 -3.566406 8 -8 v -84 c 0 -4.433594 -3.566406 -8 -8 -8 z m 0 0" fill="url(#a)"/>
|
||||
<path d="m 21 12 h 88 c 4.417969 0 8 3.582031 8 8 v 68 c 0 4.417969 -3.582031 8 -8 8 h -88 c -4.417969 0 -8 -3.582031 -8 -8 v -68 c 0 -4.417969 3.582031 -8 8 -8 z m 0 0" fill="#deddda"/>
|
||||
<path d="m 27 28 h 74 v 10 h -74 z m 0 0" fill="url(#b)"/>
|
||||
<path d="m 27 38 h 74 v 46 h -74 z m 0 0" fill="url(#c)"/>
|
||||
<path d="m 24 33 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#bf5f00" fill-opacity="0.964567"/>
|
||||
<g fill-opacity="0.984252">
|
||||
<path d="m 18 40 h 6 v 12 h -6 z m 0 0" fill="#acacac"/>
|
||||
<path d="m 18 40 h 6 v 10 h -6 z m 0 0" fill="#d1d1d1"/>
|
||||
<path d="m 37 36 h 56 v 44 h -56 z m 0 0" fill="#deddda"/>
|
||||
</g>
|
||||
<path d="m 37 34 h 56 c 1.105469 0 2 0.894531 2 2 s -0.894531 2 -2 2 h -56 c -1.105469 0 -2 -0.894531 -2 -2 s 0.894531 -2 2 -2 z m 0 0" fill-opacity="0.940945"/>
|
||||
<path d="m 37 36.859375 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#9a9996" fill-opacity="0.984252"/>
|
||||
<path d="m 37 36 h 56 v 36.925781 l -14.125 14.214844 h -41.875 z m 0 0" fill="#f6f5f4" fill-opacity="0.984252"/>
|
||||
<g clip-path="url(#d)">
|
||||
<g clip-path="url(#e)">
|
||||
<path d="m 79 77.386719 v 9.351562 c 0 2.464844 2 4.464844 4.464844 4.464844 h 9.351562 c 2.464844 0 4.464844 -2 4.464844 -4.464844 v -9.351562 c 0 -2.464844 -2 -4.464844 -4.464844 -4.464844 h -9.351562 c -2.464844 0 -4.464844 2 -4.464844 4.464844 z m 0 0" fill="url(#f)"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m 27 100 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#5e5c64" fill-opacity="0.940945"/>
|
||||
<path d="m 27 102 h 76 c 1.109375 0 2 0.890625 2 2 v 10 h -80 v -10 c 0 -1.109375 0.890625 -2 2 -2 z m 0 0" fill="#9a9996"/>
|
||||
<path d="m 13 106 v 2 c 0 4.433594 3.566406 8 8 8 h 4 v -2 h -4 c -4.433594 0 -8 -3.566406 -8 -8 z m 104 0 c 0 4.433594 -3.566406 8 -8 8 h -4 v 2 h 4 c 4.433594 0 8 -3.566406 8 -8 z m -92 6 v 2 h 80 v -2 z m 0 0" fill="#9e9c99" fill-opacity="0.366142"/>
|
||||
<path d="m 27 38 v 46 l 6 -46 z m 0 0" fill="#7e7c77" fill-opacity="0.11811"/>
|
||||
<path d="m 24 32 c 0 1.65625 -1.34375 3 -3 3 s -3 -1.34375 -3 -3 s 1.34375 -3 3 -3 s 3 1.34375 3 3 z m 0 0" fill="#ffa348" fill-opacity="0.964567"/>
|
||||
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)">
|
||||
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
|
||||
</g>
|
||||
<path d="m 89.503906 31.144531 l 10.066406 10.066407 l -41.71875 41.71875 l -10.066406 -10.066407 z m 0 0" fill="#ffa348"/>
|
||||
<path d="m 88.246094 29.886719 l 7.550781 7.550781 l -41.71875 41.71875 l -7.550781 -7.550781 z m 0 0" fill="#ff7800"/>
|
||||
<path d="m 86.789062 28.429688 l 2.515626 2.515624 l -41.71875 41.71875 l -2.515626 -2.515624 z m 0 0" fill="#ffbe6f"/>
|
||||
<path d="m 121.898438 -0.101562 c -4.855469 0.921874 -11.730469 5.152343 -18.140626 11.558593 l -16.96875 16.972657 l 12.78125 12.78125 l 16.972657 -16.972657 c 6.40625 -6.40625 10.636719 -13.28125 11.558593 -18.136719 z m 0 0" fill="url(#k)"/>
|
||||
<path d="m 110.011719 13.882812 c -2.1875 -0.398437 -5.421875 0.988282 -8.167969 3.730469 l -11.871094 11.875 l -6.6875 6.6875 c -4.800781 4.800781 -9.234375 12.007813 -9.648437 13.042969 c -0.484375 1.207031 -0.449219 2.730469 0.953125 4.136719 c 1.40625 1.40625 2.917968 1.441406 4.136718 0.953125 c 1.035157 -0.414063 8.292969 -4.984375 13.042969 -9.648438 l 2.402344 -2.398437 l 16.160156 -16.160157 c 2.742188 -2.746093 4.128907 -5.976562 3.730469 -8.167968 c -0.742188 1.390625 -1.859375 2.902344 -3.308594 4.347656 l -13.996094 13.996094 l -5.089843 -5.089844 l 13.996093 -13.996094 c 1.445313 -1.445312 2.960938 -2.566406 4.347657 -3.308594 z m 0 0" fill="url(#l)"/>
|
||||
<path d="m 95.273438 36.914062 l -2.960938 2.960938 l -2.398438 2.402344 c -4.90625 5.101562 -11.855468 10.828125 -11.855468 10.828125 c 1.011718 -0.433594 8.167968 -5.101563 12.914062 -9.769531 l 2.402344 -2.402344 l 2.960938 -2.957032 z m 0 0" fill="#62a0ea"/>
|
||||
<path d="m 87.320312 26.835938 l 13.789063 13.789062 c 0.292969 0.292969 0.292969 0.769531 0 1.0625 s -0.769531 0.292969 -1.0625 0 l -13.789063 -13.789062 c -0.292968 -0.292969 -0.292968 -0.769532 0 -1.0625 c 0.292969 -0.289063 0.769532 -0.289063 1.0625 0 z m 0 0" fill="#3584e4"/>
|
||||
<path d="m 42.421875 89.765625 c -3 3 -6.382813 4.484375 -7.554687 3.3125 c -1.171876 -1.171875 0.3125 -4.554687 3.3125 -7.554687 c 3.003906 -3.003907 6.386718 -4.488282 7.558593 -3.316407 s -0.3125 4.554688 -3.316406 7.558594 z m 0 0" fill="url(#m)"/>
|
||||
<path d="m 45.269531 70.347656 l -7.851562 12.511719 l 7.835937 7.925781 l 12.597656 -7.855468 z m -6.039062 13.171875 l 5.449219 5.449219 c 0.347656 0.347656 0.449218 0.933594 0.097656 1.160156 c -0.886719 0.570313 -2.9375 1.539063 -2.9375 1.539063 c -0.25 0.128906 -0.539063 0.164062 -0.773438 -0.066407 l -4.546875 -4.550781 c -0.234375 -0.230469 -0.207031 -0.527343 -0.066406 -0.773437 l 1.617187 -2.859375 c 0.207032 -0.363281 0.8125 -0.25 1.160157 0.101562 z m 0 0" fill="url(#n)"/>
|
||||
<path d="m 43.332031 74.777344 l 9.867188 9.867187 c 0.394531 0.390625 0.476562 0.871094 0.128906 1.066407 l -7.710937 5.253906 c -0.308594 0.210937 -0.785157 0.160156 -1.171876 -0.226563 l -6.984374 -6.988281 c -0.386719 -0.386719 -0.4375 -0.859375 -0.230469 -1.167969 l 5.234375 -7.8125 c 0.125 -0.285156 0.558594 -0.304687 0.867187 0.007813 z m 0 0" fill="url(#o)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<filter id="a" height="100%" width="100%" x="0%" y="0%">
|
||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
</filter>
|
||||
<mask id="b">
|
||||
<g filter="url(#a)">
|
||||
<rect fill-opacity="0.396" height="16" width="16"/>
|
||||
</g>
|
||||
</mask>
|
||||
<clipPath id="c">
|
||||
<rect height="152" width="192"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -168 -16)">
|
||||
<path d="m 29 112 c -4.433594 0 -8 -3.566406 -8 -8 v -2 c 0 4.433594 3.566406 8 8 8 h 88 c 4.433594 0 8 -3.566406 8 -8 v 2 c 0 4.433594 -3.566406 8 -8 8 z m 0 0" fill="#f6f5f4"/>
|
||||
</g>
|
||||
<g fill="#2e3436">
|
||||
<path d="m 4 2 v 2 h 5.585938 l 2 -2 z m -2 3 c -0.5 0 -1 0.5 -1 1 v 4 c 0 0.5 0.5 1 1 1 h 1 v -2 h 2 c 0 -0.265625 0.105469 -0.519531 0.292969 -0.707031 l 3.292969 -3.292969 z m 11.414062 0 l -4 4 h 3.585938 v 2 h 1 c 0.5 0 1 -0.5 1 -1 v -4 c 0 -0.5 -0.5 -1 -1 -1 z m -9.414062 5 v 5 h 8 v -5 h -3.585938 l -0.707031 0.707031 c -0.1875 0.1875 -0.441406 0.292969 -0.707031 0.292969 h -1 c -0.550781 0 -1 -0.449219 -1 -1 z m 0 0"/>
|
||||
<path d="m 6 10 h 1 l 9 -9 l -1 -1 l -9 9 z m 0 0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -12,3 +12,12 @@ install_data('org.gtk.PrintEditor4.desktop', install_dir: gtk_applicationsdir)
|
||||
|
||||
# appdata
|
||||
install_data('org.gtk.PrintEditor4.appdata.xml', install_dir: gtk_appdatadir)
|
||||
|
||||
# icons
|
||||
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
|
||||
|
||||
foreach size: ['scalable', 'symbolic']
|
||||
install_subdir('data/' + size,
|
||||
install_dir: icontheme_dir
|
||||
)
|
||||
endforeach
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Name=Print Editor
|
||||
Comment=A simple editor demonstrating GTK printing
|
||||
Exec=gtk4-print-editor %f
|
||||
Icon=text-editor-symbolic
|
||||
Icon=org.gtk.PrintEditor4.Devel
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
|
||||
@@ -633,7 +633,7 @@ activate_about (GSimpleAction *action,
|
||||
"website", "http://www.gtk.org",
|
||||
"comments", "Program to demonstrate GTK printing",
|
||||
"authors", (const char *[]){ "Alexander Larsson", NULL },
|
||||
"logo-icon-name", "text-editor-symbolic",
|
||||
"logo-icon-name", "org.gtk.PrintEditor4.Devel",
|
||||
"title", "About GTK Print Editor",
|
||||
"system-information", sysinfo->str,
|
||||
NULL);
|
||||
@@ -781,6 +781,8 @@ activate (GApplication *app)
|
||||
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (main_window), TRUE);
|
||||
update_title (GTK_WINDOW (main_window));
|
||||
|
||||
gtk_widget_add_css_class (main_window, "devel");
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (main_window), box);
|
||||
|
||||
|
||||
@@ -436,7 +436,6 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="title">GTK Widget Factory</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar1">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="stack_switcher">
|
||||
<property name="stack">toplevel_stack</property>
|
||||
|
||||
@@ -1423,7 +1423,6 @@ the search bar below the header bar.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
@@ -1537,7 +1536,6 @@ GtkMenuButton, GtkRevealer and GtkListBox.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -177,6 +177,7 @@ def ConvertToDocbook(infile, outfile):
|
||||
subprocess.check_call(["pandoc", infile, "-o", outfile,
|
||||
"--from=" + input_format,
|
||||
"--to=" + output_format,
|
||||
"--standalone",
|
||||
"--top-level-division=" + division])
|
||||
|
||||
def ExpandGtkDocAbbreviations(infile, outfile):
|
||||
|
||||
@@ -54,8 +54,9 @@
|
||||
<section>
|
||||
<xi:include href="xml/gtkfilter.xml" />
|
||||
<xi:include href="xml/gtkcustomfilter.xml" />
|
||||
<xi:include href="xml/gtkstringfilter.xml" />
|
||||
<xi:include href="xml/gtkmultifilter.xml" />
|
||||
<xi:include href="xml/gtkstringfilter.xml" />
|
||||
<xi:include href="xml/gtkfilefilter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkflattenlistmodel.xml" />
|
||||
<xi:include href="xml/gtkmaplistmodel.xml" />
|
||||
@@ -64,9 +65,9 @@
|
||||
<section>
|
||||
<xi:include href="xml/gtksorter.xml" />
|
||||
<xi:include href="xml/gtkcustomsorter.xml" />
|
||||
<xi:include href="xml/gtkmultisorter.xml" />
|
||||
<xi:include href="xml/gtkstringsorter.xml" />
|
||||
<xi:include href="xml/gtknumericsorter.xml" />
|
||||
<xi:include href="xml/gtkmultisorter.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionmodel.xml" />
|
||||
<section>
|
||||
@@ -74,6 +75,7 @@
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<xi:include href="xml/gtkmultiselection.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionfiltermodel.xml" />
|
||||
<xi:include href="xml/gtkbookmarklist.xml" />
|
||||
<xi:include href="xml/gtkdirectorylist.xml" />
|
||||
<xi:include href="xml/gtkstringlist.xml" />
|
||||
@@ -91,7 +93,9 @@
|
||||
<xi:include href="xml/gtklistview.xml" />
|
||||
<xi:include href="xml/gtkgridview.xml" />
|
||||
<xi:include href="xml/gtkcolumnview.xml" />
|
||||
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
|
||||
<section>
|
||||
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkdropdown.xml" />
|
||||
</chapter>
|
||||
|
||||
@@ -219,6 +223,7 @@
|
||||
<xi:include href="xml/gtksearchentry.xml" />
|
||||
<xi:include href="xml/gtksearchbar.xml" />
|
||||
<xi:include href="xml/gtkeditablelabel.xml" />
|
||||
<xi:include href="xml/gtksuggestionentry.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="TextWidgetObjects">
|
||||
@@ -284,7 +289,6 @@
|
||||
<xi:include href="xml/gtkfilechoosernative.xml" />
|
||||
<xi:include href="xml/gtkfilechooserdialog.xml" />
|
||||
<xi:include href="xml/gtkfilechooserwidget.xml" />
|
||||
<xi:include href="xml/gtkfilefilter.xml" />
|
||||
<xi:include href="xml/gtkfontchooser.xml" />
|
||||
<xi:include href="xml/gtkfontbutton.xml" />
|
||||
<xi:include href="xml/gtkfontchooserwidget.xml" />
|
||||
|
||||
@@ -348,6 +348,7 @@ GtkBitset
|
||||
gtk_bitset_ref
|
||||
gtk_bitset_unref
|
||||
gtk_bitset_new_empty
|
||||
gtk_bitset_new_range
|
||||
gtk_bitset_copy
|
||||
<SUBSECTION>
|
||||
gtk_bitset_contains
|
||||
@@ -355,6 +356,9 @@ gtk_bitset_is_empty
|
||||
gtk_bitset_equals
|
||||
gtk_bitset_get_minimum
|
||||
gtk_bitset_get_maximum
|
||||
gtk_bitset_get_size
|
||||
gtk_bitset_get_size_in_range
|
||||
gtk_bitset_get_nth
|
||||
<SUBSECTION>
|
||||
gtk_bitset_remove_all
|
||||
gtk_bitset_add
|
||||
@@ -371,7 +375,7 @@ gtk_bitset_subtract
|
||||
gtk_bitset_difference
|
||||
gtk_bitset_shift_left
|
||||
gtk_bitset_shift_right
|
||||
gtk_bitset_slice
|
||||
gtk_bitset_splice
|
||||
<SUBSECTION>
|
||||
GtkBitsetIter
|
||||
gtk_bitset_iter_init_first
|
||||
@@ -419,6 +423,7 @@ gtk_selection_model_get_type
|
||||
GtkNoSelection
|
||||
gtk_no_selection_new
|
||||
gtk_no_selection_get_model
|
||||
gtk_no_selection_set_model
|
||||
<SUBSECTION Private>
|
||||
gtk_no_selection_get_type
|
||||
</SECTION>
|
||||
@@ -430,6 +435,7 @@ GtkSingleSelection
|
||||
GTK_INVALID_LIST_POSITION
|
||||
gtk_single_selection_new
|
||||
gtk_single_selection_get_model
|
||||
gtk_single_selection_set_model
|
||||
gtk_single_selection_get_selected
|
||||
gtk_single_selection_set_selected
|
||||
gtk_single_selection_get_selected_item
|
||||
@@ -446,6 +452,8 @@ gtk_single_selection_get_type
|
||||
<TITLE>GtkMultiSeledction</TITLE>
|
||||
GtkMultiSelection
|
||||
gtk_multi_selection_new
|
||||
gtk_multi_selection_get_model
|
||||
gtk_multi_selection_set_model
|
||||
<SUBSECTION Private>
|
||||
gtk_multi_selection_get_type
|
||||
</SECTION>
|
||||
@@ -1292,23 +1300,19 @@ gtk_file_chooser_get_current_name
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_get_file
|
||||
gtk_file_chooser_set_file
|
||||
gtk_file_chooser_select_file
|
||||
gtk_file_chooser_unselect_file
|
||||
gtk_file_chooser_select_all
|
||||
gtk_file_chooser_unselect_all
|
||||
gtk_file_chooser_get_files
|
||||
gtk_file_chooser_set_current_folder
|
||||
gtk_file_chooser_get_current_folder
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_filter
|
||||
gtk_file_chooser_remove_filter
|
||||
gtk_file_chooser_list_filters
|
||||
gtk_file_chooser_get_filters
|
||||
gtk_file_chooser_set_filter
|
||||
gtk_file_chooser_get_filter
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_shortcut_folder
|
||||
gtk_file_chooser_remove_shortcut_folder
|
||||
gtk_file_chooser_list_shortcut_folders
|
||||
gtk_file_chooser_get_shortcut_folders
|
||||
<SUBSECTION>
|
||||
gtk_file_chooser_add_choice
|
||||
gtk_file_chooser_remove_choice
|
||||
@@ -1405,18 +1409,13 @@ GtkFileChooserButtonPrivate
|
||||
<SECTION>
|
||||
<FILE>gtkfilefilter</FILE>
|
||||
GtkFileFilter
|
||||
GtkFileFilterInfo
|
||||
GtkFileFilterFlags
|
||||
GtkFileFilterFunc
|
||||
gtk_file_filter_new
|
||||
gtk_file_filter_set_name
|
||||
gtk_file_filter_get_name
|
||||
gtk_file_filter_add_mime_type
|
||||
gtk_file_filter_add_pattern
|
||||
gtk_file_filter_add_pixbuf_formats
|
||||
gtk_file_filter_add_custom
|
||||
gtk_file_filter_get_needed
|
||||
gtk_file_filter_filter
|
||||
gtk_file_filter_get_attributes
|
||||
|
||||
<SUBSECTION Serialization>
|
||||
gtk_file_filter_new_from_gvariant
|
||||
@@ -1441,6 +1440,8 @@ gtk_directory_list_get_file
|
||||
gtk_directory_list_set_file
|
||||
gtk_directory_list_get_io_priority
|
||||
gtk_directory_list_set_io_priority
|
||||
gtk_directory_list_get_monitored
|
||||
gtk_directory_list_set_monitored
|
||||
gtk_directory_list_is_loading
|
||||
gtk_directory_list_get_error
|
||||
<SUBSECTION Standard>
|
||||
@@ -1535,11 +1536,13 @@ gtk_custom_filter_get_type
|
||||
<TITLE>GtkFilterListModel</TITLE>
|
||||
GtkFilterListModel
|
||||
gtk_filter_list_model_new
|
||||
gtk_filter_list_model_new_for_type
|
||||
gtk_filter_list_model_set_model
|
||||
gtk_filter_list_model_get_model
|
||||
gtk_filter_list_model_set_filter
|
||||
gtk_filter_list_model_get_filter
|
||||
gtk_filter_list_model_set_incremental
|
||||
gtk_filter_list_model_get_incremental
|
||||
gtk_filter_list_model_get_pending
|
||||
<SUBSECTION Standard>
|
||||
GTK_FILTER_LIST_MODEL
|
||||
GTK_IS_FILTER_LIST_MODEL
|
||||
@@ -2694,7 +2697,6 @@ gtk_size_group_get_type
|
||||
<TITLE>GtkSliceListModel</TITLE>
|
||||
GtkSliceListModel
|
||||
gtk_slice_list_model_new
|
||||
gtk_slice_list_model_new_for_type
|
||||
gtk_slice_list_model_set_model
|
||||
gtk_slice_list_model_get_model
|
||||
gtk_slice_list_model_set_offset
|
||||
@@ -2826,11 +2828,13 @@ gtk_tree_list_row_sorter_get_type
|
||||
<TITLE>GtkSortListModel</TITLE>
|
||||
GtkSortListModel
|
||||
gtk_sort_list_model_new
|
||||
gtk_sort_list_model_new_for_type
|
||||
gtk_sort_list_model_set_sorter
|
||||
gtk_sort_list_model_get_sorter
|
||||
gtk_sort_list_model_set_model
|
||||
gtk_sort_list_model_get_model
|
||||
gtk_sort_list_model_set_incremental
|
||||
gtk_sort_list_model_get_incremental
|
||||
gtk_sort_list_model_get_peanding
|
||||
<SUBSECTION Standard>
|
||||
GTK_SORT_LIST_MODEL
|
||||
GTK_IS_SORT_LIST_MODEL
|
||||
@@ -3419,6 +3423,7 @@ gtk_tree_list_row_get_type
|
||||
<SECTION>
|
||||
<FILE>gtktreeexpander</FILE>
|
||||
<TITLE>GtkTreeExpander</TITLE>
|
||||
GtkTreeExpander
|
||||
gtk_tree_expander_new
|
||||
gtk_tree_expander_get_child
|
||||
gtk_tree_expander_set_child
|
||||
@@ -7540,12 +7545,27 @@ gtk_expression_watch_unwatch
|
||||
<SUBSECTION>
|
||||
gtk_property_expression_new
|
||||
gtk_property_expression_new_for_pspec
|
||||
gtk_property_expression_get_expression
|
||||
gtk_property_expression_get_pspec
|
||||
gtk_constant_expression_new
|
||||
gtk_constant_expression_new_for_value
|
||||
gtk_constant_expression_get_value
|
||||
gtk_object_expression_new
|
||||
gtk_object_expression_get_object
|
||||
gtk_closure_expression_new
|
||||
gtk_cclosure_expression_new
|
||||
|
||||
<SUBSECTION>
|
||||
GTK_VALUE_HOLDS_EXPRESSION
|
||||
gtk_value_set_expression
|
||||
gtk_value_take_expression
|
||||
gtk_value_get_expression
|
||||
gtk_value_dup_expression
|
||||
|
||||
<SUBSECTION>
|
||||
GtkParamSpecExpression
|
||||
gtk_param_spec_expression
|
||||
|
||||
<SUBSECTION Standard>
|
||||
GTK_IS_EXPRESSION
|
||||
GTK_TYPE_EXPRESSION
|
||||
@@ -7606,6 +7626,42 @@ gtk_string_list_take
|
||||
gtk_string_list_remove
|
||||
gtk_string_list_splice
|
||||
gtk_string_list_get_string
|
||||
<SUBSECTION>
|
||||
GtkStringObject
|
||||
gtk_string_object_new
|
||||
gtk_string_object_get_string
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkselectionfiltermodel</FILE>
|
||||
<TITLE>GtkSelectionFilterModel</TITLE>
|
||||
GtkSelectionFilterModel
|
||||
gtk_selection_filter_model_new
|
||||
gtk_selection_filter_model_new_for_type
|
||||
gtk_selection_filter_model_set_model
|
||||
gtk_selection_filter_model_get_model
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtksuggestionentry</FILE>
|
||||
<TITLE>GtkSuggestionEntry</TITLE>
|
||||
GtkSuggestionEntry
|
||||
gtk_suggestion_entry_new
|
||||
gtk_suggestion_entry_set_model
|
||||
gtk_suggestion_entry_get_model
|
||||
gtk_suggestion_entry_set_from_strings
|
||||
gtk_suggestion_entry_set_factory
|
||||
gtk_suggestion_entry_get_factory
|
||||
gtk_suggestion_entry_set_expression
|
||||
gtk_suggestion_entry_get_expression
|
||||
gtk_suggestion_entry_set_use_filter
|
||||
gtk_suggestion_entry_get_use_filter
|
||||
gtk_suggestion_entry_set_insert_selection
|
||||
gtk_suggestion_entry_get_insert_selection
|
||||
gtk_suggestion_entry_set_insert_prefix
|
||||
gtk_suggestion_entry_get_insert_prefix
|
||||
gtk_suggestion_entry_set_show_button
|
||||
gtk_suggestion_entry_get_show_button
|
||||
gtk_suggestion_entry_set_minimum_length
|
||||
gtk_suggestion_entry_get_minimum_length
|
||||
</SECTION>
|
||||
|
||||
@@ -19,6 +19,7 @@ gtk_assistant_get_type
|
||||
gtk_assistant_page_get_type
|
||||
gtk_bin_layout_get_type
|
||||
gtk_bitset_get_type
|
||||
gtk_expression_get_type
|
||||
gtk_bookmark_list_get_type
|
||||
gtk_box_get_type
|
||||
gtk_box_layout_get_type
|
||||
@@ -29,6 +30,7 @@ gtk_builder_list_item_factory_get_type
|
||||
gtk_builder_scope_get_type
|
||||
gtk_button_get_type
|
||||
gtk_calendar_get_type
|
||||
gtk_cclosure_expression_get_type
|
||||
gtk_cell_area_get_type
|
||||
gtk_cell_area_box_get_type
|
||||
gtk_cell_area_context_get_type
|
||||
@@ -46,6 +48,7 @@ gtk_cell_renderer_toggle_get_type
|
||||
gtk_cell_view_get_type
|
||||
gtk_center_layout_get_type
|
||||
gtk_check_button_get_type
|
||||
gtk_closure_expression_get_type
|
||||
gtk_color_button_get_type
|
||||
gtk_color_chooser_get_type
|
||||
gtk_color_chooser_dialog_get_type
|
||||
@@ -54,6 +57,7 @@ gtk_column_view_get_type
|
||||
gtk_column_view_column_get_type
|
||||
gtk_combo_box_get_type
|
||||
gtk_combo_box_text_get_type
|
||||
gtk_constant_expression_get_type
|
||||
gtk_constraint_get_type
|
||||
gtk_constraint_guide_get_type
|
||||
gtk_constraint_layout_get_type
|
||||
@@ -150,6 +154,7 @@ gtk_no_selection_get_type
|
||||
gtk_notebook_get_type
|
||||
gtk_notebook_page_get_type
|
||||
gtk_numeric_sorter_get_type
|
||||
gtk_object_expression_get_type
|
||||
gtk_orientable_get_type
|
||||
gtk_overlay_get_type
|
||||
gtk_overlay_layout_get_type
|
||||
@@ -172,6 +177,7 @@ gtk_print_operation_preview_get_type
|
||||
gtk_print_settings_get_type
|
||||
@DISABLE_ON_W32@gtk_print_unix_dialog_get_type
|
||||
gtk_progress_bar_get_type
|
||||
gtk_property_expression_get_type
|
||||
gtk_radio_button_get_type
|
||||
gtk_range_get_type
|
||||
gtk_recent_manager_get_type
|
||||
@@ -184,6 +190,7 @@ gtk_scrollbar_get_type
|
||||
gtk_scrolled_window_get_type
|
||||
gtk_search_bar_get_type
|
||||
gtk_search_entry_get_type
|
||||
gtk_selection_filter_model_get_type
|
||||
gtk_selection_model_get_type
|
||||
gtk_separator_get_type
|
||||
gtk_settings_get_type
|
||||
@@ -213,6 +220,7 @@ gtk_string_filter_get_type
|
||||
gtk_string_list_get_type
|
||||
gtk_string_object_get_type
|
||||
gtk_string_sorter_get_type
|
||||
gtk_suggestion_entry_get_type
|
||||
gtk_switch_get_type
|
||||
gtk_level_bar_get_type
|
||||
gtk_style_context_get_type
|
||||
@@ -228,6 +236,7 @@ gtk_text_view_get_type
|
||||
gtk_toggle_button_get_type
|
||||
gtk_tree_drag_dest_get_type
|
||||
gtk_tree_drag_source_get_type
|
||||
gtk_tree_expander_get_type
|
||||
gtk_tree_list_model_get_type
|
||||
gtk_tree_list_row_get_type
|
||||
gtk_tree_list_row_sorter_get_type
|
||||
|
||||
@@ -137,8 +137,41 @@ use gtk_button_new_from_icon_name().
|
||||
|
||||
### Stop using GtkWidget event signals
|
||||
|
||||
Event controllers and #GtkGestures replace event signals in GTK 4.
|
||||
They have been backported to GTK 3.x so you can prepare for this change.
|
||||
Event controllers and gestures replace event signals in GTK 4.
|
||||
|
||||
Most of them have been backported to GTK 3.x so you can prepare
|
||||
for this change.
|
||||
|
||||
| Signal | Event controller |
|
||||
| --- | --- |
|
||||
| ::event | #GtkEventControllerLegacy |
|
||||
| ::event-after | #GtkEventControllerLegacy |
|
||||
| ::button-press-event | #GtkGestureClick |
|
||||
| ::button-release-event | #GtkGestureClick |
|
||||
| ::touch-event | various touch gestures |
|
||||
| ::scroll-event | #GtkEventControllerScroll |
|
||||
| ::motion-notify-event | #GtkEventControllerMotion |
|
||||
| ::delete-event | - |
|
||||
| ::key-press-event | #GtkEventControllerKey |
|
||||
| ::key-release-event | #GtkEventControllerKey |
|
||||
| ::enter-notify-event | #GtkEventControllerMotion |
|
||||
| ::leave-notify-event | #GtkEventControllerMotion |
|
||||
| ::configure-event | replaced by #GdkSurface::size-changed |
|
||||
| ::focus-in-event | #GtkEventControllerFocus |
|
||||
| ::focus-out-event | #GtkEventControllerFocus |
|
||||
| ::map-event | replaced by #GdkSurface:mapped |
|
||||
| ::unmap-event | replaced by #GdkSurface:mapped |
|
||||
| ::property-notify-event | replaced by #GdkClipboard |
|
||||
| ::selection-clear-event | replaced by #GdkClipboard |
|
||||
| ::selection-request-event | replaced by #GdkClipboard |
|
||||
| ::selection-notify-event | replaced by #GdkClipboard |
|
||||
| Drag-and-Drop signals | #GtkDragSource, #GtkDropTarget |
|
||||
| ::proximity-in-event | #GtkGestureStylus |
|
||||
| ::proximity-out-event | #GtkGestureStylus |
|
||||
| ::visibility-notify-event | - |
|
||||
| ::window-state-event | replaced by #GdkToplevel:state |
|
||||
| ::damage-event | - |
|
||||
| ::grab-broken-event | - |
|
||||
|
||||
### Set a proper application ID
|
||||
|
||||
@@ -170,7 +203,7 @@ in GTK 3, you can prepare for the switch by using gtk_widget_destroy()
|
||||
only on toplevel windows, and replace all other uses with
|
||||
gtk_container_remove() or g_object_unref().
|
||||
|
||||
### Reduce the use of generic container APIs</title>
|
||||
### Reduce the use of generic container APIs
|
||||
|
||||
GTK 4 removes gtk_container_add() and gtk_container_remove(). While there
|
||||
is not always a replacement for gtk_container_remove() in GTK 3, you can
|
||||
@@ -411,6 +444,7 @@ and gtk_box_append(). You can also reorder box children as necessary.
|
||||
The gtk_header_bar_set_show_close_button() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_show_title_buttons(). The
|
||||
corresponding getter and the property itself have also been renamed.
|
||||
The default value of the property is now %TRUE instead of %FALSE.
|
||||
|
||||
The gtk_header_bar_set_custom_title() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_title_widget(). The
|
||||
@@ -530,6 +564,26 @@ by a layout manager (if they are layout-related), or handled in some
|
||||
other way. One possibility is to use child meta objects, as seen with
|
||||
GtkAssistantPage, GtkStackPage and the like.
|
||||
|
||||
The replacements for gtk_container_add() are:
|
||||
|
||||
| Widget | Replacement |
|
||||
| ------ | ----------- |
|
||||
| GtkActionBar | gtk_action_bar_pack_start(), gtk_action_bar_pack_end() |
|
||||
| GtkBox | gtk_box_append() |
|
||||
| GtkExpander | gtk_expander_set_child() |
|
||||
| GtkFixed | gtk_fixed_put() |
|
||||
| GtkFlowBox | gtk_flow_box_insert() |
|
||||
| GtkGrid | gtk_grid_attach() |
|
||||
| GtkHeaderBar | gtk_header_bar_pack_start(), gtk_header_bar_pack_end() |
|
||||
| GtkIconView | - |
|
||||
| GtkInfoBar | gtk_info_bar_add_child() |
|
||||
| GtkListBox | gtk_list_box_insert() |
|
||||
| GtkNotebook | gtk_notebook_append_page() |
|
||||
| GtkPaned | gtk_paned_set_start_child(), gtk_paned_set_end_child() |
|
||||
| GtkStack | gtk_stack_add_named() |
|
||||
| GtkTextView | gtk_text_view_add_child_at_anchor(), gtk_text_view_add_overlay() |
|
||||
| GtkTreeView | - |
|
||||
|
||||
### Stop using GtkContainer::border-width
|
||||
|
||||
GTK 4 has removed the #GtkContainer::border-width property (together
|
||||
|
||||
@@ -123,6 +123,32 @@ the number of listitems they create such as with gtk_grid_view_set_max_columns()
|
||||
and developers running into performance problems should definitely study the
|
||||
tradeoffs of those and experiment with them.
|
||||
|
||||
## Choosing the right model {#model-choosing}
|
||||
|
||||
GTK offers a wide variety of wrapping models which change or supplement an
|
||||
existing model (or models) in some way. But when it comes to storing your
|
||||
actual data, there are only a few ready-made choices available: #GListStore
|
||||
and #GtkStringList.
|
||||
|
||||
GListStore is backed by a balanced tree and has performance characteristics
|
||||
that are expected for that data structure. It works reasonably well for dataset
|
||||
sizes in the 1,000,000 range, and can handle insertions and deletions. It uses
|
||||
a cached iter to make linear access to the items fast.
|
||||
|
||||
GtkStringList is not a general store - it can only handle strings. It is
|
||||
backed by an dynamically allocated array and has performance characteristics
|
||||
that are expected for that data structure. GtkStringList is a good fit for any
|
||||
place where you would otherwise use `char*[]` and works best if the dataset
|
||||
is not very dynamic.
|
||||
|
||||
If these models don't fit your use case or scalability requirements, you
|
||||
should make a custom #GListModel. It is a small interface and not very hard
|
||||
to implement.
|
||||
|
||||
For asymptotic performance comparisons between tree- and array-based
|
||||
implementations, see this
|
||||
[article](https://en.wikipedia.org/wiki/Dynamic_array#Performance).
|
||||
|
||||
## Displaying trees {#displaying-trees}
|
||||
|
||||
While #GtkTreeView provided built-in support for trees, the list widgets, and
|
||||
@@ -183,7 +209,7 @@ transitioning code for easy lookup:
|
||||
| #GtkTreeModel | #GListModel |
|
||||
| #GtkTreePath | #guint position, #GtkTreeListRow |
|
||||
| #GtkTreeIter | #guint position |
|
||||
| GtkTreeRowReference | #GObject item |
|
||||
| #GtkTreeRowReference | #GObject item |
|
||||
| #GtkListStore | #GListStore |
|
||||
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
|
||||
| #GtkTreeSelection | #GtkSelectionModel |
|
||||
@@ -198,4 +224,6 @@ transitioning code for easy lookup:
|
||||
| #GtkCellLayout | #GtkListItemFactory |
|
||||
| #GtkCellArea | #GtkWidget |
|
||||
| #GtkCellRenderer | #GtkWidget |
|
||||
| #GtkComboBoxText | #GtkSuggestionEntry |
|
||||
| #GtkEntryCompletion | #GtkSuggestionEntry |
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lines_label">
|
||||
<property name="visible">0</property>
|
||||
|
||||
@@ -15,7 +15,6 @@ new_window (GApplication *app,
|
||||
gtk_window_set_icon_name (GTK_WINDOW (window), "sunny");
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef GDK_ARRAY_TYPE_NAME
|
||||
#define GDK_ARRAY_TYPE_NAME GdkArray
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_NAME
|
||||
#define GDK_ARRAY_NAME gdk_array
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_ELEMENT_TYPE
|
||||
#define GDK_ARRAY_ELEMENT_TYPE gpointer
|
||||
#endif
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
#if GDK_ARRAY_PREALLOC == 0
|
||||
#undef GDK_ARRAY_PREALLOC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
#define GDK_ARRAY_REAL_SIZE(_size) ((_size) + 1)
|
||||
#else
|
||||
#define GDK_ARRAY_REAL_SIZE(_size) (_size)
|
||||
#endif
|
||||
|
||||
/* make this readable */
|
||||
#define _T_ GDK_ARRAY_ELEMENT_TYPE
|
||||
#define GdkArray GDK_ARRAY_TYPE_NAME
|
||||
#define gdk_array_paste_more(GDK_ARRAY_NAME, func_name) GDK_ARRAY_NAME ## _ ## func_name
|
||||
#define gdk_array_paste(GDK_ARRAY_NAME, func_name) gdk_array_paste_more (GDK_ARRAY_NAME, func_name)
|
||||
#define gdk_array(func_name) gdk_array_paste (GDK_ARRAY_NAME, func_name)
|
||||
|
||||
typedef struct GdkArray GdkArray;
|
||||
|
||||
struct GdkArray
|
||||
{
|
||||
_T_ *start;
|
||||
_T_ *end;
|
||||
_T_ *end_allocation;
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
_T_ preallocated[GDK_ARRAY_REAL_SIZE(GDK_ARRAY_PREALLOC)];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */
|
||||
static inline void
|
||||
gdk_array(init) (GdkArray *self)
|
||||
{
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
self->start = self->preallocated;
|
||||
self->end = self->start;
|
||||
self->end_allocation = self->start + GDK_ARRAY_PREALLOC;
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
*self->start = *(_T_[1]) {};
|
||||
#endif
|
||||
#else
|
||||
self->start = NULL;
|
||||
self->end = NULL;
|
||||
self->end_allocation = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
gdk_array(free_elements) (_T_ *start,
|
||||
_T_ *end)
|
||||
{
|
||||
#ifdef GDK_ARRAY_FREE_FUNC
|
||||
_T_ *e;
|
||||
for (e = start; e < end; e++)
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
GDK_ARRAY_FREE_FUNC (e);
|
||||
#else
|
||||
GDK_ARRAY_FREE_FUNC (*e);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* no G_GNUC_UNUSED here */
|
||||
static inline void
|
||||
gdk_array(clear) (GdkArray *self)
|
||||
{
|
||||
gdk_array(free_elements) (self->start, self->end);
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start != self->preallocated)
|
||||
#endif
|
||||
g_free (self->start);
|
||||
gdk_array(init) (self);
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gdk_array(get_data) (const GdkArray *self)
|
||||
{
|
||||
return self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gdk_array(index) (const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return self->start + pos;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gdk_array(get_capacity) (const GdkArray *self)
|
||||
{
|
||||
return self->end_allocation - self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gdk_array(get_size) (const GdkArray *self)
|
||||
{
|
||||
return self->end - self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gboolean
|
||||
gdk_array(is_empty) (const GdkArray *self)
|
||||
{
|
||||
return self->end == self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(reserve) (GdkArray *self,
|
||||
gsize n)
|
||||
{
|
||||
gsize new_size, size;
|
||||
|
||||
if (n <= gdk_array(get_capacity) (self))
|
||||
return;
|
||||
|
||||
size = gdk_array(get_size) (self);
|
||||
new_size = 1 << g_bit_storage (MAX (GDK_ARRAY_REAL_SIZE (n), 16) - 1);
|
||||
|
||||
#ifdef GDK_ARRAY_PREALLOC
|
||||
if (self->start == self->preallocated)
|
||||
{
|
||||
self->start = g_new (_T_, new_size);
|
||||
memcpy (self->start, self->preallocated, sizeof (_T_) * GDK_ARRAY_REAL_SIZE (size));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
if (self->start == NULL)
|
||||
{
|
||||
self->start = g_new (_T_, new_size);
|
||||
*self->start = *(_T_[1]) {};
|
||||
}
|
||||
else
|
||||
#endif
|
||||
self->start = g_renew (_T_, self->start, new_size);
|
||||
|
||||
self->end = self->start + size;
|
||||
self->end_allocation = self->start + new_size;
|
||||
#ifdef GDK_ARRAY_NULL_TERMINATED
|
||||
self->end_allocation--;
|
||||
#endif
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(splice) (GdkArray *self,
|
||||
gsize pos,
|
||||
gsize removed,
|
||||
_T_ *additions,
|
||||
gsize added)
|
||||
{
|
||||
gsize size;
|
||||
gsize remaining;
|
||||
|
||||
size = gdk_array(get_size) (self);
|
||||
g_assert (pos + removed <= size);
|
||||
remaining = size - pos - removed;
|
||||
|
||||
gdk_array(free_elements) (gdk_array(index) (self, pos),
|
||||
gdk_array(index) (self, pos + removed));
|
||||
|
||||
gdk_array(reserve) (self, size - removed + added);
|
||||
|
||||
if (GDK_ARRAY_REAL_SIZE (remaining) && removed != added)
|
||||
memmove (gdk_array(index) (self, pos + added),
|
||||
gdk_array(index) (self, pos + removed),
|
||||
GDK_ARRAY_REAL_SIZE (remaining) * sizeof (_T_));
|
||||
|
||||
if (added)
|
||||
{
|
||||
if (additions)
|
||||
memcpy (gdk_array(index) (self, pos),
|
||||
additions,
|
||||
added * sizeof (_T_));
|
||||
else
|
||||
memset (gdk_array(index) (self, pos), 0, added * sizeof (_T_));
|
||||
}
|
||||
|
||||
|
||||
/* might overflow, but does the right thing */
|
||||
self->end += added - removed;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(set_size) (GdkArray *self,
|
||||
gsize new_size)
|
||||
{
|
||||
gsize old_size = gdk_array(get_size) (self);
|
||||
if (new_size > old_size)
|
||||
gdk_array(splice) (self, old_size, 0, NULL, new_size - old_size);
|
||||
else
|
||||
gdk_array(splice) (self, new_size, old_size - new_size, NULL, 0);
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gdk_array(append) (GdkArray *self,
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
_T_ *value)
|
||||
#else
|
||||
_T_ value)
|
||||
#endif
|
||||
{
|
||||
gdk_array(splice) (self,
|
||||
gdk_array(get_size) (self),
|
||||
0,
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
value,
|
||||
#else
|
||||
&value,
|
||||
#endif
|
||||
1);
|
||||
}
|
||||
|
||||
#ifdef GDK_ARRAY_BY_VALUE
|
||||
G_GNUC_UNUSED static _T_ *
|
||||
gdk_array(get) (const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return gdk_array(index) (self, pos);
|
||||
}
|
||||
#else
|
||||
G_GNUC_UNUSED static _T_
|
||||
gdk_array(get) (const GdkArray *self,
|
||||
gsize pos)
|
||||
{
|
||||
return *gdk_array(index) (self, pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GDK_ARRAY_NO_UNDEF
|
||||
|
||||
#undef _T_
|
||||
#undef GdkArray
|
||||
#undef gdk_array_paste_more
|
||||
#undef gdk_array_paste
|
||||
#undef gdk_array
|
||||
#undef GDK_ARRAY_REAL_SIZE
|
||||
|
||||
#undef GDK_ARRAY_BY_VALUE
|
||||
#undef GDK_ARRAY_ELEMENT_TYPE
|
||||
#undef GDK_ARRAY_FREE_FUNC
|
||||
#undef GDK_ARRAY_NAME
|
||||
#undef GDK_ARRAY_NULL_TERMINATED
|
||||
#undef GDK_ARRAY_PREALLOC
|
||||
#undef GDK_ARRAY_TYPE_NAME
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
|
||||
|
||||
#mesondefine GDK_WINDOWING_X11
|
||||
#mesondefine GDK_WINDOWING_BROADWAY
|
||||
#mesondefine GDK_WINDOWING_MACOS
|
||||
#mesondefine GDK_WINDOWING_WAYLAND
|
||||
#mesondefine GDK_WINDOWING_WIN32
|
||||
|
||||
|
||||
@@ -875,7 +875,7 @@ init (void)
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#if defined(G_OS_UNIX) && !defined(__APPLE__)
|
||||
file_transfer_portal_register ();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -907,7 +907,7 @@ init (void)
|
||||
|
||||
g_slist_free (formats);
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#if defined(G_OS_UNIX) && !defined(__APPLE__)
|
||||
file_transfer_portal_register ();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
#include "broadway/gdkprivate-broadway.h"
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_MACOS
|
||||
#include "macos/gdkmacosdisplay-private.h"
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include "win32/gdkwin32.h"
|
||||
#include "win32/gdkprivate-win32.h"
|
||||
@@ -262,6 +266,9 @@ static GdkBackend gdk_backends[] = {
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
{ "quartz", _gdk_quartz_display_open },
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_MACOS
|
||||
{ "macos", _gdk_macos_display_open },
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
{ "win32", _gdk_win32_display_open },
|
||||
#endif
|
||||
|
||||
@@ -283,6 +283,10 @@
|
||||
#define GDK_KEY_dead_invertedbreve 0xfe6d
|
||||
#define GDK_KEY_dead_belowcomma 0xfe6e
|
||||
#define GDK_KEY_dead_currency 0xfe6f
|
||||
#define GDK_KEY_dead_lowline 0xfe90
|
||||
#define GDK_KEY_dead_aboveverticalline 0xfe91
|
||||
#define GDK_KEY_dead_belowverticalline 0xfe92
|
||||
#define GDK_KEY_dead_longsolidusoverlay 0xfe93
|
||||
#define GDK_KEY_dead_a 0xfe80
|
||||
#define GDK_KEY_dead_A 0xfe81
|
||||
#define GDK_KEY_dead_e 0xfe82
|
||||
@@ -2288,6 +2292,10 @@
|
||||
#define GDK_KEY_TouchpadOn 0x1008ffb0
|
||||
#define GDK_KEY_TouchpadOff 0x1008ffb1
|
||||
#define GDK_KEY_AudioMicMute 0x1008ffb2
|
||||
#define GDK_KEY_Keyboard 0x1008ffb3
|
||||
#define GDK_KEY_WWAN 0x1008ffb4
|
||||
#define GDK_KEY_RFKill 0x1008ffb5
|
||||
#define GDK_KEY_AudioPreset 0x1008ffb6
|
||||
#define GDK_KEY_Switch_VT_1 0x1008fe01
|
||||
#define GDK_KEY_Switch_VT_2 0x1008fe02
|
||||
#define GDK_KEY_Switch_VT_3 0x1008fe03
|
||||
|
||||
+1
-1
@@ -354,7 +354,7 @@ gdk_rgba_equal (gconstpointer p1,
|
||||
*
|
||||
* Returns a textual specification of @rgba in the form
|
||||
* `rgb(r,g,b)` or
|
||||
* `rgba(r g,b,a)`,
|
||||
* `rgba(r,g,b,a)`,
|
||||
* where “r”, “g”, “b” and “a” represent the red, green,
|
||||
* blue and alpha values respectively. “r”, “g”, and “b” are
|
||||
* represented as integers in the range 0 to 255, and “a”
|
||||
|
||||
@@ -0,0 +1,718 @@
|
||||
/* GdkMacosBaseView.c
|
||||
*
|
||||
* Copyright 2005-2007 Imendio AB
|
||||
* Copyright 2011 Hiroyuki Yamamoto
|
||||
* Copyright 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#import "GdkMacosBaseView.h"
|
||||
#import "GdkMacosWindow.h"
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
/* Text Input Client */
|
||||
#define TIC_MARKED_TEXT "tic-marked-text"
|
||||
#define TIC_SELECTED_POS "tic-selected-pos"
|
||||
#define TIC_SELECTED_LEN "tic-selected-len"
|
||||
#define TIC_INSERT_TEXT "tic-insert-text"
|
||||
#define TIC_IN_KEY_DOWN "tic-in-key-down"
|
||||
|
||||
/* GtkIMContext */
|
||||
#define GIC_CURSOR_RECT "gic-cursor-rect"
|
||||
#define GIC_FILTER_KEY "gic-filter-key"
|
||||
#define GIC_FILTER_PASSTHRU 0
|
||||
#define GIC_FILTER_FILTERED 1
|
||||
|
||||
@implementation GdkMacosBaseView
|
||||
|
||||
-(id)initWithFrame:(NSRect)frameRect
|
||||
{
|
||||
if ((self = [super initWithFrame: frameRect]))
|
||||
{
|
||||
NSRect rect = NSMakeRect (0, 0, 0, 0);
|
||||
NSTrackingAreaOptions options;
|
||||
|
||||
markedRange = NSMakeRange (NSNotFound, 0);
|
||||
selectedRange = NSMakeRange (0, 0);
|
||||
[self setValue: @(YES) forKey: @"postsFrameChangedNotifications"];
|
||||
|
||||
options = (NSTrackingMouseEnteredAndExited |
|
||||
NSTrackingMouseMoved |
|
||||
NSTrackingInVisibleRect |
|
||||
NSTrackingActiveAlways);
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:rect
|
||||
options:options
|
||||
owner:(id)self
|
||||
userInfo:nil];
|
||||
[self addTrackingArea:trackingArea];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)setNeedsDisplay:(BOOL)needsDisplay
|
||||
{
|
||||
for (id child in [self subviews])
|
||||
[child setNeedsDisplay:needsDisplay];
|
||||
}
|
||||
|
||||
-(void)setOpaqueRegion:(cairo_region_t *)region
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstMouse
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)mouseDownCanMoveWindow
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstResponder
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("acceptsFirstResponder"));
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)becomeFirstResponder
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("becomeFirstResponder"));
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)resignFirstResponder
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("resignFirstResponder"));
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)setNeedsInvalidateShadow: (BOOL)invalidate
|
||||
{
|
||||
needsInvalidateShadow = invalidate;
|
||||
}
|
||||
|
||||
-(NSTrackingArea *)trackingArea
|
||||
{
|
||||
return trackingArea;
|
||||
}
|
||||
|
||||
-(GdkMacosSurface *)gdkSurface
|
||||
{
|
||||
return [(GdkMacosWindow *)[self window] gdkSurface];
|
||||
}
|
||||
|
||||
-(GdkMacosDisplay *)gdkDisplay
|
||||
{
|
||||
GdkMacosSurface *surface = [self gdkSurface];
|
||||
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (surface));
|
||||
|
||||
return GDK_MACOS_DISPLAY (display);
|
||||
}
|
||||
|
||||
-(void)keyDown:(NSEvent *)theEvent
|
||||
{
|
||||
/* NOTE: When user press Cmd+A, interpretKeyEvents: will call noop:
|
||||
* method. When user press and hold A to show the accented char window,
|
||||
* it consumed repeating key down events for key 'A' do NOT call
|
||||
* any other method. We use this behavior to determine if this key
|
||||
* down event is filtered by interpretKeyEvents.
|
||||
*/
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
|
||||
|
||||
GDK_NOTE (EVENTS, g_message ("keyDown"));
|
||||
[self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
|
||||
}
|
||||
|
||||
-(void)flagsChanged: (NSEvent *)theEvent
|
||||
{
|
||||
}
|
||||
|
||||
-(NSUInteger)characterIndexForPoint:(NSPoint)aPoint
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("characterIndexForPoint"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
-(NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange: (NSRangePointer)actualRange
|
||||
{
|
||||
GdkRectangle *rect;
|
||||
|
||||
GDK_NOTE (EVENTS, g_message ("firstRectForCharacterRange"));
|
||||
|
||||
if ((rect = g_object_get_data (G_OBJECT ([self gdkSurface]), GIC_CURSOR_RECT)))
|
||||
{
|
||||
GdkMacosDisplay *display = [self gdkDisplay];
|
||||
int ns_x, ns_y;
|
||||
|
||||
_gdk_macos_display_to_display_coords (display,
|
||||
rect->x, rect->y + rect->height,
|
||||
&ns_x, &ns_y);
|
||||
|
||||
return NSMakeRect (ns_x, ns_y, rect->width, rect->height);
|
||||
}
|
||||
|
||||
return NSMakeRect (0, 0, 0, 0);
|
||||
}
|
||||
|
||||
-(NSArray *)validAttributesForMarkedText
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("validAttributesForMarkedText"));
|
||||
return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil];
|
||||
}
|
||||
|
||||
-(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("attributedSubstringForProposedRange"));
|
||||
return nil;
|
||||
}
|
||||
|
||||
-(BOOL)hasMarkedText
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("hasMarkedText"));
|
||||
return markedRange.location != NSNotFound && markedRange.length != 0;
|
||||
}
|
||||
|
||||
-(NSRange)markedRange
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("markedRange"));
|
||||
return markedRange;
|
||||
}
|
||||
|
||||
-(NSRange)selectedRange
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("selectedRange"));
|
||||
return selectedRange;
|
||||
}
|
||||
|
||||
-(void)unmarkText
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("unmarkText"));
|
||||
|
||||
selectedRange = NSMakeRange (0, 0);
|
||||
markedRange = NSMakeRange (NSNotFound, 0);
|
||||
|
||||
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, NULL, g_free);
|
||||
}
|
||||
|
||||
-(void)setMarkedText:(id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange
|
||||
{
|
||||
const char *str;
|
||||
|
||||
GDK_NOTE (EVENTS, g_message ("setMarkedText"));
|
||||
|
||||
if (replacementRange.location == NSNotFound)
|
||||
{
|
||||
markedRange = NSMakeRange (newSelection.location, [aString length]);
|
||||
selectedRange = NSMakeRange (newSelection.location, newSelection.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
markedRange = NSMakeRange (replacementRange.location, [aString length]);
|
||||
selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length);
|
||||
}
|
||||
|
||||
if ([aString isKindOfClass: [NSAttributedString class]])
|
||||
str = [[aString string] UTF8String];
|
||||
else
|
||||
str = [aString UTF8String];
|
||||
|
||||
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, g_strdup (str), g_free);
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
TIC_SELECTED_POS,
|
||||
GUINT_TO_POINTER (selectedRange.location));
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
TIC_SELECTED_LEN,
|
||||
GUINT_TO_POINTER (selectedRange.length));
|
||||
|
||||
GDK_NOTE (EVENTS, g_message ("setMarkedText: set %s (%p, nsview %p): %s",
|
||||
TIC_MARKED_TEXT, [self gdkSurface], self,
|
||||
str ? str : "(empty)"));
|
||||
|
||||
/* handle text input changes by mouse events */
|
||||
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
|
||||
_gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
|
||||
}
|
||||
|
||||
-(void)doCommandBySelector:(SEL)aSelector
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("doCommandBySelector"));
|
||||
|
||||
if ([self respondsToSelector: aSelector])
|
||||
[self performSelector: aSelector];
|
||||
}
|
||||
|
||||
-(void)insertText:(id)aString replacementRange: (NSRange)replacementRange
|
||||
{
|
||||
const char *str;
|
||||
NSString *string;
|
||||
|
||||
GDK_NOTE (EVENTS, g_message ("insertText"));
|
||||
|
||||
if ([self hasMarkedText])
|
||||
[self unmarkText];
|
||||
|
||||
if ([aString isKindOfClass: [NSAttributedString class]])
|
||||
string = [aString string];
|
||||
else
|
||||
string = aString;
|
||||
|
||||
NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
|
||||
NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
||||
if ([string rangeOfCharacterFromSet:ctrlChars].length &&
|
||||
[string rangeOfCharacterFromSet:wsnlChars].length == 0)
|
||||
{
|
||||
/* discard invalid text input with Chinese input methods */
|
||||
str = "";
|
||||
[self unmarkText];
|
||||
[[NSTextInputContext currentInputContext] discardMarkedText];
|
||||
}
|
||||
else
|
||||
{
|
||||
str = [string UTF8String];
|
||||
}
|
||||
|
||||
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_INSERT_TEXT, g_strdup (str), g_free);
|
||||
GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
|
||||
TIC_INSERT_TEXT, [self gdkSurface], self,
|
||||
str ? str : "(empty)"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
|
||||
|
||||
/* handle text input changes by mouse events */
|
||||
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
|
||||
_gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
|
||||
}
|
||||
|
||||
-(void)deleteBackward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteBackward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)deleteForward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteForward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)deleteToBeginningOfLine:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteToBeginningOfLine"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)deleteToEndOfLine:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteToEndOfLine"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)deleteWordBackward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteWordBackward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)deleteWordForward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("deleteWordForward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)insertBacktab:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("insertBacktab"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)insertNewline:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("insertNewline"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)insertTab:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("insertTab"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveBackward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveBackward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveBackwardAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveBackwardAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveDown:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveDown"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveDownAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveDownAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveForward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveForward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveForwardAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveForwardAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveLeft:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveLeft"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveLeftAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveLeftAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveRight:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveRight"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveRightAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveRightAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToBeginningOfDocument:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocument"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToBeginningOfDocumentAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocumentAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToBeginningOfLine:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLine"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToBeginningOfLineAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLineAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToEndOfDocument:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocument"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToEndOfDocumentAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocumentAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToEndOfLine:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToEndOfLine"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveToEndOfLineAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveToEndOfLineAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveUp:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveUp"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveUpAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveUpAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordBackward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordBackward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordBackwardAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordBackwardAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordForward:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordForward"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordForwardAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordForwardAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordLeft:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordLeft"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordLeftAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordLeftAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordRight:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordRight"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)moveWordRightAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("moveWordRightAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)pageDown:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("pageDown"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)pageDownAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("pageDownAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)pageUp:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("pageUp"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)pageUpAndModifySelection:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("pageUpAndModifySelection"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)selectAll:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("selectAll"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)selectLine:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("selectLine"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)selectWord:(id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("selectWord"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
-(void)noop: (id)sender
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_message ("noop"));
|
||||
|
||||
g_object_set_data (G_OBJECT ([self gdkSurface]),
|
||||
GIC_FILTER_KEY,
|
||||
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,6 +1,7 @@
|
||||
/* GdkQuartzView.h
|
||||
/* GdkMacosBaseView.h
|
||||
*
|
||||
* Copyright (C) 2005 Imendio AB
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2005-2007 Imendio AB
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -14,36 +15,32 @@
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#include "gdk/gdk.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/* Text Input Client */
|
||||
#define TIC_MARKED_TEXT "tic-marked-text"
|
||||
#define TIC_SELECTED_POS "tic-selected-pos"
|
||||
#define TIC_SELECTED_LEN "tic-selected-len"
|
||||
#define TIC_INSERT_TEXT "tic-insert-text"
|
||||
#define TIC_IN_KEY_DOWN "tic-in-key-down"
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
/* GtkIMContext */
|
||||
#define GIC_CURSOR_RECT "gic-cursor-rect"
|
||||
#define GIC_FILTER_KEY "gic-filter-key"
|
||||
#define GIC_FILTER_PASSTHRU 0
|
||||
#define GIC_FILTER_FILTERED 1
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacossurface.h"
|
||||
|
||||
@interface GdkQuartzView : NSView <NSTextInputClient>
|
||||
#define GDK_IS_MACOS_BASE_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosBaseView class]])
|
||||
|
||||
@interface GdkMacosBaseView : NSView <NSTextInputClient>
|
||||
{
|
||||
GdkSurface *gdk_surface;
|
||||
NSTrackingRectTag trackingRect;
|
||||
NSTrackingArea *trackingArea;
|
||||
BOOL needsInvalidateShadow;
|
||||
NSRange markedRange;
|
||||
NSRange selectedRange;
|
||||
}
|
||||
|
||||
- (void)setGdkSurface: (GdkSurface *)window;
|
||||
- (GdkSurface *)gdkSurface;
|
||||
- (NSTrackingRectTag)trackingRect;
|
||||
- (void)setNeedsInvalidateShadow: (BOOL)invalidate;
|
||||
-(GdkMacosSurface *)gdkSurface;
|
||||
-(GdkMacosDisplay *)gdkDisplay;
|
||||
-(void)setNeedsInvalidateShadow: (BOOL)invalidate;
|
||||
-(NSTrackingArea *)trackingArea;
|
||||
-(void)setOpaqueRegion:(cairo_region_t *)region;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,171 @@
|
||||
/* GdkMacosCairoSubview.c
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <cairo-quartz.h>
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#import "GdkMacosCairoSubview.h"
|
||||
#import "GdkMacosCairoView.h"
|
||||
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
@implementation GdkMacosCairoSubview
|
||||
|
||||
-(BOOL)isOpaque
|
||||
{
|
||||
return _isOpaque;
|
||||
}
|
||||
|
||||
-(BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(GdkSurface *)gdkSurface
|
||||
{
|
||||
return GDK_SURFACE ([(GdkMacosBaseView *)[self superview] gdkSurface]);
|
||||
}
|
||||
|
||||
-(void)drawRect:(NSRect)rect
|
||||
{
|
||||
CGContextRef cgContext;
|
||||
GdkSurface *gdk_surface;
|
||||
cairo_surface_t *dest;
|
||||
const NSRect *rects = NULL;
|
||||
NSView *root_view;
|
||||
NSInteger n_rects = 0;
|
||||
NSRect abs_bounds;
|
||||
cairo_t *cr;
|
||||
CGSize scale;
|
||||
int scale_factor;
|
||||
|
||||
if (self->cairoSurface == NULL)
|
||||
return;
|
||||
|
||||
/* Acquire everything we need to do translations, drawing, etc */
|
||||
gdk_surface = [self gdkSurface];
|
||||
scale_factor = gdk_surface_get_scale_factor (gdk_surface);
|
||||
root_view = [[self window] contentView];
|
||||
cgContext = [[NSGraphicsContext currentContext] CGContext];
|
||||
abs_bounds = [self convertRect:[self bounds] toView:root_view];
|
||||
|
||||
CGContextSaveGState (cgContext);
|
||||
|
||||
/* Translate scaling to remove HiDPI scaling from CGContext as
|
||||
* cairo will be doing that for us already.
|
||||
*/
|
||||
scale = CGSizeMake (1.0, 1.0);
|
||||
scale = CGContextConvertSizeToDeviceSpace (cgContext, scale);
|
||||
CGContextScaleCTM (cgContext, 1.0 / scale.width, 1.0 / scale.height);
|
||||
|
||||
/* Create the cairo surface to draw to the CGContext and translate
|
||||
* coordinates so we can pretend we are in the same coordinate system
|
||||
* as the GDK surface.
|
||||
*/
|
||||
dest = cairo_quartz_surface_create_for_cg_context (cgContext,
|
||||
gdk_surface->width * scale_factor,
|
||||
gdk_surface->height * scale_factor);
|
||||
cairo_surface_set_device_scale (dest, scale_factor, scale_factor);
|
||||
|
||||
/* Create cairo context and translate things into the origin of
|
||||
* the topmost contentView so that we just draw at 0,0 with a
|
||||
* clip region to paint the surface.
|
||||
*/
|
||||
cr = cairo_create (dest);
|
||||
cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
|
||||
|
||||
/* Clip the cairo context based on the rectangles to be drawn
|
||||
* within the bounding box :rect.
|
||||
*/
|
||||
[self getRectsBeingDrawn:&rects count:&n_rects];
|
||||
for (NSInteger i = 0; i < n_rects; i++)
|
||||
{
|
||||
NSRect area = [self convertRect:rects[i] toView:root_view];
|
||||
cairo_rectangle (cr,
|
||||
area.origin.x, area.origin.y,
|
||||
area.size.width, area.size.height);
|
||||
}
|
||||
cairo_clip (cr);
|
||||
|
||||
/* Now paint the surface (without blending) as we do not need
|
||||
* any compositing here. The transparent regions (like shadows)
|
||||
* are already on non-opaque layers.
|
||||
*/
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface (cr, self->cairoSurface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
/* Cleanup state, flush the surface to the backing layer, and
|
||||
* restore GState for future use.
|
||||
*/
|
||||
cairo_destroy (cr);
|
||||
cairo_surface_flush (dest);
|
||||
cairo_surface_destroy (dest);
|
||||
CGContextRestoreGState (cgContext);
|
||||
}
|
||||
|
||||
-(void)setCairoSurface:(cairo_surface_t *)surface
|
||||
withDamage:(cairo_region_t *)region
|
||||
{
|
||||
if (surface != self->cairoSurface)
|
||||
{
|
||||
g_clear_pointer (&self->cairoSurface, cairo_surface_destroy);
|
||||
if (surface != NULL)
|
||||
self->cairoSurface = cairo_surface_reference (surface);
|
||||
}
|
||||
|
||||
if (region != NULL)
|
||||
{
|
||||
NSView *root_view = [[self window] contentView];
|
||||
NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
|
||||
guint n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
NSRect nsrect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
|
||||
|
||||
if (NSIntersectsRect (abs_bounds, nsrect))
|
||||
{
|
||||
nsrect.origin.x -= abs_bounds.origin.x;
|
||||
nsrect.origin.y -= abs_bounds.origin.y;
|
||||
[self setNeedsDisplayInRect:nsrect];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (id view in [self subviews])
|
||||
[(GdkMacosCairoSubview *)view setCairoSurface:surface
|
||||
withDamage:region];
|
||||
}
|
||||
|
||||
-(void)setOpaque:(BOOL)opaque
|
||||
{
|
||||
self->_isOpaque = opaque;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,35 @@
|
||||
/* GdkMacosCairoSubview.h
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
|
||||
|
||||
@interface GdkMacosCairoSubview : NSView
|
||||
{
|
||||
BOOL _isOpaque;
|
||||
cairo_surface_t *cairoSurface;
|
||||
}
|
||||
|
||||
-(void)setOpaque:(BOOL)opaque;
|
||||
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
|
||||
withDamage:(cairo_region_t *)region;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,170 @@
|
||||
/* GdkMacosCairoView.c
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2005-2007 Imendio AB
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <cairo-quartz.h>
|
||||
|
||||
#include "gdkinternals.h"
|
||||
|
||||
#import "GdkMacosCairoView.h"
|
||||
#import "GdkMacosCairoSubview.h"
|
||||
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
@implementation GdkMacosCairoView
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_clear_pointer (&self->opaque, g_ptr_array_unref);
|
||||
self->transparent = NULL;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(BOOL)isOpaque
|
||||
{
|
||||
if ([self window])
|
||||
return [[self window] isOpaque];
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
|
||||
withDamage:(cairo_region_t *)cairoRegion
|
||||
{
|
||||
for (id view in [self subviews])
|
||||
[(GdkMacosCairoSubview *)view setCairoSurface:cairoSurface
|
||||
withDamage:cairoRegion];
|
||||
}
|
||||
|
||||
-(void)removeOpaqueChildren
|
||||
{
|
||||
[[self->transparent subviews]
|
||||
makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
|
||||
if (self->opaque->len)
|
||||
g_ptr_array_remove_range (self->opaque, 0, self->opaque->len);
|
||||
}
|
||||
|
||||
-(void)setOpaqueRegion:(cairo_region_t *)region
|
||||
{
|
||||
NSRect abs_bounds;
|
||||
guint n_rects;
|
||||
|
||||
if (region == NULL)
|
||||
return;
|
||||
|
||||
abs_bounds = [self convertRect:[self bounds] toView:nil];
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
/* The common case (at least for opaque windows and CSD) is that we will
|
||||
* have either one or two opaque rectangles. If we detect that the same
|
||||
* number of them are available as the previous, we can just resize the
|
||||
* previous ones to avoid adding/removing views at a fast rate while
|
||||
* resizing.
|
||||
*/
|
||||
if (n_rects == self->opaque->len)
|
||||
{
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
GdkMacosCairoSubview *child;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
child = g_ptr_array_index (self->opaque, i);
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
[child setFrame:NSMakeRect (rect.x - abs_bounds.origin.x,
|
||||
rect.y - abs_bounds.origin.y,
|
||||
rect.width,
|
||||
rect.height)];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
[self removeOpaqueChildren];
|
||||
for (guint i = 0; i < n_rects; i++)
|
||||
{
|
||||
GdkMacosCairoSubview *child;
|
||||
cairo_rectangle_int_t rect;
|
||||
NSRect nsrect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
nsrect = NSMakeRect (rect.x - abs_bounds.origin.x,
|
||||
rect.y - abs_bounds.origin.y,
|
||||
rect.width,
|
||||
rect.height);
|
||||
|
||||
child = [[GdkMacosCairoSubview alloc] initWithFrame:nsrect];
|
||||
[child setOpaque:YES];
|
||||
[child setWantsLayer:YES];
|
||||
[self->transparent addSubview:child];
|
||||
g_ptr_array_add (self->opaque, child);
|
||||
}
|
||||
}
|
||||
|
||||
-(NSView *)initWithFrame:(NSRect)frame
|
||||
{
|
||||
if ((self = [super initWithFrame:frame]))
|
||||
{
|
||||
/* An array to track all the opaque children placed into
|
||||
* the child self->transparent. This allows us to reuse them
|
||||
* when we receive a new opaque area instead of discarding
|
||||
* them on each draw.
|
||||
*/
|
||||
self->opaque = g_ptr_array_new ();
|
||||
|
||||
/* Setup our primary subview which will render all content that is not
|
||||
* within an opaque region (such as shadows for CSD windows). For opaque
|
||||
* windows, this will all be obscurred by other views, so it doesn't
|
||||
* matter much to have it here.
|
||||
*/
|
||||
self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
|
||||
[self addSubview:self->transparent];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)setFrame:(NSRect)rect
|
||||
{
|
||||
[super setFrame:rect];
|
||||
[self->transparent setFrame:NSMakeRect (0, 0, rect.size.width, rect.size.height)];
|
||||
}
|
||||
|
||||
-(BOOL)acceptsFirstMouse
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)mouseDownCanMoveWindow
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,7 +1,7 @@
|
||||
/* gdkdevicemanager-quartz.h
|
||||
/* GdkMacosCairoView.h
|
||||
*
|
||||
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
|
||||
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2005-2007 Imendio AB
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -15,28 +15,23 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_QUARTZ_DEVICE_MANAGER_CORE__
|
||||
#define __GDK_QUARTZ_DEVICE_MANAGER_CORE__
|
||||
#include <cairo.h>
|
||||
|
||||
#include <gdkdevicemanagerprivate.h>
|
||||
#include "gdkquartzdevicemanager-core.h"
|
||||
#import "GdkMacosBaseView.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GDK_IS_MACOS_CAIRO_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoView class]])
|
||||
|
||||
struct _GdkQuartzDeviceManagerCore
|
||||
@interface GdkMacosCairoView : GdkMacosBaseView
|
||||
{
|
||||
GObject parent_object;
|
||||
GdkDevice *core_pointer;
|
||||
GdkDevice *core_keyboard;
|
||||
};
|
||||
NSView *transparent;
|
||||
GPtrArray *opaque;
|
||||
}
|
||||
|
||||
struct _GdkQuartzDeviceManagerCoreClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
|
||||
withDamage:(cairo_region_t *)region;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_QUARTZ_DEVICE_MANAGER__ */
|
||||
@end
|
||||
@@ -0,0 +1,157 @@
|
||||
/* GdkMacosGLLayer.c
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/* Based on Chromium image_transport_surface_calayer_mac.mm
|
||||
* See the BSD-style license above.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
#import "GdkMacosGLLayer.h"
|
||||
|
||||
@implementation GdkMacosGLLayer
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
-(id)initWithContext:(NSOpenGLContext *)shared
|
||||
{
|
||||
[super init];
|
||||
_shared = [shared retain];
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[_shared release];
|
||||
_shared = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)setContentsRect:(NSRect)bounds
|
||||
{
|
||||
_pixelSize = bounds.size;
|
||||
[super setContentsRect:bounds];
|
||||
}
|
||||
|
||||
-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
|
||||
{
|
||||
return CGLRetainPixelFormat ([[_shared pixelFormat] CGLPixelFormatObj]);
|
||||
}
|
||||
|
||||
-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
|
||||
{
|
||||
CGLContextObj context = NULL;
|
||||
CGLCreateContext (pixelFormat, [_shared CGLContextObj], &context);
|
||||
return context;
|
||||
}
|
||||
|
||||
-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext
|
||||
pixelFormat:(CGLPixelFormatObj)pixelFormat
|
||||
forLayerTime:(CFTimeInterval)timeInterval
|
||||
displayTime:(const CVTimeStamp*)timeStamp
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)drawInCGLContext:(CGLContextObj)glContext
|
||||
pixelFormat:(CGLPixelFormatObj)pixelFormat
|
||||
forLayerTime:(CFTimeInterval)timeInterval
|
||||
displayTime:(const CVTimeStamp*)timeStamp
|
||||
{
|
||||
if (_texture == 0)
|
||||
return;
|
||||
|
||||
glClearColor (1, 0, 1, 1);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
GLint viewport[4] = {0, 0, 0, 0};
|
||||
glGetIntegerv (GL_VIEWPORT, viewport);
|
||||
NSSize viewportSize = NSMakeSize (viewport[2], viewport[3]);
|
||||
|
||||
/* Set the coordinate system to be one-to-one with pixels. */
|
||||
glMatrixMode (GL_PROJECTION);
|
||||
glLoadIdentity ();
|
||||
glOrtho (0, viewportSize.width, 0, viewportSize.height, -1, 1);
|
||||
glMatrixMode (GL_MODELVIEW);
|
||||
glLoadIdentity ();
|
||||
|
||||
/* Draw a fullscreen quad. */
|
||||
glColor4f (1, 1, 1, 1);
|
||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture);
|
||||
glBegin (GL_QUADS);
|
||||
{
|
||||
glTexCoord2f (0, 0);
|
||||
glVertex2f (0, 0);
|
||||
glTexCoord2f (0, _pixelSize.height);
|
||||
glVertex2f (0, _pixelSize.height);
|
||||
glTexCoord2f (_pixelSize.width, _pixelSize.height);
|
||||
glVertex2f (_pixelSize.width, _pixelSize.height);
|
||||
glTexCoord2f (_pixelSize.width, 0);
|
||||
glVertex2f (_pixelSize.width, 0);
|
||||
}
|
||||
glEnd ();
|
||||
glBindTexture (0, _texture);
|
||||
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
||||
[super drawInCGLContext:glContext
|
||||
pixelFormat:pixelFormat
|
||||
forLayerTime:timeInterval
|
||||
displayTime:timeStamp];
|
||||
}
|
||||
|
||||
-(void)setTexture:(GLuint)texture
|
||||
{
|
||||
_texture = texture;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
|
||||
@end
|
||||
@@ -1,6 +1,6 @@
|
||||
/* gdkscreen-quartz.h
|
||||
/* GdkMacosGLLayer.h
|
||||
*
|
||||
* Copyright (C) 2009,2010 Kristian Rietveld <kris@gtk.org>
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -14,36 +14,27 @@
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_QUARTZ_SCREEN__
|
||||
#define __GDK_QUARTZ_SCREEN__
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
#define GDK_IS_MACOS_GL_LAYER(obj) ((obj) && [obj isKindOfClass:[GdkMacosGLLayer class]])
|
||||
|
||||
struct _GdkQuartzScreen
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
@interface GdkMacosGLLayer : CAOpenGLLayer
|
||||
{
|
||||
GObject parent_instance;
|
||||
NSOpenGLContext *_shared;
|
||||
GLuint _texture;
|
||||
NSSize _pixelSize;
|
||||
}
|
||||
|
||||
GdkDisplay *display;
|
||||
-(id)initWithContext:(NSOpenGLContext *)shared;
|
||||
-(void)setTexture:(GLuint)texture;
|
||||
|
||||
/* Origin of "root window" in Cocoa coordinates */
|
||||
gint min_x;
|
||||
gint min_y;
|
||||
@end
|
||||
|
||||
gint width;
|
||||
gint height;
|
||||
|
||||
guint screen_changed_id;
|
||||
|
||||
guint emit_monitors_changed : 1;
|
||||
};
|
||||
|
||||
struct _GdkQuartzScreenClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_QUARTZ_SCREEN__ */
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
@@ -0,0 +1,732 @@
|
||||
/* GdkMacosWindow.m
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2005-2007 Imendio AB
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#import "GdkMacosBaseView.h"
|
||||
#import "GdkMacosCairoView.h"
|
||||
#import "GdkMacosWindow.h"
|
||||
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
#include "gdkmacospopupsurface-private.h"
|
||||
#include "gdkmacostoplevelsurface-private.h"
|
||||
|
||||
#include "gdkmonitorprivate.h"
|
||||
#include "gdksurfaceprivate.h"
|
||||
|
||||
@implementation GdkMacosWindow
|
||||
|
||||
-(BOOL)windowShouldClose:(id)sender
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkEvent *event;
|
||||
GList *node;
|
||||
|
||||
display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||
event = gdk_delete_event_new (GDK_SURFACE (gdk_surface));
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
_gdk_windowing_got_event (display, node, event,
|
||||
_gdk_display_get_next_serial (display));
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)windowWillMiniaturize:(NSNotification *)aNotification
|
||||
{
|
||||
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
|
||||
_gdk_macos_toplevel_surface_detach_from_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
|
||||
else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
|
||||
_gdk_macos_popup_surface_detach_from_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
|
||||
}
|
||||
|
||||
-(void)windowDidMiniaturize:(NSNotification *)aNotification
|
||||
{
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MINIMIZED);
|
||||
}
|
||||
|
||||
-(void)windowDidDeminiaturize:(NSNotification *)aNotification
|
||||
{
|
||||
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
|
||||
_gdk_macos_toplevel_surface_attach_to_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
|
||||
else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
|
||||
_gdk_macos_popup_surface_attach_to_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
|
||||
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MINIMIZED, 0);
|
||||
}
|
||||
|
||||
-(void)windowDidBecomeKey:(NSNotification *)aNotification
|
||||
{
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_FOCUSED);
|
||||
_gdk_macos_display_surface_became_key ([self gdkDisplay], gdk_surface);
|
||||
}
|
||||
|
||||
-(void)windowDidResignKey:(NSNotification *)aNotification
|
||||
{
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_FOCUSED, 0);
|
||||
_gdk_macos_display_surface_resigned_key ([self gdkDisplay], gdk_surface);
|
||||
}
|
||||
|
||||
-(void)windowDidBecomeMain:(NSNotification *)aNotification
|
||||
{
|
||||
if (![self isVisible])
|
||||
{
|
||||
/* Note: This is a hack needed because for unknown reasons, hidden
|
||||
* windows get shown when clicking the dock icon when the application
|
||||
* is not already active.
|
||||
*/
|
||||
[self orderOut:nil];
|
||||
return;
|
||||
}
|
||||
|
||||
_gdk_macos_display_surface_became_main ([self gdkDisplay], gdk_surface);
|
||||
}
|
||||
|
||||
-(void)windowDidResignMain:(NSNotification *)aNotification
|
||||
{
|
||||
_gdk_macos_display_surface_resigned_main ([self gdkDisplay], gdk_surface);
|
||||
}
|
||||
|
||||
/* Used in combination with NSLeftMouseUp in sendEvent to keep track
|
||||
* of when the window is being moved with the mouse.
|
||||
*/
|
||||
-(void)windowWillMove:(NSNotification *)aNotification
|
||||
{
|
||||
inMove = YES;
|
||||
}
|
||||
|
||||
-(void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
NSEventType event_type = [event type];
|
||||
|
||||
switch ((int)event_type)
|
||||
{
|
||||
case NSEventTypeLeftMouseUp: {
|
||||
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
|
||||
double time = ((double)[event timestamp]) * 1000.0;
|
||||
|
||||
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
|
||||
|
||||
inManualMove = NO;
|
||||
inManualResize = NO;
|
||||
inMove = NO;
|
||||
|
||||
/* We need to deliver the event to the proper drag gestures or we
|
||||
* will leave the window in inconsistent state that requires clicking
|
||||
* in the window to cancel the gesture.
|
||||
*
|
||||
* TODO: Can we improve grab breaking to fix this?
|
||||
*/
|
||||
_gdk_macos_display_send_button_event ([self gdkDisplay], event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case NSEventTypeLeftMouseDragged:
|
||||
if ([self trackManualMove] || [self trackManualResize])
|
||||
return;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
[super sendEvent:event];
|
||||
}
|
||||
|
||||
-(BOOL)isInMove
|
||||
{
|
||||
return inMove;
|
||||
}
|
||||
|
||||
-(void)checkSendEnterNotify
|
||||
{
|
||||
/* When a new window has been created, and the mouse is in the window
|
||||
* area, we will not receive an NSEventTypeMouseEntered event.
|
||||
* Therefore, we synthesize an enter notify event manually.
|
||||
*/
|
||||
if (!initialPositionKnown)
|
||||
{
|
||||
initialPositionKnown = YES;
|
||||
|
||||
if (NSPointInRect ([NSEvent mouseLocation], [self frame]))
|
||||
{
|
||||
GdkMacosBaseView *view = (GdkMacosBaseView *)[self contentView];
|
||||
NSEvent *event;
|
||||
|
||||
event = [NSEvent enterExitEventWithType: NSEventTypeMouseEntered
|
||||
location: [self mouseLocationOutsideOfEventStream]
|
||||
modifierFlags: 0
|
||||
timestamp: [[NSApp currentEvent] timestamp]
|
||||
windowNumber: [self windowNumber]
|
||||
context: NULL
|
||||
eventNumber: 0
|
||||
trackingNumber: (NSInteger)[view trackingArea]
|
||||
userData: nil];
|
||||
|
||||
[NSApp postEvent:event atStart:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)windowDidUnmaximize
|
||||
{
|
||||
NSWindowStyleMask style_mask = [self styleMask];
|
||||
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MAXIMIZED, 0);
|
||||
|
||||
/* If we are using CSD, then we transitioned to an opaque
|
||||
* window while we were maximized. Now we need to drop that
|
||||
* as we are leaving maximized state.
|
||||
*/
|
||||
if ((style_mask & NSWindowStyleMaskTitled) == 0 && [self isOpaque])
|
||||
[self setOpaque:NO];
|
||||
}
|
||||
|
||||
-(void)windowDidMove:(NSNotification *)aNotification
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (gdk_surface);
|
||||
gboolean maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
|
||||
|
||||
/* In case the window is changed when maximized remove the maximized state */
|
||||
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
|
||||
[self windowDidUnmaximize];
|
||||
|
||||
_gdk_macos_surface_update_position (gdk_surface);
|
||||
_gdk_macos_surface_reposition_children (gdk_surface);
|
||||
|
||||
[self checkSendEnterNotify];
|
||||
}
|
||||
|
||||
-(void)windowDidResize:(NSNotification *)aNotification
|
||||
{
|
||||
NSRect content_rect;
|
||||
GdkSurface *surface;
|
||||
GdkDisplay *display;
|
||||
GdkEvent *event;
|
||||
gboolean maximized;
|
||||
GList *node;
|
||||
|
||||
surface = GDK_SURFACE (gdk_surface);
|
||||
display = gdk_surface_get_display (surface);
|
||||
|
||||
content_rect = [self contentRectForFrameRect:[self frame]];
|
||||
maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
|
||||
|
||||
/* see same in windowDidMove */
|
||||
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
|
||||
[self windowDidUnmaximize];
|
||||
|
||||
surface->width = content_rect.size.width;
|
||||
surface->height = content_rect.size.height;
|
||||
|
||||
/* Certain resize operations (e.g. going fullscreen), also move the
|
||||
* origin of the window.
|
||||
*/
|
||||
_gdk_macos_surface_update_position (GDK_MACOS_SURFACE (surface));
|
||||
|
||||
[[self contentView] setFrame:NSMakeRect (0, 0, surface->width, surface->height)];
|
||||
|
||||
_gdk_surface_update_size (surface);
|
||||
|
||||
/* Synthesize a configure event */
|
||||
event = gdk_configure_event_new (surface,
|
||||
content_rect.size.width,
|
||||
content_rect.size.height);
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
_gdk_windowing_got_event (display, node, event,
|
||||
_gdk_display_get_next_serial (display));
|
||||
|
||||
_gdk_macos_surface_reposition_children (gdk_surface);
|
||||
|
||||
[self checkSendEnterNotify];
|
||||
}
|
||||
|
||||
-(id)initWithContentRect:(NSRect)contentRect
|
||||
styleMask:(NSWindowStyleMask)styleMask
|
||||
backing:(NSBackingStoreType)backingType
|
||||
defer:(BOOL)flag
|
||||
screen:(NSScreen *)screen
|
||||
{
|
||||
GdkMacosCairoView *view;
|
||||
|
||||
self = [super initWithContentRect:contentRect
|
||||
styleMask:styleMask
|
||||
backing:backingType
|
||||
defer:flag
|
||||
screen:screen];
|
||||
|
||||
[self setAcceptsMouseMovedEvents:YES];
|
||||
[self setDelegate:(id<NSWindowDelegate>)self];
|
||||
[self setReleasedWhenClosed:YES];
|
||||
|
||||
view = [[GdkMacosCairoView alloc] initWithFrame:contentRect];
|
||||
[self setContentView:view];
|
||||
[view release];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(BOOL)canBecomeMainWindow
|
||||
{
|
||||
return GDK_IS_TOPLEVEL (gdk_surface);
|
||||
}
|
||||
|
||||
-(BOOL)canBecomeKeyWindow
|
||||
{
|
||||
return GDK_IS_TOPLEVEL (gdk_surface);
|
||||
}
|
||||
|
||||
-(void)showAndMakeKey:(BOOL)makeKey
|
||||
{
|
||||
inShowOrHide = YES;
|
||||
|
||||
if (makeKey && [self canBecomeKeyWindow])
|
||||
[self makeKeyAndOrderFront:nil];
|
||||
else
|
||||
[self orderFront:nil];
|
||||
|
||||
inShowOrHide = NO;
|
||||
|
||||
[self checkSendEnterNotify];
|
||||
}
|
||||
|
||||
-(void)hide
|
||||
{
|
||||
inShowOrHide = YES;
|
||||
[self orderOut:nil];
|
||||
inShowOrHide = NO;
|
||||
|
||||
initialPositionKnown = NO;
|
||||
}
|
||||
|
||||
-(BOOL)trackManualMove
|
||||
{
|
||||
NSRect windowFrame;
|
||||
NSPoint currentLocation;
|
||||
GdkMonitor *monitor;
|
||||
GdkRectangle geometry;
|
||||
GdkRectangle workarea;
|
||||
int shadow_top = 0;
|
||||
int shadow_left = 0;
|
||||
int shadow_right = 0;
|
||||
int shadow_bottom = 0;
|
||||
GdkRectangle window_gdk;
|
||||
GdkPoint pointer_position;
|
||||
GdkPoint new_origin;
|
||||
|
||||
if (!inManualMove)
|
||||
return NO;
|
||||
|
||||
/* Get our shadow so we can adjust the window position sans-shadow */
|
||||
_gdk_macos_surface_get_shadow (gdk_surface,
|
||||
&shadow_top,
|
||||
&shadow_right,
|
||||
&shadow_bottom,
|
||||
&shadow_left);
|
||||
|
||||
windowFrame = [self frame];
|
||||
currentLocation = [NSEvent mouseLocation];
|
||||
|
||||
/* Update the snapping geometry to match the current monitor */
|
||||
monitor = _gdk_macos_display_get_monitor_at_display_coords ([self gdkDisplay],
|
||||
currentLocation.x,
|
||||
currentLocation.y);
|
||||
gdk_monitor_get_geometry (monitor, &geometry);
|
||||
gdk_monitor_get_workarea (monitor, &workarea);
|
||||
_edge_snapping_set_monitor (&self->snapping, &geometry, &workarea);
|
||||
|
||||
/* Convert origins to GDK coordinates */
|
||||
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
||||
currentLocation.x,
|
||||
currentLocation.y,
|
||||
&pointer_position.x,
|
||||
&pointer_position.y);
|
||||
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
||||
windowFrame.origin.x,
|
||||
windowFrame.origin.y + windowFrame.size.height,
|
||||
&window_gdk.x,
|
||||
&window_gdk.y);
|
||||
window_gdk.width = windowFrame.size.width;
|
||||
window_gdk.height = windowFrame.size.height;
|
||||
|
||||
/* Subtract our shadowin from the window */
|
||||
window_gdk.x += shadow_left;
|
||||
window_gdk.y += shadow_top;
|
||||
window_gdk.width = window_gdk.width - shadow_left - shadow_right;
|
||||
window_gdk.height = window_gdk.height - shadow_top - shadow_bottom;
|
||||
|
||||
/* Now place things on the monitor */
|
||||
_edge_snapping_motion (&self->snapping, &pointer_position, &window_gdk);
|
||||
|
||||
/* And add our shadow back to the frame */
|
||||
window_gdk.x -= shadow_left;
|
||||
window_gdk.y -= shadow_top;
|
||||
window_gdk.width += shadow_left + shadow_right;
|
||||
window_gdk.height += shadow_top + shadow_bottom;
|
||||
|
||||
/* Convert to quartz coordiantes */
|
||||
_gdk_macos_display_to_display_coords ([self gdkDisplay],
|
||||
window_gdk.x,
|
||||
window_gdk.y + window_gdk.height,
|
||||
&new_origin.x, &new_origin.y);
|
||||
windowFrame.origin.x = new_origin.x;
|
||||
windowFrame.origin.y = new_origin.y;
|
||||
|
||||
/* And now apply the frame to the window */
|
||||
[self setFrameOrigin:NSMakePoint(new_origin.x, new_origin.y)];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler
|
||||
* above will see the event or if it will be subjected to standard processing
|
||||
* by GDK.
|
||||
*/
|
||||
-(BOOL)isInManualResizeOrMove
|
||||
{
|
||||
return inManualResize || inManualMove;
|
||||
}
|
||||
|
||||
-(void)beginManualMove
|
||||
{
|
||||
NSPoint initialMoveLocation;
|
||||
GdkPoint point;
|
||||
GdkMonitor *monitor;
|
||||
GdkRectangle geometry;
|
||||
GdkRectangle area;
|
||||
GdkRectangle workarea;
|
||||
|
||||
if (inMove || inManualMove || inManualResize)
|
||||
return;
|
||||
|
||||
inManualMove = YES;
|
||||
|
||||
monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
|
||||
gdk_monitor_get_geometry (monitor, &geometry);
|
||||
gdk_monitor_get_workarea (monitor, &workarea);
|
||||
|
||||
initialMoveLocation = [NSEvent mouseLocation];
|
||||
|
||||
_gdk_macos_display_from_display_coords ([self gdkDisplay],
|
||||
initialMoveLocation.x,
|
||||
initialMoveLocation.y,
|
||||
&point.x,
|
||||
&point.y);
|
||||
|
||||
area.x = gdk_surface->root_x;
|
||||
area.y = gdk_surface->root_y;
|
||||
area.width = GDK_SURFACE (gdk_surface)->width;
|
||||
area.height = GDK_SURFACE (gdk_surface)->height;
|
||||
|
||||
_edge_snapping_init (&self->snapping,
|
||||
&geometry,
|
||||
&workarea,
|
||||
&point,
|
||||
&area);
|
||||
}
|
||||
|
||||
-(BOOL)trackManualResize
|
||||
{
|
||||
NSPoint mouse_location;
|
||||
NSRect new_frame;
|
||||
float mdx, mdy, dw, dh, dx, dy;
|
||||
NSSize min_size;
|
||||
|
||||
if (!inManualResize || inTrackManualResize)
|
||||
return NO;
|
||||
|
||||
inTrackManualResize = YES;
|
||||
|
||||
mouse_location = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
|
||||
mdx = initialResizeLocation.x - mouse_location.x;
|
||||
mdy = initialResizeLocation.y - mouse_location.y;
|
||||
|
||||
/* Set how a mouse location delta translates to changes in width,
|
||||
* height and position.
|
||||
*/
|
||||
dw = dh = dx = dy = 0.0;
|
||||
if (resizeEdge == GDK_SURFACE_EDGE_EAST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
|
||||
{
|
||||
dw = -1.0;
|
||||
}
|
||||
if (resizeEdge == GDK_SURFACE_EDGE_NORTH ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST)
|
||||
{
|
||||
dh = -1.0;
|
||||
}
|
||||
if (resizeEdge == GDK_SURFACE_EDGE_SOUTH ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
|
||||
{
|
||||
dh = 1.0;
|
||||
dy = -1.0;
|
||||
}
|
||||
if (resizeEdge == GDK_SURFACE_EDGE_WEST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
|
||||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST)
|
||||
{
|
||||
dw = 1.0;
|
||||
dx = -1.0;
|
||||
}
|
||||
|
||||
/* Apply changes to the frame captured when we started resizing */
|
||||
new_frame = initialResizeFrame;
|
||||
new_frame.origin.x += mdx * dx;
|
||||
new_frame.origin.y += mdy * dy;
|
||||
new_frame.size.width += mdx * dw;
|
||||
new_frame.size.height += mdy * dh;
|
||||
|
||||
/* In case the resulting window would be too small reduce the
|
||||
* change to both size and position.
|
||||
*/
|
||||
min_size = [self contentMinSize];
|
||||
|
||||
if (new_frame.size.width < min_size.width)
|
||||
{
|
||||
if (dx)
|
||||
new_frame.origin.x -= min_size.width - new_frame.size.width;
|
||||
new_frame.size.width = min_size.width;
|
||||
}
|
||||
|
||||
if (new_frame.size.height < min_size.height)
|
||||
{
|
||||
if (dy)
|
||||
new_frame.origin.y -= min_size.height - new_frame.size.height;
|
||||
new_frame.size.height = min_size.height;
|
||||
}
|
||||
|
||||
/* We could also apply aspect ratio:
|
||||
new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
|
||||
*/
|
||||
|
||||
[self setFrame:new_frame display:YES];
|
||||
|
||||
/* Let the resizing be handled by GTK+. */
|
||||
if (g_main_context_pending (NULL))
|
||||
g_main_context_iteration (NULL, FALSE);
|
||||
|
||||
inTrackManualResize = NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)beginManualResize:(GdkSurfaceEdge)edge
|
||||
{
|
||||
if (inMove || inManualMove || inManualResize)
|
||||
return;
|
||||
|
||||
inManualResize = YES;
|
||||
resizeEdge = edge;
|
||||
|
||||
initialResizeFrame = [self frame];
|
||||
initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
|
||||
}
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
-(void)draggingEnded:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
}
|
||||
|
||||
-(void)draggingExited:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
}
|
||||
|
||||
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)wantsPeriodicDraggingUpdates
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
|
||||
{
|
||||
}
|
||||
|
||||
-(void)setStyleMask:(NSWindowStyleMask)styleMask
|
||||
{
|
||||
gboolean was_fullscreen;
|
||||
gboolean is_fullscreen;
|
||||
gboolean was_opaque;
|
||||
gboolean is_opaque;
|
||||
|
||||
was_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
|
||||
was_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
|
||||
|
||||
[super setStyleMask:styleMask];
|
||||
|
||||
is_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
|
||||
is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
|
||||
|
||||
if (was_fullscreen != is_fullscreen)
|
||||
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
|
||||
|
||||
if (was_opaque != is_opaque)
|
||||
{
|
||||
[self setOpaque:is_opaque];
|
||||
|
||||
if (!is_opaque)
|
||||
[self setBackgroundColor:[NSColor clearColor]];
|
||||
}
|
||||
}
|
||||
|
||||
-(NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
|
||||
{
|
||||
GdkMacosSurface *surface = gdk_surface;
|
||||
NSRect rect;
|
||||
gint shadow_top;
|
||||
|
||||
/* Allow the window to move up "shadow_top" more than normally allowed
|
||||
* by the default impl. This makes it possible to move windows with
|
||||
* client side shadow right up to the screen's menu bar. */
|
||||
_gdk_macos_surface_get_shadow (surface, &shadow_top, NULL, NULL, NULL);
|
||||
rect = [super constrainFrameRect:frameRect toScreen:screen];
|
||||
if (frameRect.origin.y > rect.origin.y)
|
||||
rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + shadow_top);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
|
||||
defaultFrame:(NSRect)newFrame
|
||||
{
|
||||
NSRect screenFrame = [[self screen] visibleFrame];
|
||||
GdkMacosSurface *surface = gdk_surface;
|
||||
gboolean maximized = GDK_SURFACE (surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
|
||||
|
||||
if (!maximized)
|
||||
return screenFrame;
|
||||
else
|
||||
return lastUnmaximizedFrame;
|
||||
}
|
||||
|
||||
-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
|
||||
toFrame:(NSRect)newFrame
|
||||
{
|
||||
GdkMacosSurface *surface = gdk_surface;
|
||||
GdkSurfaceState state = GDK_SURFACE (surface)->state;
|
||||
|
||||
if (state & GDK_SURFACE_STATE_MAXIMIZED)
|
||||
{
|
||||
lastMaximizedFrame = newFrame;
|
||||
[self windowDidUnmaximize];
|
||||
}
|
||||
else
|
||||
{
|
||||
lastUnmaximizedFrame = [nsWindow frame];
|
||||
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MAXIMIZED);
|
||||
}
|
||||
|
||||
inMaximizeTransition = YES;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
|
||||
{
|
||||
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
|
||||
|
||||
inMaximizeTransition = NO;
|
||||
|
||||
/* Even if this is CSD, we want to be opaque while maximized
|
||||
* to speed up compositing by allowing the display server to
|
||||
* avoid costly blends.
|
||||
*/
|
||||
if (maximized)
|
||||
[self setOpaque:YES];
|
||||
}
|
||||
|
||||
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
|
||||
{
|
||||
return [[window screen] frame].size;
|
||||
}
|
||||
|
||||
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
lastUnfullscreenFrame = [self frame];
|
||||
}
|
||||
|
||||
-(void)windowWillExitFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
[self setFrame:lastUnfullscreenFrame display:YES];
|
||||
}
|
||||
|
||||
-(void)windowDidExitFullScreen:(NSNotification *)aNotification
|
||||
{
|
||||
}
|
||||
|
||||
-(void)windowDidChangeScreen:(NSNotification *)aNotification
|
||||
{
|
||||
_gdk_macos_surface_monitor_changed (gdk_surface);
|
||||
}
|
||||
|
||||
-(void)setGdkSurface:(GdkMacosSurface *)surface
|
||||
{
|
||||
self->gdk_surface = surface;
|
||||
}
|
||||
|
||||
-(void)setDecorated:(BOOL)decorated
|
||||
{
|
||||
NSWindowStyleMask style_mask = [self styleMask];
|
||||
|
||||
[self setHasShadow:decorated];
|
||||
|
||||
if (decorated)
|
||||
style_mask |= NSWindowStyleMaskTitled;
|
||||
else
|
||||
style_mask &= ~NSWindowStyleMaskTitled;
|
||||
|
||||
[self setStyleMask:style_mask];
|
||||
}
|
||||
|
||||
-(GdkMacosSurface *)gdkSurface
|
||||
{
|
||||
return self->gdk_surface;
|
||||
}
|
||||
|
||||
-(GdkMacosDisplay *)gdkDisplay
|
||||
{
|
||||
return GDK_MACOS_DISPLAY (GDK_SURFACE (self->gdk_surface)->display);
|
||||
}
|
||||
|
||||
-(BOOL)movableByWindowBackground
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,70 @@
|
||||
/* GdkMacosWindow.h
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
* Copyright © 2005-2007 Imendio AB
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacossurface.h"
|
||||
#include "edgesnapping.h"
|
||||
|
||||
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
|
||||
|
||||
@interface GdkMacosWindow : NSWindow {
|
||||
GdkMacosSurface *gdk_surface;
|
||||
|
||||
BOOL inMove;
|
||||
BOOL inShowOrHide;
|
||||
BOOL initialPositionKnown;
|
||||
|
||||
/* Manually triggered move/resize (not by the window manager) */
|
||||
BOOL inManualMove;
|
||||
BOOL inManualResize;
|
||||
BOOL inTrackManualResize;
|
||||
NSPoint initialResizeLocation;
|
||||
NSRect initialResizeFrame;
|
||||
GdkSurfaceEdge resizeEdge;
|
||||
|
||||
EdgeSnapping snapping;
|
||||
|
||||
NSRect lastUnmaximizedFrame;
|
||||
NSRect lastMaximizedFrame;
|
||||
NSRect lastUnfullscreenFrame;
|
||||
BOOL inMaximizeTransition;
|
||||
}
|
||||
|
||||
-(void)beginManualMove;
|
||||
-(void)beginManualResize:(GdkSurfaceEdge)edge;
|
||||
-(void)hide;
|
||||
-(BOOL)isInManualResizeOrMove;
|
||||
-(BOOL)isInMove;
|
||||
-(GdkMacosDisplay *)gdkDisplay;
|
||||
-(GdkMacosSurface *)gdkSurface;
|
||||
-(void)setGdkSurface:(GdkMacosSurface *)surface;
|
||||
-(void)setStyleMask:(NSWindowStyleMask)styleMask;
|
||||
-(void)showAndMakeKey:(BOOL)makeKey;
|
||||
-(BOOL)trackManualMove;
|
||||
-(BOOL)trackManualResize;
|
||||
-(void)setDecorated:(BOOL)decorated;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,229 @@
|
||||
/* edgesnapping.c
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkrectangle.h"
|
||||
#include "edgesnapping.h"
|
||||
|
||||
#define LEAVE_THRESHOLD 3.0
|
||||
#define ENTER_THRESHOLD 2.0
|
||||
|
||||
#define X1(r) ((r)->x)
|
||||
#define X2(r) ((r)->x + (r)->width)
|
||||
#define Y1(r) ((r)->y)
|
||||
#define Y2(r) ((r)->y + (r)->height)
|
||||
|
||||
void
|
||||
_edge_snapping_init (EdgeSnapping *self,
|
||||
const GdkRectangle *geometry,
|
||||
const GdkRectangle *workarea,
|
||||
const GdkPoint *pointer_position,
|
||||
const GdkRectangle *window)
|
||||
{
|
||||
g_assert (self != NULL);
|
||||
g_assert (geometry != NULL);
|
||||
g_assert (workarea != NULL);
|
||||
g_assert (pointer_position != NULL);
|
||||
|
||||
self->geometry = *geometry;
|
||||
self->workarea = *workarea;
|
||||
self->last_pointer_position = *pointer_position;
|
||||
self->pointer_offset_in_window.x = pointer_position->x - window->x;
|
||||
self->pointer_offset_in_window.y = pointer_position->y - window->y;
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_left (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
if (change < 0)
|
||||
{
|
||||
if (X1 (window) < X1 (geometry) &&
|
||||
X1 (window) > X1 (geometry) - LEAVE_THRESHOLD &&
|
||||
ABS (change) < LEAVE_THRESHOLD)
|
||||
window->x = geometry->x;
|
||||
}
|
||||
|
||||
/* We don't constrain when returning from left edge */
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_right (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
if (change > 0)
|
||||
{
|
||||
if (X2 (window) > X2 (geometry) &&
|
||||
X2 (window) < X2 (geometry) + LEAVE_THRESHOLD &&
|
||||
ABS (change) < LEAVE_THRESHOLD)
|
||||
window->x = X2 (geometry) - window->width;
|
||||
}
|
||||
|
||||
/* We don't constrain when returning from right edge */
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_top (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
if (change < 0)
|
||||
{
|
||||
if (Y1 (window) < Y1 (geometry))
|
||||
window->y = geometry->y;
|
||||
}
|
||||
|
||||
/* We don't constrain when returning from top edge */
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_bottom (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
if (change > 0)
|
||||
{
|
||||
if (Y2 (window) > Y2 (geometry) &&
|
||||
Y2 (window) < Y2 (geometry) + LEAVE_THRESHOLD &&
|
||||
ABS (change) < LEAVE_THRESHOLD)
|
||||
window->y = Y2 (geometry) - window->height;
|
||||
}
|
||||
else if (change < 0)
|
||||
{
|
||||
if (Y2 (window) < Y2 (geometry) &&
|
||||
Y2 (window) > Y2 (geometry) - ENTER_THRESHOLD &&
|
||||
ABS (change) < ENTER_THRESHOLD)
|
||||
window->y = Y2 (geometry) - window->height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_horizontal (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
g_assert (self != NULL);
|
||||
g_assert (geometry != NULL);
|
||||
g_assert (window != NULL);
|
||||
g_assert (change != 0);
|
||||
|
||||
if (ABS (X1 (geometry) - X1 (window)) < ABS (X2 (geometry)) - ABS (X2 (window)))
|
||||
edge_snapping_constrain_left (self, change, geometry, window);
|
||||
else
|
||||
edge_snapping_constrain_right (self, change, geometry, window);
|
||||
}
|
||||
|
||||
static void
|
||||
edge_snapping_constrain_vertical (EdgeSnapping *self,
|
||||
int change,
|
||||
const GdkRectangle *geometry,
|
||||
GdkRectangle *window,
|
||||
gboolean bottom_only)
|
||||
{
|
||||
g_assert (self != NULL);
|
||||
g_assert (geometry != NULL);
|
||||
g_assert (window != NULL);
|
||||
g_assert (change != 0);
|
||||
|
||||
if (!bottom_only &&
|
||||
ABS (Y1 (geometry) - Y1 (window)) < ABS (Y2 (geometry)) - ABS (Y2 (window)))
|
||||
edge_snapping_constrain_top (self, change, geometry, window);
|
||||
else
|
||||
edge_snapping_constrain_bottom (self, change, geometry, window);
|
||||
}
|
||||
|
||||
void
|
||||
_edge_snapping_motion (EdgeSnapping *self,
|
||||
const GdkPoint *pointer_position,
|
||||
GdkRectangle *window)
|
||||
{
|
||||
GdkRectangle new_window;
|
||||
GdkRectangle overlap;
|
||||
GdkPoint change;
|
||||
|
||||
g_assert (self != NULL);
|
||||
g_assert (pointer_position != NULL);
|
||||
|
||||
change.x = pointer_position->x - self->last_pointer_position.x;
|
||||
change.y = pointer_position->y - self->last_pointer_position.y;
|
||||
|
||||
self->last_pointer_position = *pointer_position;
|
||||
|
||||
window->x += change.x;
|
||||
window->y += change.y;
|
||||
|
||||
new_window = *window;
|
||||
|
||||
/* First constrain horizontal */
|
||||
if (change.x)
|
||||
{
|
||||
edge_snapping_constrain_horizontal (self, change.x, &self->workarea, &new_window);
|
||||
if (gdk_rectangle_equal (&new_window, window))
|
||||
edge_snapping_constrain_horizontal (self, change.x, &self->geometry, &new_window);
|
||||
}
|
||||
|
||||
/* Now constrain veritcally */
|
||||
if (change.y)
|
||||
{
|
||||
edge_snapping_constrain_vertical (self, change.y, &self->workarea, &new_window, FALSE);
|
||||
if (new_window.y == window->y)
|
||||
edge_snapping_constrain_vertical (self, change.y, &self->geometry, &new_window, TRUE);
|
||||
}
|
||||
|
||||
/* If the window is not placed in the monitor at all, then we need to
|
||||
* just move the window onto the new screen using the original offset
|
||||
* of the pointer within the window.
|
||||
*/
|
||||
if (!gdk_rectangle_intersect (&self->geometry, &new_window, &overlap))
|
||||
{
|
||||
new_window.x = pointer_position->x - self->pointer_offset_in_window.x;
|
||||
new_window.y = pointer_position->y - self->pointer_offset_in_window.y;
|
||||
}
|
||||
|
||||
/* And finally make sure we aren't underneath the top bar of the
|
||||
* particular monitor.
|
||||
*/
|
||||
if (Y1 (&new_window) < Y1 (&self->workarea))
|
||||
new_window.y = self->workarea.y;
|
||||
|
||||
*window = new_window;
|
||||
}
|
||||
|
||||
void
|
||||
_edge_snapping_set_monitor (EdgeSnapping *self,
|
||||
const GdkRectangle *geometry,
|
||||
const GdkRectangle *workarea)
|
||||
{
|
||||
g_assert (self != NULL);
|
||||
g_assert (geometry != NULL);
|
||||
g_assert (workarea != NULL);
|
||||
|
||||
self->geometry = *geometry;
|
||||
self->workarea = *workarea;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* edgesnapping.h
|
||||
*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __EDGE_SNAPPING_H__
|
||||
#define __EDGE_SNAPPING_H__
|
||||
|
||||
#include "gdktypes.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdkRectangle geometry;
|
||||
GdkRectangle workarea;
|
||||
GdkPoint last_pointer_position;
|
||||
GdkPoint pointer_offset_in_window;
|
||||
} EdgeSnapping;
|
||||
|
||||
void _edge_snapping_init (EdgeSnapping *self,
|
||||
const GdkRectangle *geometry,
|
||||
const GdkRectangle *workarea,
|
||||
const GdkPoint *pointer_position,
|
||||
const GdkRectangle *window);
|
||||
void _edge_snapping_motion (EdgeSnapping *self,
|
||||
const GdkPoint *pointer_position,
|
||||
GdkRectangle *window);
|
||||
void _edge_snapping_set_monitor (EdgeSnapping *self,
|
||||
const GdkRectangle *geometry,
|
||||
const GdkRectangle *workarea);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __EDGE_SNAPPING_H__ */
|
||||
@@ -0,0 +1,254 @@
|
||||
/* gdkdisplaylinksource.c
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Hergert <christian@hergert.me>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#include "gdkdisplaylinksource.h"
|
||||
|
||||
#include "gdkmacoseventsource-private.h"
|
||||
|
||||
static gint64 host_to_frame_clock_time (gint64 host_time);
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_prepare (GSource *source,
|
||||
gint *timeout_)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
gint64 now;
|
||||
|
||||
now = g_source_get_time (source);
|
||||
|
||||
if (now < impl->presentation_time)
|
||||
*timeout_ = (impl->presentation_time - now) / 1000L;
|
||||
else
|
||||
*timeout_ = -1;
|
||||
|
||||
return impl->needs_dispatch;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_check (GSource *source)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
return impl->needs_dispatch;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
gboolean ret = G_SOURCE_CONTINUE;
|
||||
|
||||
impl->needs_dispatch = FALSE;
|
||||
|
||||
if (callback != NULL)
|
||||
ret = callback (user_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_link_source_finalize (GSource *source)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
|
||||
CVDisplayLinkStop (impl->display_link);
|
||||
CVDisplayLinkRelease (impl->display_link);
|
||||
}
|
||||
|
||||
static GSourceFuncs gdk_display_link_source_funcs = {
|
||||
gdk_display_link_source_prepare,
|
||||
gdk_display_link_source_check,
|
||||
gdk_display_link_source_dispatch,
|
||||
gdk_display_link_source_finalize
|
||||
};
|
||||
|
||||
void
|
||||
gdk_display_link_source_pause (GdkDisplayLinkSource *source)
|
||||
{
|
||||
CVDisplayLinkStop (source->display_link);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
|
||||
{
|
||||
CVDisplayLinkStart (source->display_link);
|
||||
}
|
||||
|
||||
static CVReturn
|
||||
gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
|
||||
const CVTimeStamp *inNow,
|
||||
const CVTimeStamp *inOutputTime,
|
||||
CVOptionFlags flagsIn,
|
||||
CVOptionFlags *flagsOut,
|
||||
void *user_data)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = user_data;
|
||||
gint64 presentation_time;
|
||||
gboolean needs_wakeup;
|
||||
|
||||
needs_wakeup = !g_atomic_int_get (&impl->needs_dispatch);
|
||||
|
||||
presentation_time = host_to_frame_clock_time (inOutputTime->hostTime);
|
||||
|
||||
impl->presentation_time = presentation_time;
|
||||
impl->needs_dispatch = TRUE;
|
||||
|
||||
if (needs_wakeup)
|
||||
{
|
||||
NSEvent *event;
|
||||
|
||||
/* Post a message so we'll break out of the message loop.
|
||||
*
|
||||
* We don't use g_main_context_wakeup() here because that
|
||||
* would result in sending a message to the pipe(2) fd in
|
||||
* the select thread which would then send this message as
|
||||
* well. Lots of extra work.
|
||||
*/
|
||||
event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
|
||||
location: NSZeroPoint
|
||||
modifierFlags: 0
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: nil
|
||||
subtype: GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP
|
||||
data1: 0
|
||||
data2: 0];
|
||||
|
||||
[NSApp postEvent:event atStart:YES];
|
||||
}
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_link_source_new:
|
||||
*
|
||||
* Creates a new #GSource that will activate the dispatch function upon
|
||||
* notification from a CVDisplayLink that a new frame should be drawn.
|
||||
*
|
||||
* Effort is made to keep the transition from the high-priority
|
||||
* CVDisplayLink thread into this GSource lightweight. However, this is
|
||||
* somewhat non-ideal since the best case would be to do the drawing
|
||||
* from the high-priority thread.
|
||||
*
|
||||
* Returns: (transfer full): A newly created #GSource.
|
||||
*/
|
||||
GSource *
|
||||
gdk_display_link_source_new (void)
|
||||
{
|
||||
GdkDisplayLinkSource *impl;
|
||||
GSource *source;
|
||||
CVReturn ret;
|
||||
double period;
|
||||
|
||||
source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
|
||||
impl = (GdkDisplayLinkSource *)source;
|
||||
|
||||
/*
|
||||
* Create our link based on currently connected displays.
|
||||
* If there are multiple displays, this will be something that tries
|
||||
* to work for all of them. In the future, we may want to explore multiple
|
||||
* links based on the connected displays.
|
||||
*/
|
||||
ret = CVDisplayLinkCreateWithActiveCGDisplays (&impl->display_link);
|
||||
if (ret != kCVReturnSuccess)
|
||||
{
|
||||
g_warning ("Failed to initialize CVDisplayLink!");
|
||||
return source;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine our nominal period between frames.
|
||||
*/
|
||||
period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
|
||||
if (period == 0.0)
|
||||
period = 1.0 / 60.0;
|
||||
impl->refresh_interval = period * 1000000L;
|
||||
impl->refresh_rate = 1.0 / period * 1000L;
|
||||
|
||||
/*
|
||||
* Wire up our callback to be executed within the high-priority thread.
|
||||
*/
|
||||
CVDisplayLinkSetOutputCallback (impl->display_link,
|
||||
gdk_display_link_source_frame_cb,
|
||||
source);
|
||||
|
||||
g_source_set_name (source, "[gdk] quartz frame clock");
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static gint64
|
||||
host_to_frame_clock_time (gint64 host_time)
|
||||
{
|
||||
static mach_timebase_info_data_t timebase_info;
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* This code is taken from GLib to match g_get_monotonic_time().
|
||||
*/
|
||||
if (G_UNLIKELY (timebase_info.denom == 0))
|
||||
{
|
||||
/* This is a fraction that we must use to scale
|
||||
* mach_absolute_time() by in order to reach nanoseconds.
|
||||
*
|
||||
* We've only ever observed this to be 1/1, but maybe it could be
|
||||
* 1000/1 if mach time is microseconds already, or 1/1000 if
|
||||
* picoseconds. Try to deal nicely with that.
|
||||
*/
|
||||
mach_timebase_info (&timebase_info);
|
||||
|
||||
/* We actually want microseconds... */
|
||||
if (timebase_info.numer % 1000 == 0)
|
||||
timebase_info.numer /= 1000;
|
||||
else
|
||||
timebase_info.denom *= 1000;
|
||||
|
||||
/* We want to make the numer 1 to avoid having to multiply... */
|
||||
if (timebase_info.denom % timebase_info.numer == 0)
|
||||
{
|
||||
timebase_info.denom /= timebase_info.numer;
|
||||
timebase_info.numer = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We could just multiply by timebase_info.numer below, but why
|
||||
* bother for a case that may never actually exist...
|
||||
*
|
||||
* Plus -- performing the multiplication would risk integer
|
||||
* overflow. If we ever actually end up in this situation, we
|
||||
* should more carefully evaluate the correct course of action.
|
||||
*/
|
||||
mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */
|
||||
g_error ("Got weird mach timebase info of %d/%d. Please file a bug against GLib.",
|
||||
timebase_info.numer, timebase_info.denom);
|
||||
}
|
||||
}
|
||||
|
||||
return host_time / timebase_info.denom;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* gdkdisplaylinksource.h
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Hergert <christian@hergert.me>
|
||||
*/
|
||||
|
||||
#ifndef GDK_DISPLAY_LINK_SOURCE_H
|
||||
#define GDK_DISPLAY_LINK_SOURCE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GSource source;
|
||||
|
||||
CVDisplayLinkRef display_link;
|
||||
gint64 refresh_interval;
|
||||
guint refresh_rate;
|
||||
|
||||
volatile gint64 presentation_time;
|
||||
volatile guint needs_dispatch;
|
||||
} GdkDisplayLinkSource;
|
||||
|
||||
GSource *gdk_display_link_source_new (void);
|
||||
void gdk_display_link_source_pause (GdkDisplayLinkSource *source);
|
||||
void gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GDK_DISPLAY_LINK_SOURCE_H */
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_H__
|
||||
#define __GDK_MACOS_H__
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gdkmacosdevice.h"
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacosglcontext.h"
|
||||
#include "gdkmacoskeymap.h"
|
||||
#include "gdkmacosmonitor.h"
|
||||
#include "gdkmacossurface.h"
|
||||
|
||||
#endif /* __GDK_MACOS_H__ */
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
|
||||
#define __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
|
||||
|
||||
#include "gdkcairocontextprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GdkMacosCairoContext GdkMacosCairoContext;
|
||||
typedef struct _GdkMacosCairoContextClass GdkMacosCairoContextClass;
|
||||
|
||||
#define GDK_TYPE_MACOS_CAIRO_CONTEXT (_gdk_macos_cairo_context_get_type())
|
||||
#define GDK_MACOS_CAIRO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT, GdkMacosCairoContext))
|
||||
#define GDK_IS_MACOS_CAIRO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT))
|
||||
|
||||
GType _gdk_macos_cairo_context_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__ */
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright © 2016 Benjamin Otte
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkconfig.h"
|
||||
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <cairo-quartz.h>
|
||||
|
||||
#import "GdkMacosCairoView.h"
|
||||
|
||||
#include "gdkmacoscairocontext-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
struct _GdkMacosCairoContext
|
||||
{
|
||||
GdkCairoContext parent_instance;
|
||||
|
||||
cairo_surface_t *window_surface;
|
||||
};
|
||||
|
||||
struct _GdkMacosCairoContextClass
|
||||
{
|
||||
GdkCairoContextClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
|
||||
|
||||
static cairo_surface_t *
|
||||
create_cairo_surface_for_surface (GdkSurface *surface)
|
||||
{
|
||||
cairo_surface_t *cairo_surface;
|
||||
int scale;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
|
||||
scale = gdk_surface_get_scale_factor (surface);
|
||||
width = scale * gdk_surface_get_width (surface);
|
||||
height = scale * gdk_surface_get_height (surface);
|
||||
|
||||
cairo_surface = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
|
||||
if (cairo_surface != NULL)
|
||||
cairo_surface_set_device_scale (cairo_surface, scale, scale);
|
||||
|
||||
return cairo_surface;
|
||||
}
|
||||
|
||||
static cairo_t *
|
||||
_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)cairo_context;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
|
||||
return cairo_create (self->window_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
|
||||
GdkSurface *surface;
|
||||
NSWindow *nswindow;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
|
||||
surface = gdk_draw_context_get_surface (draw_context);
|
||||
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
|
||||
|
||||
if (self->window_surface == NULL)
|
||||
{
|
||||
self->window_surface = create_cairo_surface_for_surface (surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (![nswindow isOpaque])
|
||||
{
|
||||
cairo_t *cr = cairo_create (self->window_surface);
|
||||
gdk_cairo_region (cr, region);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
|
||||
cairo_region_t *painted)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
|
||||
GdkSurface *surface;
|
||||
NSView *nsview;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
g_assert (self->window_surface != NULL);
|
||||
|
||||
surface = gdk_draw_context_get_surface (draw_context);
|
||||
nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
|
||||
|
||||
if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
|
||||
[(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
|
||||
withDamage:painted];
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
|
||||
{
|
||||
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
|
||||
|
||||
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
|
||||
{
|
||||
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
|
||||
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
|
||||
|
||||
draw_context_class->begin_frame = _gdk_macos_cairo_context_begin_frame;
|
||||
draw_context_class->end_frame = _gdk_macos_cairo_context_end_frame;
|
||||
draw_context_class->surface_resized = _gdk_macos_cairo_context_surface_resized;
|
||||
|
||||
cairo_context_class->cairo_create = _gdk_macos_cairo_context_cairo_create;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_cairo_context_init (GdkMacosCairoContext *self)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_CLIPBOARD_PRIVATE_H__
|
||||
#define __GDK_MACOS_CLIPBOARD_PRIVATE_H__
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include "gdkclipboardprivate.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_MACOS_CLIPBOARD (_gdk_macos_clipboard_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
|
||||
|
||||
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
|
||||
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
|
||||
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate);
|
||||
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
|
||||
|
||||
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
|
||||
{
|
||||
GCancellable *cancellable;
|
||||
GdkClipboard *clipboard;
|
||||
char **mimeTypes;
|
||||
}
|
||||
|
||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
||||
-(NSArray<NSPasteboardType> *)types;
|
||||
|
||||
@end
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_CLIPBOARD_PRIVATE_H__ */
|
||||
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
|
||||
#include "gdkmacosclipboard-private.h"
|
||||
#include "gdkmacosutils-private.h"
|
||||
|
||||
struct _GdkMacosClipboard
|
||||
{
|
||||
GdkClipboard parent_instance;
|
||||
NSPasteboard *pasteboard;
|
||||
NSInteger last_change_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMemoryOutputStream *stream;
|
||||
NSPasteboardItem *item;
|
||||
NSPasteboardType type;
|
||||
GMainContext *main_context;
|
||||
guint done : 1;
|
||||
} WriteRequest;
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
|
||||
|
||||
static void
|
||||
write_request_free (WriteRequest *wr)
|
||||
{
|
||||
g_clear_pointer (&wr->main_context, g_main_context_unref);
|
||||
g_clear_object (&wr->stream);
|
||||
[wr->item release];
|
||||
g_slice_free (WriteRequest, wr);
|
||||
}
|
||||
|
||||
const char *
|
||||
_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([type isEqualToString:NSPasteboardTypeString] ||
|
||||
[type isEqualToString:NSStringPboardType])
|
||||
return g_intern_string ("text/plain;charset=utf-8");
|
||||
else if ([type isEqualToString:NSPasteboardTypeURL] ||
|
||||
[type isEqualToString:NSPasteboardTypeFileURL])
|
||||
return g_intern_string ("text/uri-list");
|
||||
else if ([type isEqualToString:NSPasteboardTypeColor])
|
||||
return g_intern_string ("application/x-color");
|
||||
else if ([type isEqualToString:NSPasteboardTypeTIFF])
|
||||
return g_intern_string ("image/tiff");
|
||||
else if ([type isEqualToString:NSPasteboardTypePNG])
|
||||
return g_intern_string ("image/png");
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NSPasteboardType
|
||||
_gdk_macos_clipboard_to_ns_type (const char *mime_type,
|
||||
NSPasteboardType *alternate)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = NULL;
|
||||
|
||||
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
return NSPasteboardTypeString;
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
if (alternate)
|
||||
*alternate = NSPasteboardTypeURL;
|
||||
return NSPasteboardTypeFileURL;
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
return NSPasteboardTypeColor;
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
return NSPasteboardTypeTIFF;
|
||||
}
|
||||
else if (g_strcmp0 (mime_type, "image/png") == 0)
|
||||
{
|
||||
return NSPasteboardTypePNG;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
populate_content_formats (GdkContentFormatsBuilder *builder,
|
||||
NSPasteboardType type)
|
||||
{
|
||||
const char *mime_type;
|
||||
|
||||
g_return_if_fail (builder != NULL);
|
||||
g_return_if_fail (type != NULL);
|
||||
|
||||
mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
||||
|
||||
if (mime_type != NULL)
|
||||
gdk_content_formats_builder_add_mime_type (builder, mime_type);
|
||||
}
|
||||
|
||||
static GdkContentFormats *
|
||||
load_offer_formats (GdkMacosClipboard *self)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkContentFormatsBuilder *builder;
|
||||
GdkContentFormats *formats;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
|
||||
builder = gdk_content_formats_builder_new ();
|
||||
for (NSPasteboardType type in [self->pasteboard types])
|
||||
populate_content_formats (builder, type);
|
||||
formats = gdk_content_formats_builder_free_to_formats (builder);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
return g_steal_pointer (&formats);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
|
||||
{
|
||||
GdkContentFormats *formats;
|
||||
NSInteger change_count;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
|
||||
change_count = [self->pasteboard changeCount];
|
||||
|
||||
formats = load_offer_formats (self);
|
||||
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
|
||||
gdk_content_formats_unref (formats);
|
||||
|
||||
self->last_change_count = change_count;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
create_stream_from_nsdata (NSData *data)
|
||||
{
|
||||
const guint8 *bytes = [data bytes];
|
||||
gsize len = [data length];
|
||||
|
||||
return g_memory_input_stream_new_from_data (g_memdup (bytes, len), len, g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
|
||||
GdkContentFormats *offer_formats = NULL;
|
||||
const char *mime_type;
|
||||
GInputStream *stream = NULL;
|
||||
GTask *task = NULL;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
g_assert (formats != NULL);
|
||||
|
||||
task = g_task_new (self, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, _gdk_macos_clipboard_read_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
offer_formats = load_offer_formats (GDK_MACOS_CLIPBOARD (clipboard));
|
||||
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
|
||||
|
||||
if (mime_type == NULL)
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_SUPPORTED,
|
||||
"%s",
|
||||
_("No compatible transfer format found"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
|
||||
{
|
||||
NSString *nsstr = [self->pasteboard stringForType:NSPasteboardTypeString];
|
||||
|
||||
if (nsstr != NULL)
|
||||
{
|
||||
const char *str = [nsstr UTF8String];
|
||||
stream = g_memory_input_stream_new_from_data (g_strdup (str),
|
||||
strlen (str) + 1,
|
||||
g_free);
|
||||
}
|
||||
}
|
||||
else if (strcmp (mime_type, "text/uri-list") == 0)
|
||||
{
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
||||
|
||||
if ([[self->pasteboard types] containsObject:NSPasteboardTypeFileURL])
|
||||
{
|
||||
GString *str = g_string_new (NULL);
|
||||
NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
|
||||
gsize n_files = [files count];
|
||||
char *data;
|
||||
guint len;
|
||||
|
||||
for (gsize i = 0; i < n_files; ++i)
|
||||
{
|
||||
NSString* uriString = [files objectAtIndex:i];
|
||||
uriString = [@"file://" stringByAppendingString:uriString];
|
||||
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
g_string_append_printf (str,
|
||||
"%s\r\n",
|
||||
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
}
|
||||
|
||||
len = str->len;
|
||||
data = g_string_free (str, FALSE);
|
||||
stream = g_memory_input_stream_new_from_data (data, len, g_free);
|
||||
}
|
||||
|
||||
G_GNUC_END_IGNORE_DEPRECATIONS;
|
||||
}
|
||||
else if (strcmp (mime_type, "application/x-color") == 0)
|
||||
{
|
||||
NSColorSpace *colorspace;
|
||||
NSColor *nscolor;
|
||||
guint16 color[4];
|
||||
|
||||
colorspace = [NSColorSpace genericRGBColorSpace];
|
||||
nscolor = [[NSColor colorFromPasteboard:self->pasteboard]
|
||||
colorUsingColorSpace:colorspace];
|
||||
|
||||
color[0] = 0xffff * [nscolor redComponent];
|
||||
color[1] = 0xffff * [nscolor greenComponent];
|
||||
color[2] = 0xffff * [nscolor blueComponent];
|
||||
color[3] = 0xffff * [nscolor alphaComponent];
|
||||
|
||||
stream = g_memory_input_stream_new_from_data (g_memdup (&color, sizeof color),
|
||||
sizeof color,
|
||||
g_free);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/tiff") == 0)
|
||||
{
|
||||
NSData *data = [self->pasteboard dataForType:NSPasteboardTypeTIFF];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
else if (strcmp (mime_type, "image/png") == 0)
|
||||
{
|
||||
NSData *data = [self->pasteboard dataForType:NSPasteboardTypePNG];
|
||||
stream = create_stream_from_nsdata (data);
|
||||
}
|
||||
|
||||
if (stream != NULL)
|
||||
{
|
||||
g_task_set_task_data (task, g_strdup (mime_type), g_free);
|
||||
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_new_error (task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
_("Failed to decode contents with mime-type of '%s'"),
|
||||
mime_type);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_clear_object (&task);
|
||||
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
_gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
|
||||
GAsyncResult *result,
|
||||
const char **out_mime_type,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task = (GTask *)result;
|
||||
|
||||
g_assert (GDK_IS_MACOS_CLIPBOARD (clipboard));
|
||||
g_assert (G_IS_TASK (task));
|
||||
|
||||
if (out_mime_type != NULL)
|
||||
*out_mime_type = g_strdup (g_task_get_task_data (task));
|
||||
|
||||
return g_task_propagate_pointer (task, error);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
|
||||
GdkContentProvider *content)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkMacosClipboardDataProvider *dataProvider;
|
||||
GdkContentFormats *serializable;
|
||||
NSPasteboardItem *item;
|
||||
const char * const *mime_types;
|
||||
gsize n_mime_types;
|
||||
|
||||
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
|
||||
|
||||
serializable = gdk_content_provider_ref_storable_formats (content);
|
||||
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
|
||||
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
|
||||
|
||||
dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
|
||||
mimetypes:mime_types];
|
||||
item = [[NSPasteboardItem alloc] init];
|
||||
[item setDataProvider:dataProvider forTypes:[dataProvider types]];
|
||||
|
||||
[self->pasteboard clearContents];
|
||||
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
|
||||
g_warning ("Failed to write object to pasteboard");
|
||||
|
||||
self->last_change_count = [self->pasteboard changeCount];
|
||||
|
||||
g_clear_pointer (&serializable, gdk_content_formats_unref);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gdk_macos_clipboard_claim (GdkClipboard *clipboard,
|
||||
GdkContentFormats *formats,
|
||||
gboolean local,
|
||||
GdkContentProvider *provider)
|
||||
{
|
||||
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
|
||||
gboolean ret;
|
||||
|
||||
g_assert (GDK_IS_CLIPBOARD (clipboard));
|
||||
g_assert (formats != NULL);
|
||||
g_assert (!provider || GDK_IS_CONTENT_PROVIDER (provider));
|
||||
|
||||
ret = GDK_CLIPBOARD_CLASS (_gdk_macos_clipboard_parent_class)->claim (clipboard, formats, local, provider);
|
||||
|
||||
if (local)
|
||||
_gdk_macos_clipboard_send_to_pasteboard (self, provider);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_constructed (GObject *object)
|
||||
{
|
||||
GdkMacosClipboard *self = (GdkMacosClipboard *)object;
|
||||
|
||||
if (self->pasteboard == nil)
|
||||
self->pasteboard = [[NSPasteboard generalPasteboard] retain];
|
||||
|
||||
G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_finalize (GObject *object)
|
||||
{
|
||||
GdkMacosClipboard *self = (GdkMacosClipboard *)object;
|
||||
|
||||
if (self->pasteboard != nil)
|
||||
{
|
||||
[self->pasteboard release];
|
||||
self->pasteboard = nil;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_class_init (GdkMacosClipboardClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (klass);
|
||||
|
||||
object_class->constructed = _gdk_macos_clipboard_constructed;
|
||||
object_class->finalize = _gdk_macos_clipboard_finalize;
|
||||
|
||||
clipboard_class->claim = _gdk_macos_clipboard_claim;
|
||||
clipboard_class->read_async = _gdk_macos_clipboard_read_async;
|
||||
clipboard_class->read_finish = _gdk_macos_clipboard_read_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdk_macos_clipboard_init (GdkMacosClipboard *self)
|
||||
{
|
||||
}
|
||||
|
||||
GdkClipboard *
|
||||
_gdk_macos_clipboard_new (GdkMacosDisplay *display)
|
||||
{
|
||||
GdkMacosClipboard *self;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
|
||||
|
||||
self = g_object_new (GDK_TYPE_MACOS_CLIPBOARD,
|
||||
"display", display,
|
||||
NULL);
|
||||
|
||||
_gdk_macos_clipboard_load_contents (self);
|
||||
|
||||
return GDK_CLIPBOARD (self);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
|
||||
|
||||
if ([self->pasteboard changeCount] != self->last_change_count)
|
||||
_gdk_macos_clipboard_load_contents (self);
|
||||
}
|
||||
|
||||
@implementation GdkMacosClipboardDataProvider
|
||||
|
||||
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
|
||||
{
|
||||
[super init];
|
||||
|
||||
self->mimeTypes = g_strdupv ((char **)mime_types);
|
||||
self->clipboard = g_object_ref (gdkClipboard);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
g_cancellable_cancel (self->cancellable);
|
||||
|
||||
g_clear_pointer (&self->mimeTypes, g_strfreev);
|
||||
g_clear_object (&self->clipboard);
|
||||
g_clear_object (&self->cancellable);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
|
||||
{
|
||||
g_clear_object (&self->clipboard);
|
||||
}
|
||||
|
||||
-(NSArray<NSPasteboardType> *)types
|
||||
{
|
||||
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
||||
|
||||
for (guint i = 0; self->mimeTypes[i]; i++)
|
||||
{
|
||||
const char *mime_type = self->mimeTypes[i];
|
||||
NSPasteboardType type;
|
||||
NSPasteboardType alternate = nil;
|
||||
|
||||
if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
|
||||
{
|
||||
[ret addObject:type];
|
||||
if (alternate)
|
||||
[ret addObject:alternate];
|
||||
}
|
||||
}
|
||||
|
||||
return g_steal_pointer (&ret);
|
||||
}
|
||||
|
||||
static void
|
||||
on_data_ready_cb (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
GdkClipboard *clipboard = (GdkClipboard *)object;
|
||||
WriteRequest *wr = user_data;
|
||||
GError *error = NULL;
|
||||
NSData *data = nil;
|
||||
|
||||
g_assert (GDK_IS_CLIPBOARD (clipboard));
|
||||
g_assert (G_IS_ASYNC_RESULT (result));
|
||||
g_assert (wr != NULL);
|
||||
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
|
||||
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
|
||||
|
||||
if (gdk_clipboard_write_finish (clipboard, result, &error))
|
||||
{
|
||||
gsize size;
|
||||
gpointer bytes;
|
||||
|
||||
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
|
||||
|
||||
size = g_memory_output_stream_get_size (wr->stream);
|
||||
bytes = g_memory_output_stream_steal_data (wr->stream);
|
||||
data = [[NSData alloc] initWithBytesNoCopy:bytes
|
||||
length:size
|
||||
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Failed to serialize clipboard contents: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
[wr->item setData:data forType:wr->type];
|
||||
|
||||
wr->done = TRUE;
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
-(void) pasteboard:(NSPasteboard *)pasteboard
|
||||
item:(NSPasteboardItem *)item
|
||||
provideDataForType:(NSPasteboardType)type
|
||||
{
|
||||
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
|
||||
GMainContext *main_context = g_main_context_default ();
|
||||
WriteRequest *wr;
|
||||
|
||||
if (self->clipboard == NULL || mime_type == NULL)
|
||||
{
|
||||
[item setData:[NSData data] forType:type];
|
||||
return;
|
||||
}
|
||||
|
||||
wr = g_slice_new0 (WriteRequest);
|
||||
wr->item = [item retain];
|
||||
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
|
||||
wr->type = type;
|
||||
wr->main_context = g_main_context_ref (main_context);
|
||||
wr->done = FALSE;
|
||||
|
||||
gdk_clipboard_write_async (self->clipboard,
|
||||
mime_type,
|
||||
G_OUTPUT_STREAM (wr->stream),
|
||||
G_PRIORITY_DEFAULT,
|
||||
self->cancellable,
|
||||
on_data_ready_cb,
|
||||
wr);
|
||||
|
||||
/* We're forced to provide data synchronously via this API
|
||||
* so we must block on the main loop. Using another main loop
|
||||
* than the default tends to get us locked up here, so that is
|
||||
* what we'll do for now.
|
||||
*/
|
||||
while (!wr->done)
|
||||
g_main_context_iteration (wr->main_context, TRUE);
|
||||
|
||||
write_request_free (wr);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1,7 +1,7 @@
|
||||
/* gdkdnd-quartz.h
|
||||
/* gdkmacoscursor-private.h
|
||||
*
|
||||
* Copyright (C) 2005 Imendio AB
|
||||
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
|
||||
* Copyright (C) 2005-2007 Imendio AB
|
||||
* Copyright (C) 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -17,29 +17,16 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_QUARTZ_DND__
|
||||
#define __GDK_QUARTZ_DND__
|
||||
|
||||
#include <gdkdndprivate.h>
|
||||
#include "gdkquartzdnd.h"
|
||||
#ifndef __GDK_MACOS_CURSOR_PRIVATE_H__
|
||||
#define __GDK_MACOS_CURSOR_PRIVATE_H__
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GdkQuartzDragContext
|
||||
{
|
||||
GdkDragContext context;
|
||||
|
||||
id <NSDraggingInfo> dragging_info;
|
||||
GdkDevice *device;
|
||||
};
|
||||
|
||||
struct _GdkQuartzDragContextClass
|
||||
{
|
||||
GdkDragContextClass context_class;
|
||||
};
|
||||
NSCursor *_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_QUARTZ_DND__ */
|
||||
#endif /* __GDK_MACOS_CURSOR_PRIVATE_H__ */
|
||||
@@ -0,0 +1,181 @@
|
||||
/* gdkcursor-macos.c
|
||||
*
|
||||
* Copyright (C) 2005-2007 Imendio AB
|
||||
* Copyright (C) 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gdkmacoscursor-private.h"
|
||||
|
||||
/* OS X only exports a number of cursor types in its public NSCursor interface.
|
||||
* By overriding the private _coreCursorType method, we can tell OS X to load
|
||||
* one of its internal cursors instead (since cursor images are loaded on demand
|
||||
* instead of in advance). WebKit does this too.
|
||||
*/
|
||||
|
||||
@interface gdkCoreCursor : NSCursor {
|
||||
@private
|
||||
int type;
|
||||
BOOL override;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation gdkCoreCursor
|
||||
|
||||
- (long long)_coreCursorType
|
||||
{
|
||||
if (self->override)
|
||||
return self->type;
|
||||
return [super _coreCursorType];
|
||||
}
|
||||
|
||||
#define CUSTOM_CURSOR_CTOR(name, id) \
|
||||
+ (gdkCoreCursor *)name \
|
||||
{ \
|
||||
gdkCoreCursor *obj; \
|
||||
obj = [self new]; \
|
||||
if (obj) { \
|
||||
obj->override = YES; \
|
||||
obj->type = id; \
|
||||
} \
|
||||
return obj; \
|
||||
}
|
||||
CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
|
||||
CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
|
||||
/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
|
||||
* method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
|
||||
* but rather some odd low-quality non-animating version of this cursor. Use
|
||||
* the progress cursor instead for now.
|
||||
*/
|
||||
CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
|
||||
CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
|
||||
CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
|
||||
/* TODO OS X doesn't seem to provide one; copy the move cursor for now
|
||||
* since it looks similar to what we want. */
|
||||
CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
|
||||
CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
|
||||
CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
|
||||
CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
|
||||
CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
|
||||
CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
|
||||
CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
|
||||
CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
|
||||
CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
|
||||
CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
|
||||
CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
|
||||
#undef CUSTOM_CURSOR_CTOR
|
||||
|
||||
@end
|
||||
|
||||
struct CursorsByName {
|
||||
const gchar *name;
|
||||
NSString *selector;
|
||||
};
|
||||
|
||||
static const struct CursorsByName cursors_by_name[] = {
|
||||
/* Link & Status */
|
||||
{ "context-menu", @"contextualMenuCursor" },
|
||||
{ "help", @"gdkHelpCursor" },
|
||||
{ "pointer", @"pointingHandCursor" },
|
||||
{ "progress", @"gdkProgressCursor" },
|
||||
{ "wait", @"gdkWaitCursor" },
|
||||
/* Selection */
|
||||
{ "cell", @"crosshairCursor" },
|
||||
{ "crosshair", @"crosshairCursor" },
|
||||
{ "text", @"IBeamCursor" },
|
||||
{ "vertical-text", @"IBeamCursorForVerticalLayout" },
|
||||
/* Drag & Drop */
|
||||
{ "alias", @"gdkAliasCursor" },
|
||||
{ "copy", @"dragCopyCursor" },
|
||||
{ "move", @"gdkMoveCursor" },
|
||||
{ "no-drop", @"operationNotAllowedCursor" },
|
||||
{ "not-allowed", @"operationNotAllowedCursor" },
|
||||
{ "grab", @"openHandCursor" },
|
||||
{ "grabbing", @"closedHandCursor" },
|
||||
/* Resize & Scrolling */
|
||||
{ "all-scroll", @"gdkAllScrollCursor" },
|
||||
{ "col-resize", @"resizeLeftRightCursor" },
|
||||
{ "row-resize", @"resizeUpDownCursor" },
|
||||
|
||||
/* Undocumented cursors to match native resizing */
|
||||
{ "e-resize", @"_windowResizeEastWestCursor" },
|
||||
{ "w-resize", @"_windowResizeEastWestCursor" },
|
||||
{ "n-resize", @"_windowResizeNorthSouthCursor" },
|
||||
{ "s-resize", @"_windowResizeNorthSouthCursor" },
|
||||
|
||||
{ "ne-resize", @"gdkNEResizeCursor" },
|
||||
{ "nw-resize", @"gdkNWResizeCursor" },
|
||||
{ "se-resize", @"gdkSEResizeCursor" },
|
||||
{ "sw-resize", @"gdkSWResizeCursor" },
|
||||
{ "ew-resize", @"gdkEWResizeCursor" },
|
||||
{ "ns-resize", @"gdkNSResizeCursor" },
|
||||
{ "nesw-resize", @"gdkNESWResizeCursor" },
|
||||
{ "nwse-resize", @"gdkNWSEResizeCursor" },
|
||||
/* Zoom */
|
||||
{ "zoom-in", @"gdkZoomInCursor" },
|
||||
{ "zoom-out", @"gdkZoomOutCursor" },
|
||||
};
|
||||
|
||||
static NSCursor *
|
||||
create_blank_cursor (void)
|
||||
{
|
||||
NSCursor *nscursor;
|
||||
NSImage *nsimage;
|
||||
NSSize size = { 1.0, 1.0 };
|
||||
|
||||
nsimage = [[NSImage alloc] initWithSize:size];
|
||||
nscursor = [[NSCursor alloc] initWithImage:nsimage
|
||||
hotSpot:NSMakePoint(0.0, 0.0)];
|
||||
[nsimage release];
|
||||
|
||||
return nscursor;
|
||||
}
|
||||
|
||||
NSCursor *
|
||||
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
|
||||
{
|
||||
const char *name = NULL;
|
||||
NSCursor *nscursor;
|
||||
SEL selector = @selector(arrowCursor);
|
||||
|
||||
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
|
||||
|
||||
if (cursor != NULL)
|
||||
name = gdk_cursor_get_name (cursor);
|
||||
|
||||
if (name == NULL)
|
||||
goto load_cursor;
|
||||
|
||||
if (strcmp (name, "none") == 0)
|
||||
return create_blank_cursor ();
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (cursors_by_name); i++)
|
||||
{
|
||||
if (strcmp (cursors_by_name[i].name, name) == 0)
|
||||
{
|
||||
selector = NSSelectorFromString (cursors_by_name[i].selector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
load_cursor:
|
||||
nscursor = [[gdkCoreCursor class] performSelector:selector];
|
||||
[nscursor retain];
|
||||
return nscursor;
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright 2009 Carlos Garnacho <carlosg@gnome.org>
|
||||
* Copyright 2010 Kristian Rietveld <kris@gtk.org>
|
||||
* Copyright 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
|
||||
#include "gdkmacoscursor-private.h"
|
||||
#include "gdkmacosdevice.h"
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacossurface-private.h"
|
||||
|
||||
struct _GdkMacosDevice
|
||||
{
|
||||
GdkDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _GdkMacosDeviceClass
|
||||
{
|
||||
GdkDeviceClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkMacosDevice, gdk_macos_device, GDK_TYPE_DEVICE)
|
||||
|
||||
static void
|
||||
gdk_macos_device_set_surface_cursor (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkCursor *cursor)
|
||||
{
|
||||
NSCursor *nscursor;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
g_assert (!cursor || GDK_IS_CURSOR (cursor));
|
||||
|
||||
nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
|
||||
|
||||
if (nscursor != NULL)
|
||||
{
|
||||
[nscursor set];
|
||||
[nscursor release];
|
||||
}
|
||||
}
|
||||
|
||||
static GdkSurface *
|
||||
gdk_macos_device_surface_at_position (GdkDevice *device,
|
||||
gdouble *win_x,
|
||||
gdouble *win_y,
|
||||
GdkModifierType *state)
|
||||
{
|
||||
GdkMacosDisplay *display;
|
||||
GdkMacosSurface *surface;
|
||||
NSPoint point;
|
||||
gint x;
|
||||
gint y;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||
g_assert (win_x != NULL);
|
||||
g_assert (win_y != NULL);
|
||||
|
||||
point = [NSEvent mouseLocation];
|
||||
display = GDK_MACOS_DISPLAY (gdk_device_get_display (device));
|
||||
|
||||
if (state != NULL)
|
||||
*state = (_gdk_macos_display_get_current_keyboard_modifiers (display) |
|
||||
_gdk_macos_display_get_current_mouse_modifiers (display));
|
||||
|
||||
surface = _gdk_macos_display_get_surface_at_display_coords (display, point.x, point.y, &x, &y);
|
||||
|
||||
*win_x = x;
|
||||
*win_y = y;
|
||||
|
||||
return GDK_SURFACE (surface);
|
||||
}
|
||||
|
||||
static GdkGrabStatus
|
||||
gdk_macos_device_grab (GdkDevice *device,
|
||||
GdkSurface *window,
|
||||
gboolean owner_events,
|
||||
GdkEventMask event_mask,
|
||||
GdkSurface *confine_to,
|
||||
GdkCursor *cursor,
|
||||
guint32 time_)
|
||||
{
|
||||
/* Should remain empty */
|
||||
return GDK_GRAB_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_device_ungrab (GdkDevice *device,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkMacosDevice *self = (GdkMacosDevice *)device;
|
||||
GdkDeviceGrabInfo *grab;
|
||||
GdkDisplay *display;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DEVICE (self));
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
grab = _gdk_display_get_last_device_grab (display, device);
|
||||
|
||||
if (grab != NULL)
|
||||
grab->serial_end = 0;
|
||||
|
||||
_gdk_display_device_grab_update (display, device, device, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_device_get_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
gdouble *axes,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
gdouble x_pos, y_pos;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||
g_assert (GDK_IS_MACOS_SURFACE (surface));
|
||||
|
||||
gdk_surface_get_device_position (surface, device, &x_pos, &y_pos, mask);
|
||||
|
||||
if (axes != NULL)
|
||||
{
|
||||
axes[0] = x_pos;
|
||||
axes[1] = y_pos;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_device_query_state (GdkDevice *device,
|
||||
GdkSurface *surface,
|
||||
GdkSurface **child_surface,
|
||||
gdouble *win_x,
|
||||
gdouble *win_y,
|
||||
GdkModifierType *mask)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
NSPoint point;
|
||||
int sx = 0;
|
||||
int sy = 0;
|
||||
int x_tmp;
|
||||
int y_tmp;
|
||||
|
||||
g_assert (GDK_IS_MACOS_DEVICE (device));
|
||||
g_assert (!surface || GDK_IS_MACOS_SURFACE (surface));
|
||||
|
||||
if (child_surface)
|
||||
*child_surface = surface;
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
point = [NSEvent mouseLocation];
|
||||
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
|
||||
point.x, point.y,
|
||||
&x_tmp, &y_tmp);
|
||||
|
||||
if (surface)
|
||||
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
|
||||
|
||||
if (win_x)
|
||||
*win_x = x_tmp - sx;
|
||||
|
||||
if (win_y)
|
||||
*win_y = y_tmp - sy;
|
||||
|
||||
if (mask)
|
||||
*mask = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display)) |
|
||||
_gdk_macos_display_get_current_mouse_modifiers (GDK_MACOS_DISPLAY (display));
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_device_class_init (GdkMacosDeviceClass *klass)
|
||||
{
|
||||
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->get_state = gdk_macos_device_get_state;
|
||||
device_class->grab = gdk_macos_device_grab;
|
||||
device_class->query_state = gdk_macos_device_query_state;
|
||||
device_class->set_surface_cursor = gdk_macos_device_set_surface_cursor;
|
||||
device_class->surface_at_position = gdk_macos_device_surface_at_position;
|
||||
device_class->ungrab = gdk_macos_device_ungrab;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_macos_device_init (GdkMacosDevice *self)
|
||||
{
|
||||
_gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_X, 0, 0, 1);
|
||||
_gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_Y, 0, 0, 1);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_DEVICE_H__
|
||||
#define __GDK_MACOS_DEVICE_H__
|
||||
|
||||
#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
|
||||
|
||||
typedef struct _GdkMacosDevice GdkMacosDevice;
|
||||
typedef struct _GdkMacosDeviceClass GdkMacosDeviceClass;
|
||||
|
||||
#define GDK_TYPE_MACOS_DEVICE (gdk_macos_device_get_type())
|
||||
#define GDK_MACOS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DEVICE, GdkMacosDevice))
|
||||
#define GDK_IS_MACOS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DEVICE))
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_macos_device_get_type (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_DEVICE_H__ */
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef __GDK_MACOS_DISPLAY_PRIVATE_H__
|
||||
#define __GDK_MACOS_DISPLAY_PRIVATE_H__
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
|
||||
#include "gdkmacosdisplay.h"
|
||||
#include "gdkmacoskeymap.h"
|
||||
#include "gdkmacossurface.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GdkMacosDisplay
|
||||
{
|
||||
GdkDisplay parent_instance;
|
||||
|
||||
char *name;
|
||||
GdkMacosKeymap *keymap;
|
||||
|
||||
/* An list of GdkMacosMonitor. The first instance is always the primary
|
||||
* monitor. This contains the 0,0 coordinate in quartz coordinates, but may
|
||||
* not be 0,0 in GDK coordinates.
|
||||
*/
|
||||
GListStore *monitors;
|
||||
|
||||
/* A queue of surfaces that have been made "main" so that we can update the
|
||||
* main status to the next surface when a window has lost main status (such
|
||||
* as when destroyed). This uses the GdkMacosSurface main link.
|
||||
*/
|
||||
GQueue main_surfaces;
|
||||
|
||||
/* A queue of surfaces sorted by their front-to-back ordering on the screen.
|
||||
* This is updated occasionally when we know that the data we have cached
|
||||
* has been invalidated. This uses the GdkMacosSurface.sorted link.
|
||||
*/
|
||||
GQueue sorted_surfaces;
|
||||
|
||||
/* Our CVDisplayLink based GSource which we use to freeze/thaw the
|
||||
* GdkFrameClock for the surface.
|
||||
*/
|
||||
GSource *frame_source;
|
||||
|
||||
/* A queue of surfaces which we know are awaiting frames to be drawn. This
|
||||
* uses the GdkMacosSurface.frame link.
|
||||
*/
|
||||
GQueue awaiting_frames;
|
||||
|
||||
/* The surface that is receiving keyboard events */
|
||||
GdkMacosSurface *keyboard_surface;
|
||||
|
||||
/* Used to translate from quartz coordinate space to GDK */
|
||||
int width;
|
||||
int height;
|
||||
int min_x;
|
||||
int min_y;
|
||||
int max_x;
|
||||
int max_y;
|
||||
};
|
||||
|
||||
struct _GdkMacosDisplayClass
|
||||
{
|
||||
GdkDisplayClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GdkDisplay *_gdk_macos_display_open (const gchar *display_name);
|
||||
int _gdk_macos_display_get_fd (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_queue_events (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_to_display_coords (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y,
|
||||
int *out_x,
|
||||
int *out_y);
|
||||
void _gdk_macos_display_from_display_coords (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y,
|
||||
int *out_x,
|
||||
int *out_y);
|
||||
NSScreen *_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y);
|
||||
GdkMonitor *_gdk_macos_display_get_monitor_at_coords (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y);
|
||||
GdkMonitor *_gdk_macos_display_get_monitor_at_display_coords (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y);
|
||||
GdkEvent *_gdk_macos_display_translate (GdkMacosDisplay *self,
|
||||
NSEvent *event);
|
||||
void _gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
|
||||
guint32 time);
|
||||
GdkModifierType _gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self);
|
||||
GdkModifierType _gdk_macos_display_get_current_mouse_modifiers (GdkMacosDisplay *self);
|
||||
GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
|
||||
double x,
|
||||
double y,
|
||||
int *surface_x,
|
||||
int *surface_y);
|
||||
void _gdk_macos_display_reload_monitors (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_synthesize_motion (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
NSWindow *_gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
|
||||
int *x,
|
||||
int *y);
|
||||
gboolean _gdk_macos_display_get_setting (GdkMacosDisplay *self,
|
||||
const gchar *setting,
|
||||
GValue *value);
|
||||
void _gdk_macos_display_reload_settings (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
void _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
|
||||
GdkMacosSurface *surface);
|
||||
int _gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_clear_sorting (GdkMacosDisplay *self);
|
||||
const GList *_gdk_macos_display_get_surfaces (GdkMacosDisplay *self);
|
||||
void _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
|
||||
NSEvent *nsevent);
|
||||
void _gdk_macos_display_warp_pointer (GdkMacosDisplay *self,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_MACOS_DISPLAY_PRIVATE_H__ */
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||
* Copyright © 1998-2002 Tor Lillqvist
|
||||
* Copyright © 2005-2008 Imendio AB
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <AppKit/AppKit.h>
|
||||
|
||||
#include "gdkdisplayprivate.h"
|
||||
|
||||
#include "gdkmacosdisplay-private.h"
|
||||
#include "gdkmacosutils-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *font_name;
|
||||
int xft_dpi;
|
||||
int double_click_time;
|
||||
int cursor_blink_timeout;
|
||||
guint enable_animations : 1;
|
||||
guint shell_shows_desktop : 1;
|
||||
guint shell_shows_menubar : 1;
|
||||
guint primary_button_warps_slider : 1;
|
||||
} GdkMacosSettings;
|
||||
|
||||
static GdkMacosSettings current_settings;
|
||||
static gboolean current_settings_initialized;
|
||||
|
||||
static void
|
||||
_gdk_macos_settings_load (GdkMacosSettings *settings)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString *name;
|
||||
NSInteger ival;
|
||||
float fval;
|
||||
char *str;
|
||||
int pt_size;
|
||||
|
||||
g_assert (settings != NULL);
|
||||
|
||||
settings->shell_shows_desktop = TRUE;
|
||||
settings->shell_shows_menubar = TRUE;
|
||||
settings->enable_animations = TRUE;
|
||||
settings->xft_dpi = 72 * 1024;
|
||||
|
||||
ival = [defaults integerForKey:@"NSTextInsertionPointBlinkPeriod"];
|
||||
if (ival > 0)
|
||||
settings->cursor_blink_timeout = ival;
|
||||
else
|
||||
settings->cursor_blink_timeout = 1000;
|
||||
|
||||
settings->primary_button_warps_slider =
|
||||
[[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"] == YES;
|
||||
|
||||
fval = [defaults floatForKey:@"com.apple.mouse.doubleClickThreshold"];
|
||||
if (fval == 0.0)
|
||||
fval = 0.5;
|
||||
settings->double_click_time = fval * 1000;
|
||||
|
||||
name = [[NSFont systemFontOfSize:0] familyName];
|
||||
pt_size = (gint)[[NSFont userFontOfSize:0] pointSize];
|
||||
/* Let's try to use the "views" font size (12pt) by default. This is
|
||||
* used for lists/text/other "content" which is the largest parts of
|
||||
* apps, using the "regular control" size (13pt) looks a bit out of
|
||||
* place. We might have to tweak this.
|
||||
*
|
||||
* The size has to be hardcoded as there doesn't seem to be a way to
|
||||
* get the views font size programmatically.
|
||||
*/
|
||||
str = g_strdup_printf ("%s %d", [name UTF8String], pt_size);
|
||||
settings->font_name = g_intern_string (str);
|
||||
g_free (str);
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_macos_display_get_setting (GdkMacosDisplay *self,
|
||||
const gchar *setting,
|
||||
GValue *value)
|
||||
{
|
||||
GDK_BEGIN_MACOS_ALLOC_POOL;
|
||||
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), FALSE);
|
||||
g_return_val_if_fail (setting != NULL, FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
if (!current_settings_initialized)
|
||||
{
|
||||
_gdk_macos_settings_load (¤t_settings);
|
||||
current_settings_initialized = TRUE;
|
||||
}
|
||||
|
||||
if (FALSE) {}
|
||||
else if (strcmp (setting, "gtk-enable-animations") == 0)
|
||||
{
|
||||
g_value_set_boolean (value, current_settings.enable_animations);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-xft-dpi") == 0)
|
||||
{
|
||||
g_value_set_int (value, current_settings.xft_dpi);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-cursor-blink-timeout") == 0)
|
||||
{
|
||||
g_value_set_int (value, current_settings.cursor_blink_timeout);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-double-click-time") == 0)
|
||||
{
|
||||
g_value_set_int (value, current_settings.double_click_time);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-font-name") == 0)
|
||||
{
|
||||
g_value_set_static_string (value, current_settings.font_name);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-primary-button-warps-slider") == 0)
|
||||
{
|
||||
g_value_set_boolean (value, current_settings.primary_button_warps_slider);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-shell-shows-desktop") == 0)
|
||||
{
|
||||
g_value_set_boolean (value, current_settings.shell_shows_desktop);
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (strcmp (setting, "gtk-shell-shows-menubar") == 0)
|
||||
{
|
||||
g_value_set_boolean (value, current_settings.shell_shows_menubar);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
GDK_END_MACOS_ALLOC_POOL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_macos_display_reload_settings (GdkMacosDisplay *self)
|
||||
{
|
||||
GdkMacosSettings old_settings;
|
||||
|
||||
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
|
||||
|
||||
old_settings = current_settings;
|
||||
_gdk_macos_settings_load (¤t_settings);
|
||||
current_settings_initialized = TRUE;
|
||||
|
||||
if (old_settings.xft_dpi != current_settings.xft_dpi)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-xft-dpi");
|
||||
|
||||
if (old_settings.double_click_time != current_settings.double_click_time)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-double-click-time");
|
||||
|
||||
if (old_settings.enable_animations != current_settings.enable_animations)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-enable-animations");
|
||||
|
||||
if (old_settings.font_name != current_settings.font_name)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-font-name");
|
||||
|
||||
if (old_settings.primary_button_warps_slider != current_settings.primary_button_warps_slider)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-primary-button-warps-slider");
|
||||
|
||||
if (old_settings.shell_shows_menubar != current_settings.shell_shows_menubar)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-menubar");
|
||||
|
||||
if (old_settings.shell_shows_desktop != current_settings.shell_shows_desktop)
|
||||
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-desktop");
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user