Compare commits
3 Commits
gridview-s
...
frame-cloc
Author | SHA1 | Date | |
---|---|---|---|
|
49e93f6ee4 | ||
|
4ec2234537 | ||
|
5a3755b233 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1 @@
|
||||
/subprojects/*/
|
||||
.flatpak-builder/
|
||||
|
@@ -24,9 +24,9 @@ stages:
|
||||
variables:
|
||||
COMMON_MESON_FLAGS: "-Dwerror=true -Dcairo:werror=false -Dgi-docgen:werror=false -Dgraphene:werror=false -Dlibepoxy:werror=false -Dlibsass:werror=false -Dpango:werror=false -Dsassc:werror=false -Dgdk-pixbuf:werror=false -Dglib:werror=false -Dlibcloudproviders:werror=false -Dlibpng:werror=false -Dlibtiff:werror=false -Dsysprof:werror=false -Dwayland-protocols:werror=false -Dharfbuzz:werror=false -Dfreetype2:werror=false -Dfontconfig:werror=false -Dfribidi:werror=false -Dlibffi:werror=false -Dlibjpeg-turbo:werror=false -Dmutest:werror=false -Dpixman:werror=false -Dproxy-libintl:werror=false"
|
||||
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Dbuild-testsuite=true -Dintrospection=enabled"
|
||||
FEATURE_FLAGS: "-Dvulkan=enabled -Dcloudproviders=enabled -Ddemos=false -Dbuild-examples=false -Dbuild-tests=false -Dbuild-testsuite=true"
|
||||
MESON_TEST_TIMEOUT_MULTIPLIER: 3
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v46"
|
||||
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v41"
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
@@ -57,9 +57,11 @@ style-check-diff:
|
||||
reports:
|
||||
junit:
|
||||
- "${CI_PROJECT_DIR}/_build/report-x11.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-x11_unstable.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland_gles.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-wayland_unstable.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-broadway.xml"
|
||||
- "${CI_PROJECT_DIR}/_build/report-broadway_unstable.xml"
|
||||
name: "gtk-${CI_COMMIT_REF_NAME}"
|
||||
paths:
|
||||
- "${CI_PROJECT_DIR}/_build/meson-logs"
|
||||
@@ -70,7 +72,6 @@ style-check-diff:
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/tools/output/*/*"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/gsk/compare/*/*/*.png"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/css/output/*/*.syscap"
|
||||
- "${CI_PROJECT_DIR}/_build/testsuite/headless/*/*.log"
|
||||
- "${CI_PROJECT_DIR}/_build_hello/meson-logs"
|
||||
cache:
|
||||
key: "$CI_JOB_NAME"
|
||||
@@ -86,27 +87,7 @@ fedora-x86_64:
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
${BACKEND_FLAGS}
|
||||
${FEATURE_FLAGS}
|
||||
_build
|
||||
- meson compile -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
- .gitlab-ci/run-tests.sh _build wayland_gles
|
||||
|
||||
release-build:
|
||||
extends: .build-fedora-default
|
||||
stage: build
|
||||
needs: []
|
||||
variables:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=release"
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- mkdir _install
|
||||
@@ -122,8 +103,11 @@ release-build:
|
||||
- PKG_CONFIG_PATH=${CI_PROJECT_DIR}/_install/lib64/pkgconfig:${CI_PROJECT_DIR}/_install/share/pkgconfig meson setup _build_hello examples/hello
|
||||
- LD_LIBRARY_PATH=${CI_PROJECT_DIR}/_install/lib64 meson compile -C _build_hello
|
||||
- .gitlab-ci/run-tests.sh _build x11
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
- .gitlab-ci/run-tests.sh _build waylandgles
|
||||
- .gitlab-ci/run-tests.sh _build broadway
|
||||
|
||||
fedora-clang:
|
||||
release-build:
|
||||
extends: .build-fedora-default
|
||||
stage: build
|
||||
needs: []
|
||||
@@ -132,7 +116,7 @@ fedora-clang:
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- export CC=clang
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- meson setup
|
||||
@@ -142,6 +126,7 @@ fedora-clang:
|
||||
${FEATURE_FLAGS}
|
||||
_build
|
||||
- meson compile -C _build
|
||||
- .gitlab-ci/run-tests.sh _build x11
|
||||
|
||||
fedora-mingw64:
|
||||
extends: .build-fedora-default
|
||||
@@ -162,11 +147,23 @@ fedora-mingw64:
|
||||
script:
|
||||
- .gitlab-ci/show-info-linux.sh
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=1.0
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson subprojects download
|
||||
- meson subprojects update --reset
|
||||
- meson -Dintrospection=disabled -Dgraphene:introspection=disabled _build
|
||||
- meson compile -C _build
|
||||
# Test that mingw64-meson still fails. If it has stopped failing, the CI
|
||||
# will fail and now you should remove the hack that follows this.
|
||||
- FAILED=false
|
||||
- mingw64-meson --version || FAILED=true
|
||||
- test $FAILED = false && echo "mingw64-meson works now, remove the hack" && exit 1
|
||||
# HACK: Running mingw64-meson directly fails on the CI with:
|
||||
# /usr/bin/mingw64-meson: line 92: fg: no job control
|
||||
# Because rpm is not evaluating %__meson and it gets interpreted as a job
|
||||
# specifier. So we fix that and run it ourselves.
|
||||
- rpm --eval "%{mingw64_meson}" > mingw64-meson.sh
|
||||
- sed -i -e 's/%__meson/meson/' mingw64-meson.sh
|
||||
- chmod +x mingw64-meson.sh
|
||||
- ./mingw64-meson.sh -Dintrospection=disabled -Dgraphene:introspection=disabled _build
|
||||
- ninja -C _build
|
||||
|
||||
.mingw-defaults:
|
||||
stage: build
|
||||
@@ -208,7 +205,7 @@ macos:
|
||||
needs: []
|
||||
before_script:
|
||||
- bash .gitlab-ci/show-info-osx.sh
|
||||
- pip3 install --user meson~=1.0
|
||||
- pip3 install --user meson~=0.64
|
||||
- pip3 install --user ninja
|
||||
- export PATH=/Users/gitlabrunner/Library/Python/3.7/bin:$PATH
|
||||
- export MESON_FORCE_BACKTRACE=1
|
||||
@@ -366,11 +363,10 @@ static-scan:
|
||||
EXTRA_MESON_FLAGS: "--buildtype=debug"
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
${EXTRA_MESON_FLAGS}
|
||||
${BACKEND_FLAGS}
|
||||
${FEATURE_FLAGS}
|
||||
_scan_build
|
||||
- ninja -C _scan_build scan-build
|
||||
artifacts:
|
||||
@@ -389,6 +385,7 @@ asan-build:
|
||||
variables:
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- CC=clang meson setup --buildtype=debugoptimized -Db_sanitize=address -Db_lundef=false -Dintrospection=disabled -Df16c=disabled _build
|
||||
- ninja -C _build
|
||||
- .gitlab-ci/run-tests.sh _build wayland
|
||||
@@ -403,6 +400,7 @@ reference:
|
||||
needs: []
|
||||
script:
|
||||
- export PATH="$HOME/.local/bin:$PATH"
|
||||
- pip3 install --user meson~=0.64
|
||||
- meson setup
|
||||
${COMMON_MESON_FLAGS}
|
||||
--buildtype=release
|
||||
|
@@ -1,4 +1,4 @@
|
||||
FROM fedora:38
|
||||
FROM fedora:37
|
||||
|
||||
RUN dnf -y install \
|
||||
adwaita-icon-theme \
|
||||
@@ -32,6 +32,7 @@ RUN dnf -y install \
|
||||
glib2-static \
|
||||
glibc-devel \
|
||||
glibc-headers \
|
||||
gnome-desktop-testing \
|
||||
gnupg2 \
|
||||
gobject-introspection-devel \
|
||||
graphene-devel \
|
||||
@@ -72,14 +73,10 @@ RUN dnf -y install \
|
||||
mesa-dri-drivers \
|
||||
mesa-libEGL-devel \
|
||||
mesa-libGLES-devel \
|
||||
meson \
|
||||
mutter \
|
||||
ninja-build \
|
||||
pango-devel \
|
||||
pcre-devel \
|
||||
pcre-static \
|
||||
pipewire \
|
||||
pipewire-gstreamer \
|
||||
python3 \
|
||||
python3-docutils \
|
||||
python3-gobject \
|
||||
@@ -87,7 +84,6 @@ RUN dnf -y install \
|
||||
python3-markdown \
|
||||
python3-packaging \
|
||||
python3-pip \
|
||||
python3-pydbus \
|
||||
python3-pygments \
|
||||
python3-typogrify \
|
||||
python3-wheel \
|
||||
@@ -99,7 +95,6 @@ RUN dnf -y install \
|
||||
weston \
|
||||
weston-libs \
|
||||
which \
|
||||
wireplumber \
|
||||
xorg-x11-server-Xvfb \
|
||||
&& dnf clean all
|
||||
|
||||
|
@@ -20,7 +20,6 @@ flatpak build ${builddir} meson \
|
||||
-Dx11-backend=true \
|
||||
-Dwayland-backend=true \
|
||||
-Dbuild-tests=false \
|
||||
-Dbuild-testsuite=false \
|
||||
-Dbuild-examples=false \
|
||||
-Dintrospection=disabled \
|
||||
-Ddemos=true \
|
||||
|
@@ -138,8 +138,7 @@ if [ $run == 1 ]; then
|
||||
echo -e "\e[1;32mRUNNING\e[0m: ${base} as ${TAG}"
|
||||
${CMD} run \
|
||||
--rm \
|
||||
--userns=keep-id \
|
||||
--volume "$(pwd)/..:/home/user/app:rw,z" \
|
||||
--volume "$(pwd)/..:/home/user/app" \
|
||||
--workdir "/home/user/app" \
|
||||
--tty \
|
||||
--interactive "${TAG}" \
|
||||
|
@@ -6,7 +6,6 @@ set +e
|
||||
srcdir=$( pwd )
|
||||
builddir=$1
|
||||
backend=$2
|
||||
multiplier=${MESON_TEST_TIMEOUT_MULTIPLIER:-1}
|
||||
|
||||
# Ignore memory leaks lower in dependencies
|
||||
export LSAN_OPTIONS=suppressions=$srcdir/lsan.supp:print_suppressions=0:verbosity=1:log_threads=1
|
||||
@@ -16,8 +15,7 @@ case "${backend}" in
|
||||
x11)
|
||||
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -28,9 +26,17 @@ case "${backend}" in
|
||||
# Store the exit code for the CI run, but always
|
||||
# generate the reports
|
||||
exit_code=$?
|
||||
|
||||
xvfb-run -a -s "-screen 0 1024x768x24 -noreset" \
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend}_unstable \
|
||||
--suite=flaky \
|
||||
--suite=failing || true
|
||||
;;
|
||||
|
||||
wayland*)
|
||||
wayland)
|
||||
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
||||
|
||||
weston --backend=headless-backend.so --socket=wayland-5 --idle-time=0 &
|
||||
@@ -38,17 +44,49 @@ case "${backend}" in
|
||||
export WAYLAND_DISPLAY=wayland-5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
--no-suite=failing \
|
||||
--no-suite=flaky \
|
||||
--no-suite=${backend}_failing \
|
||||
--no-suite=gsk-compare-broadway
|
||||
exit_code=$?
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend}_unstable \
|
||||
--suite=flaky \
|
||||
--suite=failing || true
|
||||
|
||||
kill ${compositor}
|
||||
;;
|
||||
|
||||
waylandgles)
|
||||
export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
||||
|
||||
weston --backend=headless-backend.so --socket=wayland-6 --idle-time=0 &
|
||||
compositor=$!
|
||||
export WAYLAND_DISPLAY=wayland-6
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
--no-suite=failing \
|
||||
--no-suite=flaky \
|
||||
--no-suite=gsk-compare-broadway
|
||||
exit_code=$?
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend}_unstable \
|
||||
--suite=flaky \
|
||||
--suite=failing || true
|
||||
|
||||
kill ${compositor}
|
||||
;;
|
||||
|
||||
@@ -60,8 +98,7 @@ case "${backend}" in
|
||||
export BROADWAY_DISPLAY=:5
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--quiet \
|
||||
--timeout-multiplier "${multiplier}" \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend} \
|
||||
--suite=gtk \
|
||||
@@ -69,6 +106,16 @@ case "${backend}" in
|
||||
--no-suite=flaky \
|
||||
--no-suite=gsk-compare-opengl
|
||||
|
||||
# don't let Broadway failures fail the run, for now
|
||||
exit_code=0
|
||||
|
||||
meson test -C ${builddir} \
|
||||
--timeout-multiplier "${MESON_TEST_TIMEOUT_MULTIPLIER}" \
|
||||
--print-errorlogs \
|
||||
--setup=${backend}_unstable \
|
||||
--suite=flaky \
|
||||
--suite=failing || true
|
||||
|
||||
kill ${server}
|
||||
;;
|
||||
|
||||
@@ -81,19 +128,20 @@ esac
|
||||
|
||||
cd ${builddir}
|
||||
|
||||
$srcdir/.gitlab-ci/meson-junit-report.py \
|
||||
for suffix in "" "_unstable"; do
|
||||
$srcdir/.gitlab-ci/meson-junit-report.py \
|
||||
--project-name=gtk \
|
||||
--backend="${backend}" \
|
||||
--backend="${backend}${suffix}" \
|
||||
--job-id="${CI_JOB_NAME}" \
|
||||
--output="report-${backend}.xml" \
|
||||
"meson-logs/testlog-${backend}.json"
|
||||
|
||||
$srcdir/.gitlab-ci/meson-html-report.py \
|
||||
--output="report-${backend}${suffix}.xml" \
|
||||
"meson-logs/testlog-${backend}${suffix}.json"
|
||||
$srcdir/.gitlab-ci/meson-html-report.py \
|
||||
--project-name=gtk \
|
||||
--backend="${backend}" \
|
||||
--backend="${backend}${suffix}" \
|
||||
--job-id="${CI_JOB_NAME}" \
|
||||
--reftest-output-dir="testsuite/reftests/output/${backend}" \
|
||||
--output="report-${backend}.html" \
|
||||
"meson-logs/testlog-${backend}.json"
|
||||
--reftest-output-dir="testsuite/reftests/output/${backend}${suffix}" \
|
||||
--output="report-${backend}${suffix}.html" \
|
||||
"meson-logs/testlog-${backend}${suffix}.json"
|
||||
done
|
||||
|
||||
exit $exit_code
|
||||
|
341
NEWS
341
NEWS
@@ -1,342 +1,5 @@
|
||||
Overview of Changes in 4.11.3, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
* GtkGridView:
|
||||
- Respect css border-spacing
|
||||
- Don't leak the factories
|
||||
|
||||
* GtkListView:
|
||||
- Don't leak the factories
|
||||
|
||||
* GtkNotebook:
|
||||
- Make the pages model implement GtkSelectionModel
|
||||
|
||||
* GtkScrolledWindow:
|
||||
- Propagate child measure size whenever possible
|
||||
|
||||
* GtkPopoverMenu:
|
||||
- Avoid unnecessary left padding
|
||||
|
||||
* Css:
|
||||
- Add new binding-friendly css provider apis
|
||||
|
||||
* Theme:
|
||||
- Show focus in the shortcuts window
|
||||
|
||||
* Tests:
|
||||
- Improve test coverage
|
||||
|
||||
* Wayland:
|
||||
- Make exporting surface handles more flexible
|
||||
|
||||
* Build:
|
||||
- Some build options have been renamed:
|
||||
demos -> build-demos
|
||||
profile -> demo-profile
|
||||
The old names still work
|
||||
|
||||
* Deprecations:
|
||||
- gtk_css_provider_load_from_data
|
||||
- gdk_wayland_toplevel_unexport_handle
|
||||
- gdk_pixbuf_get_from_surface
|
||||
- gdk_pixbuf_get_from_texture
|
||||
- gtk_image_new_from_pixbuf
|
||||
- gtk_image_set_from_pixbuf
|
||||
- gtk_picture_new_for_pixbuf
|
||||
- gtk_picture_set_pixbuf
|
||||
|
||||
* Translation updates:
|
||||
Basque
|
||||
Catalan
|
||||
Russian
|
||||
|
||||
|
||||
Overview of Changes in 4.11.2, 09-05-2023
|
||||
=========================================
|
||||
|
||||
* GtkGLArea:
|
||||
- Add an allowed-apis property
|
||||
|
||||
* GtkListBox:
|
||||
- Fix a problem with gtk_list_box_remove_all
|
||||
|
||||
* Add the GtkSectionModel interface, and implement it in most
|
||||
of our list models
|
||||
|
||||
* GtkListView:
|
||||
- Support displaying sections
|
||||
|
||||
* GtkCenterBox:
|
||||
- Add a shrink-center-last property
|
||||
|
||||
* GtkButton, GtkMenuButton:
|
||||
- Add a can-shrink property
|
||||
|
||||
* GtkPopover:
|
||||
- Fix problems with grabs
|
||||
|
||||
* GtkFileChooser:
|
||||
- Fix a problem with removing files
|
||||
- Make the date, time and location columns work
|
||||
- Fix filtering in the save entry popup
|
||||
- A few memory leak fixes
|
||||
- Handle webdav in the pathbar
|
||||
|
||||
* GtkBox:
|
||||
- Support baselines in vertical orientation with GtkBox:baseline-child
|
||||
|
||||
* Dialogs:
|
||||
- Destroy windows promptly when the async callback finishes
|
||||
- Detect absence of the OpenURI portal and fall back
|
||||
|
||||
* Theme:
|
||||
- Add explicit style classes to a number of widgets
|
||||
- Fix some contrast issues in the dark theme
|
||||
|
||||
* Accessibility:
|
||||
- Fix alert dialogs in the a11y tree
|
||||
- Improve accessibility of GtkShortcutsWindow
|
||||
|
||||
* Layout:
|
||||
- Some fixes to baseline alignment
|
||||
- Separate GTK_ALIGN_BASELINE_CENTER and _FILL
|
||||
|
||||
* CSS:
|
||||
- Fix a crash with color transitions
|
||||
|
||||
* GSK:
|
||||
- Fix problems with negative scales
|
||||
- Improve scaling of offscreens for (cross-fades, masks, blends)
|
||||
|
||||
* GL:
|
||||
- Add GdkGLTextureBuilder, a more flexible api for creating textures
|
||||
- Support setting update regions for GL textures
|
||||
- Ensure that we work with GLES 2
|
||||
|
||||
* Vulkan:
|
||||
- More fixes to the experimental Vulkan renderer
|
||||
- Rework glyph caching
|
||||
|
||||
* Wayland:
|
||||
- Don't destroy wl_surfaces on hide
|
||||
- Plug leaks of compositor-side resources
|
||||
|
||||
* X11:
|
||||
- Fix artifacts in gnome-shell frame decorations
|
||||
|
||||
* Windows:
|
||||
- Fix GL context initialization
|
||||
|
||||
* Inspector:
|
||||
- Improve the action list
|
||||
- Improve the accessibility pane
|
||||
- Fix a crash
|
||||
|
||||
* Tools:
|
||||
- gtk4-node-editor: Improve scaling
|
||||
- gtk4-node-editor: Preserve aspect ratio of textures
|
||||
- gtk4-node-editor: Add some smarter editing
|
||||
- gtk4-demo: Make the stylus demo work with mice
|
||||
|
||||
* Deprecations:
|
||||
- gtk_widget_get_allocated_width/height/baseline
|
||||
- GTK_ALIGN_BASELINE
|
||||
|
||||
* Translation updates
|
||||
Bulgarian
|
||||
Chinese (China)
|
||||
Friulian
|
||||
Galician
|
||||
Hebrew
|
||||
Persian
|
||||
Polish
|
||||
Portuguese
|
||||
`Russian
|
||||
Turkish
|
||||
|
||||
|
||||
Overview of Changes in 4.11.1, 03-04-2023
|
||||
=========================================
|
||||
|
||||
* GtkLabel, GtkLinkButton:
|
||||
- Make file:// uris work again
|
||||
|
||||
* GtkListView/GtkColumnView/GtkGridView:
|
||||
- Fix clipping issues
|
||||
- Handle focus movement better
|
||||
- Introduce ::tab-behavior properties
|
||||
- Introduce GtkListItem::focusable
|
||||
- Introduce GtkColumnViewCell
|
||||
- Introduce row factories in GtkColumnView
|
||||
- Make list grid and column views inert when not rendering
|
||||
|
||||
* Drag-and-Drop:
|
||||
- Support resizing drag surfaces, using the new
|
||||
GdkDragSurface::compute-size signal
|
||||
|
||||
* Theme:
|
||||
- Port .boxed-list style from Adwaita
|
||||
- Make insensitive pictures appear grayed out
|
||||
|
||||
* Accessibility:
|
||||
- Fix memory leaks
|
||||
- Fix a crash
|
||||
|
||||
* GDK:
|
||||
- Add gdk_surface_get_scale to get the fractional scale
|
||||
- Use fractional scales on Wayland with cairo
|
||||
- Use fractional scales on Wayland with GL if GDK_DEBUG=gl-fractional
|
||||
is set. This support is still experimental
|
||||
|
||||
* GSK:
|
||||
- Allow limiting texture sizes with GSK_MAX_TEXTURE_SIZE
|
||||
- Use samplers for GL texture filtering
|
||||
- Fix problems with texture slicing
|
||||
- Avoid re-uploading textures when possible
|
||||
- Use mipmaps when it is beneficial
|
||||
|
||||
* Wayland:
|
||||
- Fix handling of Drag hotspots
|
||||
- Fix a crash with cursor size 0
|
||||
- Support absolute paths in WAYLAND_DISPLAY
|
||||
- Use the fractional scale protocol
|
||||
- Use a viewporter to set buffer scale
|
||||
|
||||
* Windows:
|
||||
- Fix problems with WGL
|
||||
|
||||
* Vulkan:
|
||||
- Some fixes to the experimental Vulkan renderer
|
||||
- Support fractional scaling
|
||||
|
||||
* Debugging:
|
||||
- Show more Wayland-specific information in the inspector
|
||||
|
||||
* Deprecations:
|
||||
- gtk_widget_translate_coordinates
|
||||
- gdk_surface_create_similar_surface
|
||||
|
||||
* Documentation:
|
||||
- Add a section on coordinate systems
|
||||
|
||||
* Build:
|
||||
- Require wayland-protocols 1.31
|
||||
|
||||
* Translation updates
|
||||
- British English
|
||||
- Bulgarian
|
||||
- Chinese (China)
|
||||
- Dutch
|
||||
- French
|
||||
- Persian
|
||||
- Russian
|
||||
|
||||
|
||||
Overview of Changes in 4.10.1, 14-03-2023
|
||||
=========================================
|
||||
|
||||
* GtkFileChooser
|
||||
- Improve search performance
|
||||
- Be safe against pathless files
|
||||
- Fix memory leaks
|
||||
- Only show local files in recent files
|
||||
- Show most recent files first
|
||||
- Make files non-selectable in selet_folder mode
|
||||
|
||||
* GtkListView / GtkColumnView / GtkGridView
|
||||
- Fix scrolling problems
|
||||
- Support CSS border-spacing
|
||||
|
||||
* GtkComboBox
|
||||
- Fix a size allocation problem
|
||||
|
||||
* gtk
|
||||
- Size allocation fixes
|
||||
|
||||
* Accessibility
|
||||
- Miscellaneous property fixes and improvements
|
||||
|
||||
* Wayland
|
||||
- Fix an ordering problem in surface disposal
|
||||
|
||||
* Windows
|
||||
- Fix Visual Studio build with older GLib
|
||||
|
||||
* Translation updates
|
||||
Basque
|
||||
Bulgarian
|
||||
Catalan
|
||||
Czech
|
||||
Danish
|
||||
Finnish
|
||||
Friulian
|
||||
Galician
|
||||
Georgian
|
||||
Hungarian
|
||||
Lithuanian
|
||||
Polish
|
||||
Portuguese
|
||||
Swedish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
|
||||
Overview of Changes in 4.10.0, 04-03-2023
|
||||
=========================================
|
||||
|
||||
* GtkTextView
|
||||
- Document hanging indentation
|
||||
|
||||
* GtkListView
|
||||
- Fix a size allocation problem
|
||||
|
||||
* GtkFileChooser
|
||||
- Fix paned behavior
|
||||
- Fix a crash
|
||||
|
||||
* GtkText
|
||||
- Fix various problems with undo
|
||||
|
||||
* Accessibility
|
||||
- Make some getters transfer-full
|
||||
- Allow setting accessible parents and siblings
|
||||
- Add a role for toggle buttons
|
||||
- Miscellaneous property fixes and improvements
|
||||
|
||||
* gtk
|
||||
- Improve the handling resize-during-size-allocate
|
||||
|
||||
* gdk
|
||||
- Introduce GdkTextureDownloader and use it
|
||||
- Make gdk_texture_get_format public
|
||||
|
||||
* gsk
|
||||
- Make mask nodes more versatile
|
||||
- Improve the GL implementation for texture scale nodes
|
||||
|
||||
* X11
|
||||
- Fix key handling during DND
|
||||
|
||||
* Tools
|
||||
- gtk-builder-tool: Try harder to handle templates
|
||||
- gtk-builder-tool: Prefer properties over <child>
|
||||
|
||||
* Translation updates
|
||||
Basque
|
||||
Belarusian
|
||||
Bulgarian
|
||||
Indonesian
|
||||
Galician
|
||||
Georgian
|
||||
German
|
||||
Hebrew
|
||||
Lithuanian
|
||||
Portuguese
|
||||
Spanish
|
||||
Swedish
|
||||
Turkish
|
||||
Ukrainian
|
||||
|
||||
Overview of Changes in 4.9.5, xx-xx-xxxx
|
||||
========================================
|
||||
|
||||
Overview of Changes in 4.9.4, 12-02-2023
|
||||
========================================
|
||||
|
17
README.md
17
README.md
@@ -116,12 +116,19 @@ docs/reference/gtk/html/gtk-building.html
|
||||
|
||||
Or [online](https://docs.gtk.org/gtk4/building.html)
|
||||
|
||||
Building from git
|
||||
-----------------
|
||||
Default branch renamed to `main`
|
||||
--------------------------------
|
||||
|
||||
The GTK sources are hosted on [gitlab.gnome.org](http://gitlab.gnome.org). The main
|
||||
development branch is called `main`, and stable branches are named after their minor
|
||||
version, for example `gtk-4-10`.
|
||||
The default development branch of GTK has been renamed to `main`.
|
||||
To update your local checkout, use:
|
||||
```sh
|
||||
git checkout master
|
||||
git branch -m master main
|
||||
git fetch
|
||||
git branch --unset-upstream
|
||||
git branch -u origin/main
|
||||
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
|
||||
```
|
||||
|
||||
How to report bugs
|
||||
------------------
|
||||
|
@@ -187,7 +187,7 @@
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Ddemo-profile=devel"
|
||||
"-Dprofile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
|
@@ -116,7 +116,7 @@
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Ddemo-profile=devel"
|
||||
"-Dprofile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
|
@@ -116,7 +116,7 @@
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Ddemo-profile=devel"
|
||||
"-Dprofile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
|
@@ -116,7 +116,7 @@
|
||||
"--libdir=/app/lib",
|
||||
"-Dvulkan=disabled",
|
||||
"-Dbuildtype=debugoptimized",
|
||||
"-Ddemo-profile=devel"
|
||||
"-Dprofile=devel"
|
||||
],
|
||||
"sources" : [
|
||||
{
|
||||
|
@@ -1,201 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2022 Collabora Inc.
|
||||
# 2023 Emmanuele Bassi
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
#
|
||||
# Original author: Xavier Claessens <xclaesse@gmail.com>
|
||||
|
||||
import argparse
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Disable line length warnings as wrapping the C code templates would be hard
|
||||
# flake8: noqa: E501
|
||||
|
||||
|
||||
def gen_versions_macros(args, current_major_version, current_minor_version, current_micro_version):
|
||||
with args.out_path.open("w", encoding="utf-8") as ofile, args.in_path.open(
|
||||
"r", encoding="utf-8"
|
||||
) as ifile:
|
||||
for line in ifile.readlines():
|
||||
if "@GDK_VERSIONS@" in line:
|
||||
ofile.write(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
/**
|
||||
* GDK_MAJOR_VERSION:
|
||||
*
|
||||
* The major version component of the library's version, e.g. "1" for "1.2.3".
|
||||
*/
|
||||
#define GDK_MAJOR_VERSION ({current_major_version})
|
||||
|
||||
/**
|
||||
* GDK_MINOR_VERSION:
|
||||
*
|
||||
* The minor version component of the library's version, e.g. "2" for "1.2.3".
|
||||
*/
|
||||
#define GDK_MINOR_VERSION ({current_minor_version})
|
||||
|
||||
/**
|
||||
* GDK_MICRO_VERSION:
|
||||
*
|
||||
* The micro version component of the library's version, e.g. "3" for "1.2.3".
|
||||
*/
|
||||
#define GDK_MICRO_VERSION ({current_micro_version})
|
||||
"""
|
||||
)
|
||||
)
|
||||
for minor in range(0, current_minor_version + 2, 2):
|
||||
ofile.write(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
/**
|
||||
* GDK_VERSION_{current_major_version}_{minor}:
|
||||
*
|
||||
* A macro that evaluates to the {current_major_version}.{minor} version of GTK, in a format
|
||||
* that can be used by the C pre-processor.
|
||||
*
|
||||
* Since: {current_major_version}.{minor}
|
||||
*/
|
||||
#define GDK_VERSION_{current_major_version}_{minor} (G_ENCODE_VERSION ({current_major_version}, {minor}))
|
||||
"""
|
||||
)
|
||||
)
|
||||
else:
|
||||
ofile.write(line)
|
||||
|
||||
|
||||
def gen_visibility_macros(args, current_major_version, current_minor_version, current_micro_version):
|
||||
"""
|
||||
Generates a set of macros for each minor stable version of GTK
|
||||
|
||||
- GDK_DEPRECATED
|
||||
- GDK_DEPRECATED_IN_…
|
||||
- GDK_DEPRECATED_MACRO_IN_…
|
||||
- GDK_DEPRECATED_ENUMERATOR_IN_…
|
||||
- GDK_DEPRECATED_TYPE_IN_…
|
||||
|
||||
- GDK_AVAILABLE_IN_ALL
|
||||
- GDK_AVAILABLE_IN_…
|
||||
- GDK_AVAILABLE_STATIC_INLINE_IN_…
|
||||
- GDK_AVAILABLE_MACRO_IN_…
|
||||
- GDK_AVAILABLE_ENUMERATOR_IN_…
|
||||
- GDK_AVAILABLE_TYPE_IN_…
|
||||
|
||||
- GDK_UNAVAILABLE(maj,min)
|
||||
- GDK_UNAVAILABLE_STATIC_INLINE(maj,min)
|
||||
"""
|
||||
|
||||
ns = args.namespace
|
||||
with args.out_path.open("w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
textwrap.dedent(
|
||||
f"""\
|
||||
#pragma once
|
||||
|
||||
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined({ns}_STATIC_COMPILATION)
|
||||
# define _{ns}_EXPORT __declspec(dllexport)
|
||||
# define _{ns}_IMPORT __declspec(dllimport)
|
||||
#elif __GNUC__ >= 4
|
||||
# define _{ns}_EXPORT __attribute__((visibility("default")))
|
||||
# define _{ns}_IMPORT
|
||||
#else
|
||||
# define _{ns}_EXPORT
|
||||
# define _{ns}_IMPORT
|
||||
#endif
|
||||
#ifdef GTK_COMPILATION
|
||||
# define _{ns}_API _{ns}_EXPORT
|
||||
#else
|
||||
# define _{ns}_API _{ns}_IMPORT
|
||||
#endif
|
||||
|
||||
#define _{ns}_EXTERN _{ns}_API extern
|
||||
|
||||
#define {ns}_VAR _{ns}_EXTERN
|
||||
#define {ns}_AVAILABLE_IN_ALL _{ns}_EXTERN
|
||||
|
||||
#ifdef GDK_DISABLE_DEPRECATION_WARNINGS
|
||||
#define {ns}_DEPRECATED _{ns}_EXTERN
|
||||
#define {ns}_DEPRECATED_FOR(f) _{ns}_EXTERN
|
||||
#define {ns}_UNAVAILABLE(maj,min) _{ns}_EXTERN
|
||||
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min)
|
||||
#else
|
||||
#define {ns}_DEPRECATED G_DEPRECATED _{ns}_EXTERN
|
||||
#define {ns}_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _{ns}_EXTERN
|
||||
#define {ns}_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _{ns}_EXTERN
|
||||
#define {ns}_UNAVAILABLE_STATIC_INLINE(maj,min) G_UNAVAILABLE(maj,min)
|
||||
#endif
|
||||
"""
|
||||
)
|
||||
)
|
||||
for minor in range(0, current_minor_version + 2, 2):
|
||||
f.write(
|
||||
textwrap.dedent(
|
||||
f"""
|
||||
#if GDK_VERSION_MIN_REQUIRED >= GDK_VERSION_4_{minor}
|
||||
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} {ns}_DEPRECATED
|
||||
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) {ns}_DEPRECATED_FOR (f)
|
||||
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor} GDK_DEPRECATED_MACRO
|
||||
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_MACRO_FOR (f)
|
||||
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor} GDK_DEPRECATED_ENUMERATOR
|
||||
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_ENUMERATOR_FOR (f)
|
||||
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor} GDK_DEPRECATED_TYPE
|
||||
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f) GDK_DEPRECATED_TYPE_FOR (f)
|
||||
#else
|
||||
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor} _{ns}_EXTERN
|
||||
#define {ns}_DEPRECATED_IN_{current_major_version}_{minor}_FOR(f) _{ns}_EXTERN
|
||||
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}
|
||||
#define {ns}_DEPRECATED_MACRO_IN_{current_major_version}_{minor}_FOR(f)
|
||||
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}
|
||||
#define {ns}_DEPRECATED_ENUMERATOR_IN_{current_major_version}_{minor}_FOR(f)
|
||||
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}
|
||||
#define {ns}_DEPRECATED_TYPE_IN_{current_major_version}_{minor}_FOR(f)
|
||||
#endif
|
||||
|
||||
#if GDK_VERSION_MAX_ALLOWED < GDK_VERSION_{current_major_version}_{minor}
|
||||
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} {ns}_UNAVAILABLE ({current_major_version}, {minor})
|
||||
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_STATIC_INLINE ({current_major_version}, {minor})
|
||||
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_MACRO ({current_major_version}, {minor})
|
||||
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_ENUMERATOR ({current_major_version}, {minor})
|
||||
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor} GDK_UNAVAILABLE_TYPE ({current_major_version}, {minor})
|
||||
#else
|
||||
#define {ns}_AVAILABLE_IN_{current_major_version}_{minor} _{ns}_EXTERN
|
||||
#define {ns}_AVAILABLE_STATIC_INLINE_IN_{current_major_version}_{minor}
|
||||
#define {ns}_AVAILABLE_MACRO_IN_{current_major_version}_{minor}
|
||||
#define {ns}_AVAILABLE_ENUMERATOR_IN_{current_major_version}_{minor}
|
||||
#define {ns}_AVAILABLE_TYPE_IN_{current_major_version}_{minor}
|
||||
#endif
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("gtk_version", help="Current GLib version")
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
versions_parser = subparsers.add_parser(
|
||||
"versions-macros", help="Generate versions macros"
|
||||
)
|
||||
versions_parser.add_argument("in_path", help="input file", type=Path)
|
||||
versions_parser.add_argument("out_path", help="output file", type=Path)
|
||||
versions_parser.set_defaults(func=gen_versions_macros)
|
||||
|
||||
visibility_parser = subparsers.add_parser(
|
||||
"visibility-macros", help="Generate visibility macros"
|
||||
)
|
||||
visibility_parser.add_argument("namespace", help="Macro namespace")
|
||||
visibility_parser.add_argument("out_path", help="output file", type=Path)
|
||||
visibility_parser.set_defaults(func=gen_visibility_macros)
|
||||
|
||||
args = parser.parse_args()
|
||||
version = [int(i) for i in args.gtk_version.split(".")]
|
||||
args.func(args, version[0], version[1], version[2])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -9,7 +9,7 @@ constraint_editor_sources = [
|
||||
|
||||
constraint_editor_resources = gnome.compile_resources('constraint_editor_resources',
|
||||
'constraint-editor.gresource.xml',
|
||||
source_dir: meson.current_source_dir(),
|
||||
source_dir: '.',
|
||||
)
|
||||
|
||||
executable('gtk4-constraint-editor',
|
||||
|
@@ -116,8 +116,7 @@ effective_align (GtkAlign align,
|
||||
return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
|
||||
case GTK_ALIGN_FILL:
|
||||
case GTK_ALIGN_CENTER:
|
||||
case GTK_ALIGN_BASELINE_FILL:
|
||||
case GTK_ALIGN_BASELINE_CENTER:
|
||||
case GTK_ALIGN_BASELINE:
|
||||
default:
|
||||
return align;
|
||||
}
|
||||
@@ -259,8 +258,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
|
||||
case GTK_ALIGN_END:
|
||||
alloc->x += width - alloc->width;
|
||||
break;
|
||||
case GTK_ALIGN_BASELINE_FILL:
|
||||
case GTK_ALIGN_BASELINE_CENTER:
|
||||
case GTK_ALIGN_BASELINE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -283,8 +281,7 @@ blur_overlay_get_child_position (BlurOverlay *overlay,
|
||||
case GTK_ALIGN_END:
|
||||
alloc->y += height - alloc->height;
|
||||
break;
|
||||
case GTK_ALIGN_BASELINE_FILL:
|
||||
case GTK_ALIGN_BASELINE_CENTER:
|
||||
case GTK_ALIGN_BASELINE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
@@ -300,13 +297,12 @@ blur_overlay_snapshot (GtkWidget *widget,
|
||||
GtkWidget *main_widget;
|
||||
GskRenderNode *main_widget_node = NULL;
|
||||
GtkWidget *child;
|
||||
int width, height;
|
||||
GtkAllocation main_alloc;
|
||||
cairo_region_t *clip = NULL;
|
||||
int i;
|
||||
|
||||
main_widget = BLUR_OVERLAY (widget)->main_widget;
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
gtk_widget_get_allocation (widget, &main_alloc);
|
||||
|
||||
for (child = gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
@@ -319,7 +315,7 @@ blur_overlay_snapshot (GtkWidget *widget,
|
||||
|
||||
if (blur > 0)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkAllocation alloc;
|
||||
graphene_rect_t bounds;
|
||||
|
||||
if (main_widget_node == NULL)
|
||||
@@ -331,8 +327,8 @@ blur_overlay_snapshot (GtkWidget *widget,
|
||||
main_widget_node = gtk_snapshot_free_to_node (child_snapshot);
|
||||
}
|
||||
|
||||
if (!gtk_widget_compute_bounds (child, gtk_widget_get_parent (child), &bounds))
|
||||
graphene_rect_init (&bounds, 0, 0, 0, 0);
|
||||
gtk_widget_get_allocation (child, &alloc);
|
||||
graphene_rect_init (&bounds, alloc.x, alloc.y, alloc.width, alloc.height);
|
||||
gtk_snapshot_push_blur (snapshot, blur);
|
||||
gtk_snapshot_push_clip (snapshot, &bounds);
|
||||
gtk_snapshot_append_node (snapshot, main_widget_node);
|
||||
@@ -341,17 +337,13 @@ blur_overlay_snapshot (GtkWidget *widget,
|
||||
|
||||
if (clip == NULL)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
rect.width = main_alloc.width;
|
||||
rect.height = main_alloc.height;
|
||||
clip = cairo_region_create_rectangle (&rect);
|
||||
}
|
||||
|
||||
rect.x = floor (bounds.origin.x);
|
||||
rect.y = floor (bounds.origin.y);
|
||||
rect.width = ceil (bounds.origin.x + bounds.size.width - rect.x);
|
||||
rect.height = ceil (bounds.origin.y + bounds.size.height - rect.y);
|
||||
cairo_region_subtract_rectangle (clip, &rect);
|
||||
cairo_region_subtract_rectangle (clip, (cairo_rectangle_int_t *)&alloc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,11 +51,15 @@ struct _BlurOverlayClass
|
||||
GtkAllocation *allocation);
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType blur_overlay_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkWidget *blur_overlay_new (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void blur_overlay_add_overlay (BlurOverlay *overlay,
|
||||
GtkWidget *widget,
|
||||
double blur);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void blur_overlay_set_child (BlurOverlay *overlay,
|
||||
GtkWidget *widget);
|
||||
|
||||
|
@@ -50,7 +50,7 @@ update_css_for_blend_mode (GtkCssProvider *provider,
|
||||
blend_mode,
|
||||
blend_mode);
|
||||
|
||||
gtk_css_provider_load_from_string (provider, css);
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_free (css);
|
||||
|
@@ -43,7 +43,7 @@
|
||||
<file>cssview.css</file>
|
||||
<file>reset.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_selections">
|
||||
<gresource prefix="/dropdown">
|
||||
<file>suggestionentry.h</file>
|
||||
<file>suggestionentry.c</file>
|
||||
<file>suggestionentry.css</file>
|
||||
@@ -195,9 +195,6 @@
|
||||
<gresource prefix="/listview_settings">
|
||||
<file>listview_settings.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_settings2">
|
||||
<file>listview_settings2.ui</file>
|
||||
</gresource>
|
||||
<gresource prefix="/listview_ucd_data/">
|
||||
<file>ucdnames.data</file>
|
||||
</gresource>
|
||||
@@ -277,6 +274,7 @@
|
||||
<file>cursors.c</file>
|
||||
<file>dialog.c</file>
|
||||
<file>drawingarea.c</file>
|
||||
<file>dropdown.c</file>
|
||||
<file>dnd.c</file>
|
||||
<file>editable_cells.c</file>
|
||||
<file>entry_completion.c</file>
|
||||
@@ -300,7 +298,6 @@
|
||||
<file>iconscroll.c</file>
|
||||
<file>iconview.c</file>
|
||||
<file>iconview_edit.c</file>
|
||||
<file>image_scaling.c</file>
|
||||
<file>images.c</file>
|
||||
<file>infobar.c</file>
|
||||
<file>layoutmanager.c</file>
|
||||
@@ -313,9 +310,7 @@
|
||||
<file>listview_clocks.c</file>
|
||||
<file>listview_filebrowser.c</file>
|
||||
<file>listview_minesweeper.c</file>
|
||||
<file>listview_selections.c</file>
|
||||
<file>listview_settings.c</file>
|
||||
<file>listview_settings2.c</file>
|
||||
<file>listview_ucd.c</file>
|
||||
<file>listview_weather.c</file>
|
||||
<file>listview_words.c</file>
|
||||
@@ -323,6 +318,7 @@
|
||||
<file>main.c</file>
|
||||
<file>markup.c</file>
|
||||
<file>mask.c</file>
|
||||
<file>menu.c</file>
|
||||
<file>overlay.c</file>
|
||||
<file>overlay_decorative.c</file>
|
||||
<file>paint.c</file>
|
||||
|
@@ -5,8 +5,7 @@ enum
|
||||
{
|
||||
PROP_TEXTURE = 1,
|
||||
PROP_FILTER,
|
||||
PROP_SCALE,
|
||||
PROP_ANGLE,
|
||||
PROP_SCALE
|
||||
};
|
||||
|
||||
struct _Demo3Widget
|
||||
@@ -15,7 +14,6 @@ struct _Demo3Widget
|
||||
|
||||
GdkTexture *texture;
|
||||
float scale;
|
||||
float angle;
|
||||
GskScalingFilter filter;
|
||||
|
||||
GtkWidget *menu;
|
||||
@@ -28,85 +26,10 @@ struct _Demo3WidgetClass
|
||||
|
||||
G_DEFINE_TYPE (Demo3Widget, demo3_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
static gboolean
|
||||
query_tooltip (GtkWidget *widget,
|
||||
int x,
|
||||
int y,
|
||||
gboolean keyboard_mode,
|
||||
GtkTooltip *tooltip,
|
||||
gpointer data)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
GtkWidget *grid;
|
||||
GtkWidget *label;
|
||||
char *s, *s2;
|
||||
const char *filter[] = { "Linear", "Nearest", "Trilinear" };
|
||||
int precision, l;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
|
||||
label = gtk_label_new ("Texture");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
|
||||
s = g_strdup_printf ("%d\342\200\206\303\227\342\200\206%d",
|
||||
gdk_texture_get_width (self->texture),
|
||||
gdk_texture_get_height (self->texture));
|
||||
label = gtk_label_new (s);
|
||||
g_free (s);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 1, 0, 1, 1);
|
||||
|
||||
label = gtk_label_new ("Rotation");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
||||
s = g_strdup_printf ("%.1f", self->angle);
|
||||
if (g_str_has_suffix (s, ".0"))
|
||||
s[strlen (s) - 2] = '\0';
|
||||
s2 = g_strconcat (s, "\302\260", NULL);
|
||||
label = gtk_label_new (s2);
|
||||
g_free (s2);
|
||||
g_free (s);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 1, 1, 1, 1);
|
||||
|
||||
label = gtk_label_new ("Scale");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 2, 1, 1);
|
||||
|
||||
precision = 1;
|
||||
do {
|
||||
s = g_strdup_printf ("%.*f", precision, self->scale);
|
||||
l = strlen (s) - 1;
|
||||
while (s[l] == '0')
|
||||
l--;
|
||||
if (s[l] == '.')
|
||||
s[l] = '\0';
|
||||
precision++;
|
||||
} while (strcmp (s, "0") == 0);
|
||||
|
||||
label = gtk_label_new (s);
|
||||
g_free (s);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 1, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("Filter");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 1, 1);
|
||||
label = gtk_label_new (filter[self->filter]);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 1);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 1, 3, 1, 1);
|
||||
|
||||
gtk_tooltip_set_custom (tooltip, grid);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_init (Demo3Widget *self)
|
||||
{
|
||||
self->scale = 1.f;
|
||||
self->angle = 0.f;
|
||||
self->filter = GSK_SCALING_FILTER_LINEAR;
|
||||
gtk_widget_init_template (GTK_WIDGET (self));
|
||||
}
|
||||
@@ -129,35 +52,26 @@ demo3_widget_snapshot (GtkWidget *widget,
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int x, y, width, height;
|
||||
double w, h, w2, h2;
|
||||
double w, h;
|
||||
GskRenderNode *node;
|
||||
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
|
||||
w2 = w = self->scale * gdk_texture_get_width (self->texture);
|
||||
h2 = h = self->scale * gdk_texture_get_height (self->texture);
|
||||
w = self->scale * gdk_texture_get_width (self->texture);
|
||||
h = self->scale * gdk_texture_get_height (self->texture);
|
||||
|
||||
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
|
||||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
|
||||
{
|
||||
double s = w2;
|
||||
w2 = h2;
|
||||
h2 = s;
|
||||
}
|
||||
|
||||
x = (width - ceil (w2)) / 2;
|
||||
y = (height - ceil (h2)) / 2;
|
||||
x = MAX (0, (width - ceil (w)) / 2);
|
||||
y = MAX (0, (height - ceil (h)) / 2);
|
||||
|
||||
gtk_snapshot_push_clip (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
gtk_snapshot_save (snapshot);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (x, y));
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (w2 / 2, h2 / 2));
|
||||
gtk_snapshot_rotate (snapshot, self->angle);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- w / 2, - h / 2));
|
||||
gtk_snapshot_append_scaled_texture (snapshot,
|
||||
self->texture,
|
||||
self->filter,
|
||||
&GRAPHENE_RECT_INIT (0, 0, w, h));
|
||||
node = gsk_texture_scale_node_new (self->texture,
|
||||
&GRAPHENE_RECT_INIT (0, 0, w, h),
|
||||
self->filter);
|
||||
gtk_snapshot_append_node (snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
gtk_snapshot_restore (snapshot);
|
||||
gtk_snapshot_pop (snapshot);
|
||||
}
|
||||
@@ -172,26 +86,14 @@ demo3_widget_measure (GtkWidget *widget,
|
||||
int *natural_baseline)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int width, height;
|
||||
int size;
|
||||
|
||||
width = gdk_texture_get_width (self->texture);
|
||||
height = gdk_texture_get_height (self->texture);
|
||||
|
||||
if (G_APPROX_VALUE (self->angle, 90.f, FLT_EPSILON) ||
|
||||
G_APPROX_VALUE (self->angle, 270.f, FLT_EPSILON))
|
||||
{
|
||||
int s = width;
|
||||
width = height;
|
||||
height = s;
|
||||
}
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
size = width;
|
||||
size = gdk_texture_get_width (self->texture);
|
||||
else
|
||||
size = height;
|
||||
size = gdk_texture_get_height (self->texture);
|
||||
|
||||
*minimum = *natural = (int) ceil (self->scale * size);
|
||||
*minimum = *natural = self->scale * size;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -209,8 +111,6 @@ demo3_widget_size_allocate (GtkWidget *widget,
|
||||
gtk_popover_present (GTK_POPOVER (self->menu));
|
||||
}
|
||||
|
||||
static void update_actions (Demo3Widget *self);
|
||||
|
||||
static void
|
||||
demo3_widget_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -224,24 +124,11 @@ demo3_widget_set_property (GObject *object,
|
||||
case PROP_TEXTURE:
|
||||
g_clear_object (&self->texture);
|
||||
self->texture = g_value_dup_object (value);
|
||||
self->scale = 1.f;
|
||||
self->angle = 0.f;
|
||||
self->filter = GSK_SCALING_FILTER_LINEAR;
|
||||
update_actions (self);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
g_object_notify (object, "scale");
|
||||
g_object_notify (object, "angle");
|
||||
g_object_notify (object, "filter");
|
||||
break;
|
||||
|
||||
case PROP_SCALE:
|
||||
self->scale = g_value_get_float (value);
|
||||
update_actions (self);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
case PROP_ANGLE:
|
||||
self->angle = fmodf (g_value_get_float (value), 360.f);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (object));
|
||||
break;
|
||||
|
||||
@@ -274,10 +161,6 @@ demo3_widget_get_property (GObject *object,
|
||||
g_value_set_float (value, self->scale);
|
||||
break;
|
||||
|
||||
case PROP_ANGLE:
|
||||
g_value_set_float (value, self->angle);
|
||||
break;
|
||||
|
||||
case PROP_FILTER:
|
||||
g_value_set_enum (value, self->filter);
|
||||
break;
|
||||
@@ -303,14 +186,6 @@ pressed_cb (GtkGestureClick *gesture,
|
||||
gtk_popover_popup (GTK_POPOVER (self->menu));
|
||||
}
|
||||
|
||||
static void
|
||||
update_actions (Demo3Widget *self)
|
||||
{
|
||||
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.in", self->scale < 1024.);
|
||||
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.out", self->scale > 1./1024.);
|
||||
gtk_widget_action_set_enabled (GTK_WIDGET (self), "zoom.reset", self->scale != 1.);
|
||||
}
|
||||
|
||||
static void
|
||||
zoom_cb (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
@@ -320,30 +195,19 @@ zoom_cb (GtkWidget *widget,
|
||||
float scale;
|
||||
|
||||
if (g_str_equal (action_name, "zoom.in"))
|
||||
scale = MIN (1024., self->scale * M_SQRT2);
|
||||
scale = MIN (10, self->scale * M_SQRT2);
|
||||
else if (g_str_equal (action_name, "zoom.out"))
|
||||
scale = MAX (1./1024., self->scale / M_SQRT2);
|
||||
else if (g_str_equal (action_name, "zoom.reset"))
|
||||
scale = 1.0;
|
||||
scale = MAX (0.01, self->scale / M_SQRT2);
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
scale = 1.0;
|
||||
|
||||
gtk_widget_action_set_enabled (widget, "zoom.in", scale < 10);
|
||||
gtk_widget_action_set_enabled (widget, "zoom.out", scale > 0.01);
|
||||
gtk_widget_action_set_enabled (widget, "zoom.reset", scale != 1);
|
||||
|
||||
g_object_set (widget, "scale", scale, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_cb (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
Demo3Widget *self = DEMO3_WIDGET (widget);
|
||||
int angle;
|
||||
|
||||
g_variant_get (parameter, "i", &angle);
|
||||
|
||||
g_object_set (widget, "angle", fmodf (self->angle + angle, 360.f), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
{
|
||||
@@ -365,12 +229,7 @@ demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
|
||||
g_object_class_install_property (object_class, PROP_SCALE,
|
||||
g_param_spec_float ("scale", NULL, NULL,
|
||||
1./1024., 1024., 1.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_ANGLE,
|
||||
g_param_spec_float ("angle", NULL, NULL,
|
||||
0.0, 360.0, 0.0,
|
||||
0.0, 10.0, 1.0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_FILTER,
|
||||
@@ -382,7 +241,6 @@ demo3_widget_class_init (Demo3WidgetClass *class)
|
||||
gtk_widget_class_install_action (widget_class, "zoom.in", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.out", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "zoom.reset", NULL, zoom_cb);
|
||||
gtk_widget_class_install_action (widget_class, "rotate", "i", rotate_cb);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/menu/demo3widget.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, Demo3Widget, menu);
|
||||
@@ -397,12 +255,7 @@ demo3_widget_new (const char *resource)
|
||||
|
||||
texture = gdk_texture_new_from_resource (resource);
|
||||
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET,
|
||||
"texture", texture,
|
||||
"has-tooltip", TRUE,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (self, "query-tooltip", G_CALLBACK (query_tooltip), NULL);
|
||||
self = g_object_new (DEMO3_TYPE_WIDGET, "texture", texture, NULL);
|
||||
|
||||
g_object_unref (texture);
|
||||
|
||||
|
@@ -12,11 +12,6 @@
|
||||
<attribute name="label">1∶1</attribute>
|
||||
<attribute name="action">zoom.reset</attribute>
|
||||
</item>
|
||||
<item>
|
||||
<attribute name="label">Rotate</attribute>
|
||||
<attribute name="action">rotate</attribute>
|
||||
<attribute name="target" type="i">90</attribute>
|
||||
</item>
|
||||
</menu>
|
||||
<template class="Demo3Widget">
|
||||
<child>
|
||||
|
@@ -70,7 +70,7 @@ set_color (CanvasItem *item,
|
||||
css = g_strdup_printf ("#%s { background: %s; }", name, str);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, css);
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider_for_display (gtk_widget_get_display (item->label), GTK_STYLE_PROVIDER (provider), 700);
|
||||
item->provider = GTK_STYLE_PROVIDER (provider);
|
||||
|
||||
@@ -109,21 +109,15 @@ static void
|
||||
apply_transform (CanvasItem *item)
|
||||
{
|
||||
GskTransform *transform;
|
||||
graphene_rect_t bounds;
|
||||
double x, y;
|
||||
|
||||
/* Add css padding and margin */
|
||||
if (!gtk_widget_compute_bounds (item->label, item->label, &bounds))
|
||||
return;
|
||||
|
||||
x = bounds.size.width / 2.;
|
||||
y = bounds.size.height / 2.;
|
||||
|
||||
item->r = sqrt (x * x + y * y);
|
||||
x = gtk_widget_get_allocated_width (item->label) / 2.0;
|
||||
y = gtk_widget_get_allocated_height (item->label) / 2.0;
|
||||
item->r = sqrt (x*x + y*y);
|
||||
|
||||
transform = gsk_transform_translate (NULL, &(graphene_point_t) { item->r, item->r });
|
||||
transform = gsk_transform_rotate (transform, item->angle + item->delta);
|
||||
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (-x, -y));
|
||||
transform = gsk_transform_translate (transform, &(graphene_point_t) { -x, -y });
|
||||
|
||||
gtk_fixed_set_child_transform (GTK_FIXED (item->fixed), item->label, transform);
|
||||
gsk_transform_unref (transform);
|
||||
@@ -330,7 +324,7 @@ canvas_item_start_editing (CanvasItem *item)
|
||||
GtkWidget *canvas = gtk_widget_get_parent (GTK_WIDGET (item));
|
||||
GtkWidget *entry;
|
||||
GtkWidget *scale;
|
||||
graphene_point_t p;
|
||||
double x, y;
|
||||
|
||||
if (item->editor)
|
||||
return;
|
||||
@@ -356,9 +350,8 @@ canvas_item_start_editing (CanvasItem *item)
|
||||
|
||||
gtk_box_append (GTK_BOX (item->editor), scale);
|
||||
|
||||
if (!gtk_widget_compute_point (GTK_WIDGET (item), canvas, &GRAPHENE_POINT_INIT (0, 0), &p))
|
||||
graphene_point_init (&p, 0, 0);
|
||||
gtk_fixed_put (GTK_FIXED (canvas), item->editor, p.x, p.y + 2 * item->r);
|
||||
gtk_widget_translate_coordinates (GTK_WIDGET (item), canvas, 0, 0, &x, &y);
|
||||
gtk_fixed_put (GTK_FIXED (canvas), item->editor, x, y + 2 * item->r);
|
||||
gtk_widget_grab_focus (entry);
|
||||
|
||||
}
|
||||
@@ -375,7 +368,6 @@ prepare (GtkDragSource *source,
|
||||
GtkWidget *canvas;
|
||||
GtkWidget *item;
|
||||
Hotspot *hotspot;
|
||||
graphene_point_t p;
|
||||
|
||||
canvas = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (source));
|
||||
item = gtk_widget_pick (canvas, x, y, GTK_PICK_DEFAULT);
|
||||
@@ -387,10 +379,7 @@ prepare (GtkDragSource *source,
|
||||
g_object_set_data (G_OBJECT (canvas), "dragged-item", item);
|
||||
|
||||
hotspot = g_new (Hotspot, 1);
|
||||
if (!gtk_widget_compute_point (canvas, item, &GRAPHENE_POINT_INIT (x, y), &p))
|
||||
graphene_point_init (&p, x, y);
|
||||
hotspot->x = p.x;
|
||||
hotspot->y = p.y;
|
||||
gtk_widget_translate_coordinates (canvas, item, x, y, &hotspot->x, &hotspot->y);
|
||||
g_object_set_data_full (G_OBJECT (canvas), "hotspot", hotspot, g_free);
|
||||
|
||||
return gdk_content_provider_new_typed (GTK_TYPE_WIDGET, item);
|
||||
@@ -765,7 +754,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS
|
||||
g_string_append_printf (css, ".canvasitem.%s { background: %s; }\n", colors[i], colors[i]);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, css->str);
|
||||
gtk_css_provider_load_from_data (provider, css->str, css->len);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
|
@@ -369,7 +369,7 @@ match_func (MatchObject *obj,
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_listview_selections (GtkWidget *do_widget)
|
||||
do_dropdown (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *button, *box, *spin, *check, *hbox, *label, *entry;
|
@@ -301,7 +301,7 @@ do_fishbowl (GtkWidget *do_widget)
|
||||
if (provider == NULL)
|
||||
{
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, css);
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
@@ -1294,18 +1294,18 @@ add_axis (hb_face_t *hb_face,
|
||||
|
||||
axis_label = gtk_label_new (name);
|
||||
gtk_widget_set_halign (axis_label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (axis_label, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (axis_label, GTK_ALIGN_BASELINE);
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), axis_label, 0, i, 1, 1);
|
||||
adjustment = gtk_adjustment_new (value, ax->min_value, ax->max_value,
|
||||
1.0, 10.0, 0.0);
|
||||
axis_scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, adjustment);
|
||||
gtk_scale_add_mark (GTK_SCALE (axis_scale), ax->default_value, GTK_POS_TOP, NULL);
|
||||
gtk_widget_set_valign (axis_scale, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (axis_scale, GTK_ALIGN_BASELINE);
|
||||
gtk_widget_set_hexpand (axis_scale, TRUE);
|
||||
gtk_widget_set_size_request (axis_scale, 100, -1);
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), axis_scale, 1, i, 1, 1);
|
||||
axis_entry = gtk_entry_new ();
|
||||
gtk_widget_set_valign (axis_entry, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (axis_entry, GTK_ALIGN_BASELINE);
|
||||
gtk_editable_set_width_chars (GTK_EDITABLE (axis_entry), 4);
|
||||
gtk_editable_set_max_width_chars (GTK_EDITABLE (axis_entry), 4);
|
||||
gtk_widget_set_hexpand (axis_entry, FALSE);
|
||||
@@ -1562,14 +1562,14 @@ update_font_variations (void)
|
||||
label = gtk_label_new ("Instance");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
|
||||
gtk_grid_attach (GTK_GRID (demo->variations_grid), label, 0, -1, 1, 1);
|
||||
|
||||
strings = gtk_string_list_new (NULL);
|
||||
combo = gtk_drop_down_new (G_LIST_MODEL (strings), NULL);
|
||||
|
||||
gtk_widget_set_halign (combo, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (combo, GTK_ALIGN_BASELINE);
|
||||
|
||||
gtk_string_list_append (strings, "");
|
||||
|
||||
|
@@ -42,8 +42,8 @@ val_to_xy (GtkFontPlane *plane,
|
||||
double u, v;
|
||||
int width, height;
|
||||
|
||||
width = gtk_widget_get_width (GTK_WIDGET (plane));
|
||||
height = gtk_widget_get_height (GTK_WIDGET (plane));
|
||||
width = gtk_widget_get_allocated_width (GTK_WIDGET (plane));
|
||||
height = gtk_widget_get_allocated_height (GTK_WIDGET (plane));
|
||||
|
||||
u = adjustment_get_normalized_value (plane->width_adj);
|
||||
v = adjustment_get_normalized_value (plane->weight_adj);
|
||||
@@ -62,8 +62,8 @@ plane_snapshot (GtkWidget *widget,
|
||||
cairo_t *cr;
|
||||
|
||||
val_to_xy (plane, &x, &y);
|
||||
width = gtk_widget_get_width (widget);
|
||||
height = gtk_widget_get_height (widget);
|
||||
width = gtk_widget_get_allocated_width (widget);
|
||||
height = gtk_widget_get_allocated_height (widget);
|
||||
|
||||
cr = gtk_snapshot_append_cairo (snapshot,
|
||||
&GRAPHENE_RECT_INIT (0, 0, width, height));
|
||||
@@ -131,8 +131,8 @@ update_value (GtkFontPlane *plane,
|
||||
GtkWidget *widget = GTK_WIDGET (plane);
|
||||
double u, v;
|
||||
|
||||
u = CLAMP (x * (1.0 / gtk_widget_get_width (widget)), 0, 1);
|
||||
v = CLAMP (1 - y * (1.0 / gtk_widget_get_height (widget)), 0, 1);
|
||||
u = CLAMP (x * (1.0 / gtk_widget_get_allocated_width (widget)), 0, 1);
|
||||
v = CLAMP (1 - y * (1.0 / gtk_widget_get_allocated_height (widget)), 0, 1);
|
||||
|
||||
adjustment_set_normalized_value (plane->width_adj, u);
|
||||
adjustment_set_normalized_value (plane->weight_adj, v);
|
||||
|
@@ -43,7 +43,6 @@ update_image (void)
|
||||
cairo_t *cr;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkPixbuf *pixbuf2;
|
||||
GdkTexture *texture;
|
||||
cairo_font_options_t *fopt;
|
||||
cairo_hint_style_t hintstyle;
|
||||
cairo_hint_metrics_t hintmetrics;
|
||||
@@ -121,17 +120,8 @@ update_image (void)
|
||||
cairo_destroy (cr);
|
||||
g_object_unref (layout);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_data (cairo_image_surface_get_data (surface),
|
||||
GDK_COLORSPACE_RGB, TRUE, 8,
|
||||
cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
cairo_image_surface_get_stride (surface),
|
||||
NULL, NULL);
|
||||
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf,
|
||||
gdk_pixbuf_get_width (pixbuf) * scale,
|
||||
gdk_pixbuf_get_height (pixbuf) * scale,
|
||||
GDK_INTERP_NEAREST);
|
||||
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
|
||||
|
||||
g_object_unref (pixbuf);
|
||||
cairo_surface_destroy (surface);
|
||||
@@ -288,24 +278,14 @@ retry:
|
||||
pango_layout_iter_free (iter);
|
||||
g_object_unref (layout);
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_data (cairo_image_surface_get_data (surface),
|
||||
GDK_COLORSPACE_RGB, TRUE, 8,
|
||||
cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
cairo_image_surface_get_stride (surface),
|
||||
NULL, NULL);
|
||||
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf,
|
||||
gdk_pixbuf_get_width (pixbuf) * scale,
|
||||
gdk_pixbuf_get_height (pixbuf) * scale,
|
||||
GDK_INTERP_NEAREST);
|
||||
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface));
|
||||
pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, gdk_pixbuf_get_width (pixbuf) * scale, gdk_pixbuf_get_height (pixbuf) * scale, GDK_INTERP_NEAREST);
|
||||
g_object_unref (pixbuf);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf2);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (image), GDK_PAINTABLE (texture));
|
||||
g_object_unref (pixbuf2);
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (image), pixbuf2);
|
||||
|
||||
g_object_unref (pixbuf2);
|
||||
}
|
||||
|
||||
|
@@ -221,13 +221,16 @@ static void
|
||||
realize (GtkWidget *widget)
|
||||
{
|
||||
const char *vertex_path, *fragment_path;
|
||||
GdkGLContext *context;
|
||||
|
||||
gtk_gl_area_make_current (GTK_GL_AREA (widget));
|
||||
|
||||
if (gtk_gl_area_get_error (GTK_GL_AREA (widget)) != NULL)
|
||||
return;
|
||||
|
||||
if (gtk_gl_area_get_api (GTK_GL_AREA (widget)) == GDK_GL_API_GLES)
|
||||
context = gtk_gl_area_get_context (GTK_GL_AREA (widget));
|
||||
|
||||
if (gdk_gl_context_get_use_es (context))
|
||||
{
|
||||
vertex_path = "/glarea/glarea-gles.vs.glsl";
|
||||
fragment_path = "/glarea/glarea-gles.fs.glsl";
|
||||
|
@@ -337,7 +337,7 @@ create_gltransition_window (GtkWidget *do_widget)
|
||||
1, 1, 1, 1);
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, "button.small { padding: 0; }");
|
||||
gtk_css_provider_load_from_data (provider, "button.small { padding: 0; }", -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
@@ -27,17 +27,24 @@ G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_SHADER_PAINTABLE (gsk_shader_paintable_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GskShaderPaintable, gsk_shader_paintable, GSK, SHADER_PAINTABLE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkPaintable * gsk_shader_paintable_new (GskGLShader *shader,
|
||||
GBytes *data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskGLShader * gsk_shader_paintable_get_shader (GskShaderPaintable *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_shader_paintable_set_shader (GskShaderPaintable *self,
|
||||
GskGLShader *shader);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GBytes * gsk_shader_paintable_get_args (GskShaderPaintable *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_shader_paintable_set_args (GskShaderPaintable *self,
|
||||
GBytes *data);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gsk_shader_paintable_update_time (GskShaderPaintable *self,
|
||||
int time_idx,
|
||||
gint64 frame_time);
|
||||
|
@@ -737,6 +737,7 @@ gtk_gears_realize (GtkWidget *widget)
|
||||
GtkGLArea *glarea = GTK_GL_AREA (widget);
|
||||
GtkGears *gears = GTK_GEARS (widget);
|
||||
GtkGearsPrivate *priv = gtk_gears_get_instance_private (gears);
|
||||
GdkGLContext *context;
|
||||
GLuint vao, v, f, program;
|
||||
const char *p;
|
||||
char msg[512];
|
||||
@@ -747,6 +748,8 @@ gtk_gears_realize (GtkWidget *widget)
|
||||
if (gtk_gl_area_get_error (glarea) != NULL)
|
||||
return;
|
||||
|
||||
context = gtk_gl_area_get_context (glarea);
|
||||
|
||||
glEnable (GL_CULL_FACE);
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
|
||||
@@ -756,7 +759,7 @@ gtk_gears_realize (GtkWidget *widget)
|
||||
priv->vao = vao;
|
||||
|
||||
/* Compile the vertex shader */
|
||||
if (gtk_gl_area_get_api (glarea) == GDK_GL_API_GLES)
|
||||
if (gdk_gl_context_get_use_es (context))
|
||||
p = vertex_shader_gles;
|
||||
else
|
||||
p = vertex_shader_gl;
|
||||
@@ -767,7 +770,7 @@ gtk_gears_realize (GtkWidget *widget)
|
||||
g_debug ("vertex shader info: %s\n", msg);
|
||||
|
||||
/* Compile the fragment shader */
|
||||
if (gtk_gl_area_get_api (glarea) == GDK_GL_API_GLES)
|
||||
if (gdk_gl_context_get_use_es (context))
|
||||
p = fragment_shader_gles;
|
||||
else
|
||||
p = fragment_shader_gl;
|
||||
|
@@ -370,7 +370,7 @@ do_iconscroll (GtkWidget *do_widget)
|
||||
set_widget_type (0);
|
||||
|
||||
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps_label"));
|
||||
id = g_timeout_add_full (G_PRIORITY_HIGH, 500, update_fps, label, NULL);
|
||||
id = g_timeout_add (500, update_fps, label);
|
||||
g_object_set_data_full (G_OBJECT (label), "timeout",
|
||||
GUINT_TO_POINTER (id), remove_timeout);
|
||||
|
||||
|
@@ -1,191 +0,0 @@
|
||||
/* Image Scaling
|
||||
* #Keywords: zoom, scale, filter, action, menu
|
||||
*
|
||||
* The custom widget we create here is similar to a GtkPicture,
|
||||
* but allows setting a zoom level and filtering mode for the
|
||||
* displayed paintable.
|
||||
*
|
||||
* It also demonstrates how to add a context menu to a custom
|
||||
* widget and connect it with widget actions.
|
||||
*
|
||||
* The context menu has items to change the zoom level.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo3widget.h"
|
||||
|
||||
static void
|
||||
file_opened (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *data)
|
||||
{
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
GdkTexture *texture;
|
||||
|
||||
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_from_file (file, &error);
|
||||
g_object_unref (file);
|
||||
if (!texture)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (data), "texture", texture, NULL);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
open_file (GtkWidget *picker,
|
||||
GtkWidget *demo)
|
||||
{
|
||||
GtkWindow *parent = GTK_WINDOW (gtk_widget_get_root (picker));
|
||||
GtkFileDialog *dialog;
|
||||
GtkFileFilter *filter;
|
||||
GListStore *filters;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_set_name (filter, "Images");
|
||||
gtk_file_filter_add_pixbuf_formats (filter);
|
||||
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
|
||||
g_list_store_append (filters, filter);
|
||||
g_object_unref (filter);
|
||||
|
||||
gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
|
||||
g_object_unref (filters);
|
||||
|
||||
gtk_file_dialog_open (dialog, parent, NULL, file_opened, demo);
|
||||
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
rotate (GtkWidget *button,
|
||||
GtkWidget *demo)
|
||||
{
|
||||
float angle;
|
||||
|
||||
g_object_get (demo, "angle", &angle, NULL);
|
||||
|
||||
angle = fmodf (angle + 90.f, 360.f);
|
||||
|
||||
g_object_set (demo, "angle", angle, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_to (GBinding *binding,
|
||||
const GValue *src,
|
||||
GValue *dest,
|
||||
gpointer user_data)
|
||||
{
|
||||
double from;
|
||||
float to;
|
||||
|
||||
from = g_value_get_double (src);
|
||||
to = (float) pow (2., from);
|
||||
g_value_set_float (dest, to);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_from (GBinding *binding,
|
||||
const GValue *src,
|
||||
GValue *dest,
|
||||
gpointer user_data)
|
||||
{
|
||||
float to;
|
||||
double from;
|
||||
|
||||
to = g_value_get_float (src);
|
||||
from = log2 (to);
|
||||
g_value_set_double (dest, from);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_image_scaling (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *dropdown;
|
||||
GtkWidget *button;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Image Scaling");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), box2);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("document-open-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Open File");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (open_file), widget);
|
||||
gtk_box_append (GTK_BOX (box2), button);
|
||||
|
||||
button = gtk_button_new_from_icon_name ("object-rotate-right-symbolic");
|
||||
gtk_widget_set_tooltip_text (button, "Rotate");
|
||||
g_signal_connect (button, "clicked", G_CALLBACK (rotate), widget);
|
||||
gtk_box_append (GTK_BOX (box2), button);
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, -10., 10., 0.1);
|
||||
gtk_scale_add_mark (GTK_SCALE (scale), 0., GTK_POS_TOP, NULL);
|
||||
gtk_widget_set_tooltip_text (scale, "Zoom");
|
||||
gtk_range_set_value (GTK_RANGE (scale), 0.);
|
||||
gtk_widget_set_hexpand (scale, TRUE);
|
||||
gtk_box_append (GTK_BOX (box2), scale);
|
||||
|
||||
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
|
||||
gtk_widget_set_tooltip_text (dropdown, "Filter");
|
||||
gtk_box_append (GTK_BOX (box2), dropdown);
|
||||
|
||||
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
|
||||
|
||||
g_object_bind_property_full (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL,
|
||||
transform_to,
|
||||
transform_from,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
@@ -30,7 +30,6 @@ progressive_prepared_callback (GdkPixbufLoader *loader,
|
||||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
GtkWidget *picture;
|
||||
GdkTexture *texture;
|
||||
|
||||
picture = GTK_WIDGET (data);
|
||||
|
||||
@@ -41,9 +40,7 @@ progressive_prepared_callback (GdkPixbufLoader *loader,
|
||||
*/
|
||||
gdk_pixbuf_fill (pixbuf, 0xaaaaaaff);
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (picture), pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -54,18 +51,22 @@ progressive_updated_callback (GdkPixbufLoader *loader,
|
||||
int height,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *picture = GTK_WIDGET (data);
|
||||
GdkTexture *texture;
|
||||
GtkWidget *picture;
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_loader_get_pixbuf (loader));
|
||||
gtk_picture_set_paintable (GTK_PICTURE (picture), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
picture = GTK_WIDGET (data);
|
||||
|
||||
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (picture), NULL);
|
||||
gtk_picture_set_pixbuf (GTK_PICTURE (picture), pixbuf);
|
||||
}
|
||||
|
||||
static int
|
||||
progressive_timeout (gpointer data)
|
||||
{
|
||||
GtkWidget *picture = GTK_WIDGET (data);
|
||||
GtkWidget *picture;
|
||||
|
||||
picture = GTK_WIDGET (data);
|
||||
|
||||
/* This shows off fully-paranoid error handling, so looks scary.
|
||||
* You could factor out the error handling code into a nice separate
|
||||
|
@@ -64,8 +64,6 @@
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="short_time_label">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">1</property>
|
||||
<property name="valign">baseline</property>
|
||||
<property name="label" translatable="yes">38m</property>
|
||||
<style>
|
||||
|
@@ -30,86 +30,90 @@
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<signal name="row-activated" handler="row_activated"/>
|
||||
<style>
|
||||
<class name="rich-list"/>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
|
||||
<object class="GtkFrame">
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<property name="show-separators">1</property>
|
||||
<signal name="row-activated" handler="row_activated"/>
|
||||
<style>
|
||||
<class name="rich-list"/>
|
||||
</style>
|
||||
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkLabel" id="switch_label">
|
||||
<property name="label" translatable="yes">Switch</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="switch">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="switch_label">
|
||||
<property name="label" translatable="yes">Switch</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="switch">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkLabel" id="check_label">
|
||||
<property name="label" translatable="yes">Check</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="active">1</property>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="check_label">
|
||||
<property name="label" translatable="yes">Check</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="check">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="active">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkListBoxRow">
|
||||
<child>
|
||||
<object class="GtkLabel" id="image_label">
|
||||
<property name="label" translatable="yes">Click here!</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="icon-name">object-select-symbolic</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="opacity">0</property>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="image_label">
|
||||
<property name="label" translatable="yes">Click here!</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="icon-name">object-select-symbolic</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="opacity">0</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -130,142 +134,146 @@
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<style>
|
||||
<class name="rich-list"/>
|
||||
<class name="boxed-list"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkFrame">
|
||||
<child>
|
||||
<object class="GtkListBox">
|
||||
<property name="selection-mode">none</property>
|
||||
<property name="show-separators">1</property>
|
||||
<style>
|
||||
<class name="rich-list"/>
|
||||
</style>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="scale_label">
|
||||
<property name="label" translatable="yes">Scale</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="draw-value">0</property>
|
||||
<property name="width-request">150</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="value">50</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="scale_label">
|
||||
<property name="label" translatable="yes">Scale</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="draw-value">0</property>
|
||||
<property name="width-request">150</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="value">50</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="spin_label">
|
||||
<property name="label" translatable="yes">Spinbutton</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="value">50</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="dropdown_label">
|
||||
<property name="label" translatable="yes">Dropdown</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item>Choice 1</item>
|
||||
<item>Choice 2</item>
|
||||
<item>Choice 3</item>
|
||||
<item>Choice 4</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="spin_label">
|
||||
<property name="label" translatable="yes">Spinbutton</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="upper">100</property>
|
||||
<property name="value">50</property>
|
||||
<property name="step-increment">1</property>
|
||||
<property name="page-increment">10</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="dropdown_label">
|
||||
<property name="label" translatable="yes">Dropdown</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkDropDown">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="model">
|
||||
<object class="GtkStringList">
|
||||
<items>
|
||||
<item>Choice 1</item>
|
||||
<item>Choice 2</item>
|
||||
<item>Choice 3</item>
|
||||
<item>Choice 4</item>
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="entry_label">
|
||||
<property name="label" translatable="yes">Entry</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="placeholder-text">Type here…</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkListBoxRow">
|
||||
<property name="activatable">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkLabel" id="entry_label">
|
||||
<property name="label" translatable="yes">Entry</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="placeholder-text">Type here…</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -14,15 +14,145 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "settings-key.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
typedef struct _SettingsKey SettingsKey;
|
||||
struct _SettingsKey
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSettings *settings;
|
||||
GSettingsSchemaKey *key;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SUMMARY,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VALUE,
|
||||
PROP_TYPE,
|
||||
PROP_DEFAULT_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
#define SETTINGS_TYPE_KEY (settings_key_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SettingsKey, settings_key, SETTINGS, KEY, GObject);
|
||||
|
||||
G_DEFINE_TYPE (SettingsKey, settings_key, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
item_value_changed (GtkEditableLabel *label,
|
||||
GParamSpec *pspec,
|
||||
GtkColumnViewCell *cell)
|
||||
settings_key_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, g_settings_schema_key_get_description (self->key));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, g_settings_schema_key_get_name (self->key));
|
||||
break;
|
||||
|
||||
case PROP_SUMMARY:
|
||||
g_value_set_string (value, g_settings_schema_key_get_summary (self->key));
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_get_value (self->settings, g_settings_schema_key_get_name (self->key));
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_TYPE:
|
||||
{
|
||||
const GVariantType *type = g_settings_schema_key_get_value_type (self->key);
|
||||
g_value_set_string (value, g_variant_type_peek_string (type));
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEFAULT_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_schema_key_get_default_value (self->key);
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_finalize (GObject *object)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
g_object_unref (self->settings);
|
||||
g_settings_schema_key_unref (self->key);
|
||||
|
||||
G_OBJECT_CLASS (settings_key_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_class_init (SettingsKeyClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = settings_key_finalize;
|
||||
gobject_class->get_property = settings_key_get_property;
|
||||
|
||||
properties[PROP_DESCRIPTION] =
|
||||
g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_SUMMARY] =
|
||||
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_TYPE] =
|
||||
g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_DEFAULT_VALUE] =
|
||||
g_param_spec_string ("default-value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_init (SettingsKey *self)
|
||||
{
|
||||
}
|
||||
|
||||
static SettingsKey *
|
||||
settings_key_new (GSettings *settings,
|
||||
GSettingsSchemaKey *key)
|
||||
{
|
||||
SettingsKey *result = g_object_new (SETTINGS_TYPE_KEY, NULL);
|
||||
|
||||
result->settings = g_object_ref (settings);
|
||||
result->key = g_settings_schema_key_ref (key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
item_value_changed (GtkEditableLabel *label,
|
||||
GParamSpec *pspec,
|
||||
GtkListItem *item)
|
||||
{
|
||||
SettingsKey *self;
|
||||
GSettingsSchemaKey *key;
|
||||
const char *text;
|
||||
const GVariantType *type;
|
||||
GVariant *variant;
|
||||
@@ -32,11 +162,11 @@ item_value_changed (GtkEditableLabel *label,
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (label));
|
||||
|
||||
self = gtk_column_view_cell_get_item (cell);
|
||||
key = settings_key_get_key (self);
|
||||
g_object_get (item, "item", &self, NULL);
|
||||
g_object_unref (self);
|
||||
|
||||
type = g_settings_schema_key_get_value_type (key);
|
||||
name = g_settings_schema_key_get_name (key);
|
||||
type = g_settings_schema_key_get_value_type (self->key);
|
||||
name = g_settings_schema_key_get_name (self->key);
|
||||
|
||||
variant = g_variant_parse (type, text, NULL, NULL, &error);
|
||||
if (!variant)
|
||||
@@ -46,13 +176,13 @@ item_value_changed (GtkEditableLabel *label,
|
||||
goto revert;
|
||||
}
|
||||
|
||||
if (!g_settings_schema_key_range_check (key, variant))
|
||||
if (!g_settings_schema_key_range_check (self->key, variant))
|
||||
{
|
||||
g_warning ("Not a valid value for %s", name);
|
||||
goto revert;
|
||||
}
|
||||
|
||||
g_settings_set_value (settings_key_get_settings (self), name, variant);
|
||||
g_settings_set_value (self->settings, name, variant);
|
||||
g_variant_unref (variant);
|
||||
return;
|
||||
|
||||
|
@@ -20,7 +20,6 @@
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="tab-behavior">item</property>
|
||||
<style>
|
||||
<class name="navigation-sidebar"/>
|
||||
</style>
|
||||
@@ -77,7 +76,6 @@
|
||||
<property name="vexpand">1</property>
|
||||
<child>
|
||||
<object class="GtkColumnView" id="columnview">
|
||||
<property name="tab-behavior">cell</property>
|
||||
<style>
|
||||
<class name="data-table"/>
|
||||
</style>
|
||||
@@ -90,13 +88,13 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
@@ -118,12 +116,12 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkEditableLabel">
|
||||
<binding name="text">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<signal name="notify::label" handler="item_value_changed"/>
|
||||
@@ -146,13 +144,13 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="type" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
@@ -175,13 +173,13 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="default-value" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
@@ -205,14 +203,14 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">1</property>
|
||||
<binding name="label">
|
||||
<lookup name="summary" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
@@ -236,14 +234,14 @@
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkColumnViewCell">
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<property name="wrap">1</property>
|
||||
<binding name="label">
|
||||
<lookup name="description" type="SettingsKey">
|
||||
<lookup name="item">GtkColumnViewCell</lookup>
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
|
@@ -1,230 +0,0 @@
|
||||
/* Lists/Alternative Settings
|
||||
* #Keywords: GtkListHeaderFactory, GtkSectionModel
|
||||
*
|
||||
* This demo shows an alternative settings viewer for GSettings.
|
||||
*
|
||||
* It demonstrates how to implement support for sections with GtkListView.
|
||||
*
|
||||
* It also shows how to quickly flatten a large tree of items into a list
|
||||
* that can be filtered to find the items one is looking for.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "settings-key.h"
|
||||
|
||||
static void
|
||||
item_value_changed (GtkEditableLabel *label,
|
||||
GParamSpec *pspec,
|
||||
GtkColumnViewCell *cell)
|
||||
{
|
||||
SettingsKey *self;
|
||||
GSettingsSchemaKey *key;
|
||||
const char *text;
|
||||
const GVariantType *type;
|
||||
GVariant *variant;
|
||||
GError *error = NULL;
|
||||
const char *name;
|
||||
char *value;
|
||||
|
||||
text = gtk_editable_get_text (GTK_EDITABLE (label));
|
||||
|
||||
self = gtk_column_view_cell_get_item (cell);
|
||||
key = settings_key_get_key (self);
|
||||
|
||||
type = g_settings_schema_key_get_value_type (key);
|
||||
name = g_settings_schema_key_get_name (key);
|
||||
|
||||
variant = g_variant_parse (type, text, NULL, NULL, &error);
|
||||
if (!variant)
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_clear_error (&error);
|
||||
goto revert;
|
||||
}
|
||||
|
||||
if (!g_settings_schema_key_range_check (key, variant))
|
||||
{
|
||||
g_warning ("Not a valid value for %s", name);
|
||||
goto revert;
|
||||
}
|
||||
|
||||
g_settings_set_value (settings_key_get_settings (self), name, variant);
|
||||
g_variant_unref (variant);
|
||||
return;
|
||||
|
||||
revert:
|
||||
gtk_widget_error_bell (GTK_WIDGET (label));
|
||||
|
||||
g_object_get (self, "value", &value, NULL);
|
||||
gtk_editable_set_text (GTK_EDITABLE (label), value);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
static int
|
||||
strvcmp (gconstpointer p1,
|
||||
gconstpointer p2)
|
||||
{
|
||||
const char * const *s1 = p1;
|
||||
const char * const *s2 = p2;
|
||||
|
||||
return strcmp (*s1, *s2);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
map_settings_to_keys (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
GSettings *settings = item;
|
||||
GSettingsSchema *schema;
|
||||
GListStore *store;
|
||||
char **keys;
|
||||
guint i;
|
||||
|
||||
g_object_get (settings, "settings-schema", &schema, NULL);
|
||||
|
||||
store = g_list_store_new (SETTINGS_TYPE_KEY);
|
||||
|
||||
keys = g_settings_schema_list_keys (schema);
|
||||
|
||||
for (i = 0; keys[i] != NULL; i++)
|
||||
{
|
||||
GSettingsSchemaKey *almost_there = g_settings_schema_get_key (schema, keys[i]);
|
||||
SettingsKey *finally = settings_key_new (settings, almost_there);
|
||||
g_list_store_append (store, finally);
|
||||
g_object_unref (finally);
|
||||
g_settings_schema_key_unref (almost_there);
|
||||
}
|
||||
|
||||
g_strfreev (keys);
|
||||
g_settings_schema_unref (schema);
|
||||
g_object_unref (settings);
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
static GListModel *
|
||||
create_settings_model (gpointer item,
|
||||
gpointer unused)
|
||||
{
|
||||
GSettings *settings = item;
|
||||
char **schemas;
|
||||
GListStore *result;
|
||||
guint i;
|
||||
|
||||
if (settings == NULL)
|
||||
{
|
||||
g_settings_schema_source_list_schemas (g_settings_schema_source_get_default (),
|
||||
TRUE,
|
||||
&schemas,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
schemas = g_settings_list_children (settings);
|
||||
}
|
||||
|
||||
if (schemas == NULL || schemas[0] == NULL)
|
||||
{
|
||||
g_free (schemas);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qsort (schemas, g_strv_length (schemas), sizeof (char *), strvcmp);
|
||||
|
||||
result = g_list_store_new (G_TYPE_SETTINGS);
|
||||
for (i = 0; schemas[i] != NULL; i++)
|
||||
{
|
||||
GSettings *child;
|
||||
|
||||
if (settings == NULL)
|
||||
child = g_settings_new (schemas[i]);
|
||||
else
|
||||
child = g_settings_get_child (settings, schemas[i]);
|
||||
|
||||
g_list_store_append (result, child);
|
||||
g_object_unref (child);
|
||||
}
|
||||
|
||||
g_strfreev (schemas);
|
||||
|
||||
return G_LIST_MODEL (result);
|
||||
}
|
||||
|
||||
static void
|
||||
search_enabled (GtkSearchEntry *entry)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
}
|
||||
|
||||
static void
|
||||
stop_search (GtkSearchEntry *entry,
|
||||
gpointer data)
|
||||
{
|
||||
gtk_editable_set_text (GTK_EDITABLE (entry), "");
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
do_listview_settings2 (GtkWidget *do_widget)
|
||||
{
|
||||
if (window == NULL)
|
||||
{
|
||||
GtkListView *listview;
|
||||
GListModel *model;
|
||||
GtkTreeListModel *treemodel;
|
||||
GtkNoSelection *selection;
|
||||
GtkBuilderScope *scope;
|
||||
GtkBuilder *builder;
|
||||
GError *error = NULL;
|
||||
GtkFilter *filter;
|
||||
|
||||
g_type_ensure (SETTINGS_TYPE_KEY);
|
||||
|
||||
scope = gtk_builder_cscope_new ();
|
||||
gtk_builder_cscope_add_callback (scope, search_enabled);
|
||||
gtk_builder_cscope_add_callback (scope, stop_search);
|
||||
gtk_builder_cscope_add_callback (scope, settings_key_get_search_string);
|
||||
gtk_builder_cscope_add_callback (scope, item_value_changed);
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_set_scope (builder, scope);
|
||||
g_object_unref (scope);
|
||||
|
||||
gtk_builder_add_from_resource (builder, "/listview_settings2/listview_settings2.ui", &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
|
||||
|
||||
listview = GTK_LIST_VIEW (gtk_builder_get_object (builder, "listview"));
|
||||
filter = GTK_FILTER (gtk_builder_get_object (builder, "filter"));
|
||||
|
||||
model = create_settings_model (NULL, NULL);
|
||||
treemodel = gtk_tree_list_model_new (model,
|
||||
TRUE,
|
||||
TRUE,
|
||||
create_settings_model,
|
||||
NULL,
|
||||
NULL);
|
||||
model = G_LIST_MODEL (gtk_map_list_model_new (G_LIST_MODEL (treemodel), map_settings_to_keys, NULL, NULL));
|
||||
model = G_LIST_MODEL (gtk_flatten_list_model_new (model));
|
||||
model = G_LIST_MODEL (gtk_filter_list_model_new (model, g_object_ref (filter)));
|
||||
selection = gtk_no_selection_new (model);
|
||||
|
||||
gtk_list_view_set_model (GTK_LIST_VIEW (listview), GTK_SELECTION_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
|
||||
g_object_unref (builder);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkStringFilter" id="filter">
|
||||
<property name="expression">
|
||||
<closure type="gchararray" function="settings_key_get_search_string" />
|
||||
</property>
|
||||
<property name="search" bind-source="entry" bind-property="text" />
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="title" translatable="yes">Settings</property>
|
||||
<property name="default-width">640</property>
|
||||
<property name="default-height">480</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<child type="end">
|
||||
<object class="GtkToggleButton" id="search_button">
|
||||
<property name="icon-name">system-search-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkSearchBar">
|
||||
<property name="search-mode-enabled" bind-source="search_button" bind-property="active" bind-flags="bidirectional"/>
|
||||
<signal name="notify::search-mode-enabled" handler="search_enabled" object="entry"/>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="entry">
|
||||
<signal name="stop-search" handler="stop_search"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkListView" id="listview">
|
||||
<property name="vexpand">1</property>
|
||||
<style>
|
||||
<class name="rich-list"/>
|
||||
</style>
|
||||
<property name="factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="child">
|
||||
<object class="GtkBox">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="name" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<style>
|
||||
<class name="dim-label"/>
|
||||
</style>
|
||||
<property name="xalign">0</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<binding name="label">
|
||||
<lookup name="summary" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="halign">end</property>
|
||||
<binding name="text">
|
||||
<lookup name="value" type="SettingsKey">
|
||||
<lookup name="item">GtkListItem</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
<signal name="notify::label" handler="item_value_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
<property name="header-factory">
|
||||
<object class="GtkBuilderListItemFactory">
|
||||
<property name="bytes"><![CDATA[
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListHeader">
|
||||
<property name="child">
|
||||
<object class="GtkLabel">
|
||||
<property name="xalign">0</property>
|
||||
<binding name="label">
|
||||
<lookup name="schema" type="GSettings">
|
||||
<lookup name="settings" type="SettingsKey">
|
||||
<lookup name="item">GtkListHeader</lookup>
|
||||
</lookup>
|
||||
</lookup>
|
||||
</binding>
|
||||
</object>
|
||||
</property>
|
||||
</template>
|
||||
</interface>
|
||||
]]></property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@@ -367,7 +367,7 @@ do_listview_ucd (GtkWidget *do_widget)
|
||||
gtk_label_set_width_chars (GTK_LABEL (label), 2);
|
||||
gtk_widget_add_css_class (label, "enormous");
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, "label.enormous { font-size: 80px; }");
|
||||
gtk_css_provider_load_from_data (provider, "label.enormous { font-size: 80px; }", -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (), GTK_STYLE_PROVIDER (provider), 800);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), label);
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<template class="GtkListItem">
|
||||
<property name="focusable">0</property>
|
||||
<property name="child">
|
||||
<object class="GtkTreeExpander" id="expander">
|
||||
<binding name="list-row">
|
||||
|
72
demos/gtk-demo/menu.c
Normal file
72
demos/gtk-demo/menu.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/* Menu
|
||||
* #Keywords: action, zoom
|
||||
*
|
||||
* Demonstrates how to add a context menu to a custom widget
|
||||
* and connect it with widget actions.
|
||||
*
|
||||
* The custom widget we create here is similar to a GtkPicture,
|
||||
* but allows setting a zoom level for the displayed paintable.
|
||||
*
|
||||
* Our context menu has items to change the zoom level.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include "demo3widget.h"
|
||||
|
||||
|
||||
GtkWidget *
|
||||
do_menu (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *box;
|
||||
GtkWidget *box2;
|
||||
GtkWidget *sw;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *scale;
|
||||
GtkWidget *dropdown;
|
||||
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Menu");
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
|
||||
widget = demo3_widget_new ("/transparent/portland-rose.jpg");
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), widget);
|
||||
|
||||
box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
gtk_box_append (GTK_BOX (box), box2);
|
||||
|
||||
scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0.01, 10.0, 0.1);
|
||||
gtk_range_set_value (GTK_RANGE (scale), 1.0);
|
||||
gtk_widget_set_hexpand (scale, TRUE);
|
||||
gtk_box_append (GTK_BOX (box2), scale);
|
||||
|
||||
dropdown = gtk_drop_down_new (G_LIST_MODEL (gtk_string_list_new ((const char *[]){ "Linear", "Nearest", "Trilinear", NULL })), NULL);
|
||||
gtk_box_append (GTK_BOX (box2), dropdown);
|
||||
|
||||
g_object_bind_property (dropdown, "selected", widget, "filter", G_BINDING_DEFAULT);
|
||||
|
||||
g_object_bind_property (gtk_range_get_adjustment (GTK_RANGE (scale)), "value",
|
||||
widget, "scale",
|
||||
G_BINDING_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_set_visible (window, TRUE);
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
@@ -39,7 +39,6 @@ demos = files([
|
||||
'iconscroll.c',
|
||||
'iconview.c',
|
||||
'iconview_edit.c',
|
||||
'image_scaling.c',
|
||||
'images.c',
|
||||
'infobar.c',
|
||||
'layoutmanager.c',
|
||||
@@ -48,6 +47,7 @@ demos = files([
|
||||
'listbox.c',
|
||||
'listbox_controls.c',
|
||||
'mask.c',
|
||||
'menu.c',
|
||||
'flowbox.c',
|
||||
'list_store.c',
|
||||
'listview_applauncher.c',
|
||||
@@ -55,9 +55,8 @@ demos = files([
|
||||
'listview_colors.c',
|
||||
'listview_filebrowser.c',
|
||||
'listview_minesweeper.c',
|
||||
'listview_selections.c',
|
||||
'dropdown.c',
|
||||
'listview_settings.c',
|
||||
'listview_settings2.c',
|
||||
'listview_ucd.c',
|
||||
'listview_weather.c',
|
||||
'listview_words.c',
|
||||
@@ -132,7 +131,6 @@ extra_demo_sources = files([
|
||||
'demo4widget.c',
|
||||
'pixbufpaintable.c',
|
||||
'script-names.c',
|
||||
'settings-key.c',
|
||||
'unicode-names.c',
|
||||
'suggestionentry.c',
|
||||
'language-names.c',
|
||||
@@ -227,7 +225,7 @@ if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_
|
||||
else
|
||||
gtkdemo_resources = gnome.compile_resources('gtkdemo_resources',
|
||||
'demo.gresource.xml',
|
||||
source_dir: meson.current_source_dir()
|
||||
source_dir: '.',
|
||||
)
|
||||
endif
|
||||
|
||||
@@ -235,7 +233,8 @@ endif
|
||||
demo_cflags = []
|
||||
foreach flag: common_cflags
|
||||
if flag not in ['-Werror=missing-prototypes', '-Wmissing-prototypes',
|
||||
'-Werror=missing-declarations', '-Wmissing-declarations']
|
||||
'-Werror=missing-declarations', '-Wmissing-declarations',
|
||||
'-fvisibility=hidden']
|
||||
demo_cflags += flag
|
||||
endif
|
||||
endforeach
|
||||
|
@@ -24,7 +24,6 @@ typedef struct
|
||||
GdkRGBA draw_color;
|
||||
GtkPadController *pad_controller;
|
||||
double brush_size;
|
||||
GtkGesture *gesture;
|
||||
} DrawingArea;
|
||||
|
||||
typedef struct
|
||||
@@ -104,11 +103,13 @@ drawing_area_size_allocate (GtkWidget *widget,
|
||||
static void
|
||||
drawing_area_map (GtkWidget *widget)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
|
||||
GTK_WIDGET_CLASS (drawing_area_parent_class)->map (widget);
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
drawing_area_ensure_surface ((DrawingArea *) widget,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget));
|
||||
allocation.width, allocation.height);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -261,7 +262,7 @@ drawing_area_apply_stroke (DrawingArea *area,
|
||||
double y,
|
||||
double pressure)
|
||||
{
|
||||
if (tool && gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER)
|
||||
if (gdk_device_tool_get_tool_type (tool) == GDK_DEVICE_TOOL_TYPE_ERASER)
|
||||
{
|
||||
cairo_set_line_width (area->cr, 10 * pressure * area->brush_size);
|
||||
cairo_set_operator (area->cr, CAIRO_OPERATOR_DEST_OUT);
|
||||
@@ -312,9 +313,7 @@ stylus_gesture_motion (GtkGestureStylus *gesture,
|
||||
drawing_area_apply_stroke (area, tool,
|
||||
backlog[i].axes[GDK_AXIS_X],
|
||||
backlog[i].axes[GDK_AXIS_Y],
|
||||
backlog[i].flags & GDK_AXIS_FLAG_PRESSURE
|
||||
? backlog[i].axes[GDK_AXIS_PRESSURE]
|
||||
: 1);
|
||||
backlog[i].axes[GDK_AXIS_PRESSURE]);
|
||||
}
|
||||
|
||||
g_free (backlog);
|
||||
@@ -344,8 +343,6 @@ drawing_area_init (DrawingArea *area)
|
||||
|
||||
area->draw_color = (GdkRGBA) { 0, 0, 0, 1 };
|
||||
area->brush_size = 1;
|
||||
|
||||
area->gesture = gesture;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@@ -384,12 +381,6 @@ drawing_area_color_set (DrawingArea *area,
|
||||
gtk_color_dialog_button_set_rgba (button, color);
|
||||
}
|
||||
|
||||
static GtkGesture *
|
||||
drawing_area_get_gesture (DrawingArea *area)
|
||||
{
|
||||
return area->gesture;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_paint (GtkWidget *toplevel)
|
||||
{
|
||||
@@ -397,7 +388,7 @@ do_paint (GtkWidget *toplevel)
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkWidget *draw_area, *headerbar, *button;
|
||||
GtkWidget *draw_area, *headerbar, *colorbutton;
|
||||
|
||||
window = gtk_window_new ();
|
||||
|
||||
@@ -406,22 +397,15 @@ do_paint (GtkWidget *toplevel)
|
||||
|
||||
headerbar = gtk_header_bar_new ();
|
||||
|
||||
button = gtk_color_dialog_button_new (gtk_color_dialog_new ());
|
||||
g_signal_connect (button, "notify::rgba",
|
||||
colorbutton = gtk_color_dialog_button_new (gtk_color_dialog_new ());
|
||||
g_signal_connect (colorbutton, "notify::rgba",
|
||||
G_CALLBACK (color_button_color_set), draw_area);
|
||||
g_signal_connect (draw_area, "color-set",
|
||||
G_CALLBACK (drawing_area_color_set), button);
|
||||
gtk_color_dialog_button_set_rgba (GTK_COLOR_DIALOG_BUTTON (button),
|
||||
G_CALLBACK (drawing_area_color_set), colorbutton);
|
||||
gtk_color_dialog_button_set_rgba (GTK_COLOR_DIALOG_BUTTON (colorbutton),
|
||||
&(GdkRGBA) { 0, 0, 0, 1 });
|
||||
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), button);
|
||||
|
||||
button = gtk_check_button_new_with_label ("Stylus only");
|
||||
g_object_bind_property (button, "active",
|
||||
drawing_area_get_gesture ((DrawingArea *)draw_area), "stylus-only",
|
||||
G_BINDING_SYNC_CREATE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (headerbar), button);
|
||||
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), colorbutton);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), headerbar);
|
||||
gtk_window_set_title (GTK_WINDOW (window), "Paint");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
@@ -384,7 +384,7 @@ create_board (GtkWidget *window)
|
||||
"}";
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, css);
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
|
@@ -13,13 +13,20 @@
|
||||
static GtkWidget *app_picker;
|
||||
|
||||
static void
|
||||
set_file (GFile *file,
|
||||
gpointer data)
|
||||
file_opened (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *data)
|
||||
{
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
char *name;
|
||||
|
||||
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
gtk_widget_set_sensitive (app_picker, FALSE);
|
||||
g_object_set_data (G_OBJECT (app_picker), "file", NULL);
|
||||
return;
|
||||
@@ -33,25 +40,6 @@ set_file (GFile *file,
|
||||
g_object_set_data_full (G_OBJECT (app_picker), "file", g_object_ref (file), g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
file_opened (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *data)
|
||||
{
|
||||
GFile *file;
|
||||
GError *error = NULL;
|
||||
|
||||
file = gtk_file_dialog_open_finish (GTK_FILE_DIALOG (source), result, &error);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
set_file (file, data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
abort_mission (gpointer data)
|
||||
{
|
||||
@@ -142,28 +130,11 @@ launch_uri (GtkButton *picker)
|
||||
g_object_unref (launcher);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_drop (GtkDropTarget *target,
|
||||
const GValue *value,
|
||||
double x,
|
||||
double y,
|
||||
gpointer data)
|
||||
{
|
||||
if (G_VALUE_HOLDS (value, G_TYPE_FILE))
|
||||
{
|
||||
set_file (g_value_get_object (value), data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_pickers (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *table, *label, *picker, *button;
|
||||
GtkDropTarget *drop_target;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
@@ -208,13 +179,7 @@ do_pickers (GtkWidget *do_widget)
|
||||
|
||||
picker = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
|
||||
button = gtk_button_new_from_icon_name ("document-open-symbolic");
|
||||
|
||||
label = gtk_label_new ("None");
|
||||
|
||||
drop_target = gtk_drop_target_new (G_TYPE_FILE, GDK_ACTION_COPY);
|
||||
g_signal_connect (drop_target, "drop", G_CALLBACK (on_drop), label);
|
||||
gtk_widget_add_controller (button, GTK_EVENT_CONTROLLER (drop_target));
|
||||
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.);
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
|
@@ -1,165 +0,0 @@
|
||||
#include "settings-key.h"
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
struct _SettingsKey
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSettings *settings;
|
||||
GSettingsSchemaKey *key;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_NAME,
|
||||
PROP_SETTINGS,
|
||||
PROP_SUMMARY,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_VALUE,
|
||||
PROP_TYPE,
|
||||
PROP_DEFAULT_VALUE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (SettingsKey, settings_key, G_TYPE_OBJECT);
|
||||
static GParamSpec *properties[N_PROPS] = { NULL, };
|
||||
|
||||
static void
|
||||
settings_key_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_DESCRIPTION:
|
||||
g_value_set_string (value, g_settings_schema_key_get_description (self->key));
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, g_settings_schema_key_get_name (self->key));
|
||||
break;
|
||||
|
||||
case PROP_SUMMARY:
|
||||
g_value_set_string (value, g_settings_schema_key_get_summary (self->key));
|
||||
break;
|
||||
|
||||
case PROP_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_get_value (self->settings, g_settings_schema_key_get_name (self->key));
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_TYPE:
|
||||
{
|
||||
const GVariantType *type = g_settings_schema_key_get_value_type (self->key);
|
||||
g_value_set_string (value, g_variant_type_peek_string (type));
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_DEFAULT_VALUE:
|
||||
{
|
||||
GVariant *variant = g_settings_schema_key_get_default_value (self->key);
|
||||
g_value_take_string (value, g_variant_print (variant, FALSE));
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_SETTINGS:
|
||||
g_value_set_object (value, self->settings);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_finalize (GObject *object)
|
||||
{
|
||||
SettingsKey *self = SETTINGS_KEY (object);
|
||||
|
||||
g_object_unref (self->settings);
|
||||
g_settings_schema_key_unref (self->key);
|
||||
|
||||
G_OBJECT_CLASS (settings_key_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_class_init (SettingsKeyClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = settings_key_finalize;
|
||||
gobject_class->get_property = settings_key_get_property;
|
||||
|
||||
properties[PROP_DESCRIPTION] =
|
||||
g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_SETTINGS] =
|
||||
g_param_spec_object ("settings", NULL, NULL, G_TYPE_SETTINGS, G_PARAM_READABLE);
|
||||
properties[PROP_SUMMARY] =
|
||||
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_VALUE] =
|
||||
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_TYPE] =
|
||||
g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
properties[PROP_DEFAULT_VALUE] =
|
||||
g_param_spec_string ("default-value", NULL, NULL, NULL, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_key_init (SettingsKey *self)
|
||||
{
|
||||
}
|
||||
|
||||
SettingsKey *
|
||||
settings_key_new (GSettings *settings,
|
||||
GSettingsSchemaKey *key)
|
||||
{
|
||||
SettingsKey *result = g_object_new (SETTINGS_TYPE_KEY, NULL);
|
||||
|
||||
result->settings = g_object_ref (settings);
|
||||
result->key = g_settings_schema_key_ref (key);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GSettingsSchemaKey *
|
||||
settings_key_get_key (SettingsKey *self)
|
||||
{
|
||||
return self->key;
|
||||
}
|
||||
|
||||
GSettings *
|
||||
settings_key_get_settings (SettingsKey *self)
|
||||
{
|
||||
return self->settings;
|
||||
}
|
||||
|
||||
char *
|
||||
settings_key_get_search_string (SettingsKey *self)
|
||||
{
|
||||
char *schema, *result;
|
||||
|
||||
g_object_get (self->settings, "schema-id", &schema, NULL);
|
||||
|
||||
result = g_strconcat (g_settings_schema_key_get_name (self->key), " ",
|
||||
g_settings_schema_key_get_summary (self->key), " ",
|
||||
schema,
|
||||
NULL);
|
||||
|
||||
g_free (schema);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
|
||||
typedef struct _SettingsKey SettingsKey;
|
||||
#define SETTINGS_TYPE_KEY (settings_key_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (SettingsKey, settings_key, SETTINGS, KEY, GObject);
|
||||
|
||||
SettingsKey * settings_key_new (GSettings *settings,
|
||||
GSettingsSchemaKey *key);
|
||||
|
||||
GSettingsSchemaKey * settings_key_get_key (SettingsKey *self);
|
||||
GSettings * settings_key_get_settings (SettingsKey *self);
|
||||
char * settings_key_get_search_string (SettingsKey *self);
|
@@ -22,7 +22,6 @@ show_shortcuts (GtkWidget *window,
|
||||
gtk_window_set_transient_for (GTK_WINDOW (overlay), GTK_WINDOW (window));
|
||||
g_object_set (overlay, "view-name", view, NULL);
|
||||
g_object_unref (builder);
|
||||
gtk_window_present (GTK_WINDOW (overlay));
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT void
|
||||
|
@@ -28,14 +28,14 @@ add_row (GtkGrid *table,
|
||||
|
||||
label = gtk_label_new_with_mnemonic (label_text);
|
||||
gtk_widget_set_halign (label, GTK_ALIGN_START);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (table, label, 0, row, 1, 1);
|
||||
|
||||
dropdown = gtk_drop_down_new_from_strings (options);
|
||||
gtk_label_set_mnemonic_widget (GTK_LABEL (label), dropdown);
|
||||
gtk_widget_set_halign (dropdown, GTK_ALIGN_END);
|
||||
gtk_widget_set_valign (dropdown, GTK_ALIGN_BASELINE_FILL);
|
||||
gtk_widget_set_valign (dropdown, GTK_ALIGN_BASELINE);
|
||||
gtk_size_group_add_widget (size_group, dropdown);
|
||||
gtk_grid_attach (table, dropdown, 1, row, 1, 1);
|
||||
}
|
||||
|
@@ -471,7 +471,7 @@ suggestion_entry_size_allocate (GtkWidget *widget,
|
||||
&(GtkAllocation) { width - arrow_nat, 0, arrow_nat, height },
|
||||
baseline);
|
||||
|
||||
gtk_widget_set_size_request (self->popup, gtk_widget_get_width (GTK_WIDGET (self)), -1);
|
||||
gtk_widget_set_size_request (self->popup, gtk_widget_get_allocated_width (GTK_WIDGET (self)), -1);
|
||||
gtk_widget_queue_resize (self->popup);
|
||||
|
||||
gtk_popover_present (GTK_POPOVER (self->popup));
|
||||
@@ -849,7 +849,7 @@ suggestion_entry_init (SuggestionEntry *self)
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/listview_selections/suggestionentry.css");
|
||||
gtk_css_provider_load_from_resource (provider, "/dropdown/suggestionentry.css");
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
800);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* Overlay/Transparency
|
||||
* #Keywords: GtkOverlay, GtkSnapshot, blur
|
||||
* #Keywords: GtkOverlay, GtkSnapshot
|
||||
*
|
||||
* Blur the background behind an overlay.
|
||||
*/
|
||||
|
@@ -8,7 +8,7 @@ iconbrowser_sources = [
|
||||
|
||||
iconbrowser_resources = gnome.compile_resources('iconbrowser_resources',
|
||||
'iconbrowser.gresource.xml',
|
||||
source_dir: meson.current_source_dir(),
|
||||
source_dir: '.',
|
||||
)
|
||||
|
||||
executable('gtk4-icon-browser',
|
||||
|
@@ -1,5 +1,5 @@
|
||||
gen_demo_header = find_program('../build-aux/meson/gen-demo-header.py')
|
||||
demo_profile = get_option('demo-profile')
|
||||
demo_profile = get_option('profile')
|
||||
|
||||
demo_conf_h = declare_dependency(
|
||||
sources: custom_target('demo-header',
|
||||
|
@@ -78,8 +78,6 @@ gtk_renderer_paintable_paintable_snapshot (GdkPaintable *paintable,
|
||||
|
||||
gdk_paintable_snapshot (GDK_PAINTABLE (texture), snapshot, width, height);
|
||||
g_object_unref (texture);
|
||||
|
||||
gsk_render_node_unref (node);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@@ -7,7 +7,7 @@ node_editor_sources = [
|
||||
|
||||
node_editor_resources = gnome.compile_resources('node_editor_resources',
|
||||
'node-editor.gresource.xml',
|
||||
source_dir: meson.current_source_dir(),
|
||||
source_dir: '.',
|
||||
)
|
||||
|
||||
executable('gtk4-node-editor',
|
||||
|
@@ -201,7 +201,7 @@ node_editor_application_startup (GApplication *app)
|
||||
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (provider, css);
|
||||
gtk_css_provider_load_from_data (provider, css, -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
@@ -32,11 +32,6 @@
|
||||
#include "gsk/vulkan/gskvulkanrenderer.h"
|
||||
#endif
|
||||
|
||||
#include <cairo.h>
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
#include <cairo-svg.h>
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gsize start_chars;
|
||||
@@ -64,7 +59,6 @@ struct _NodeEditorWindow
|
||||
GListStore *renderers;
|
||||
GskRenderNode *node;
|
||||
|
||||
GFile *file;
|
||||
GFileMonitor *file_monitor;
|
||||
|
||||
GArray *errors;
|
||||
@@ -175,7 +169,6 @@ text_changed (GtkTextBuffer *buffer,
|
||||
GtkTextIter iter;
|
||||
GtkTextIter start, end;
|
||||
float scale;
|
||||
GskRenderNode *big_node;
|
||||
|
||||
g_array_remove_range (self->errors, 0, self->errors->len);
|
||||
text = get_current_text (self->text_buffer);
|
||||
@@ -188,18 +181,13 @@ text_changed (GtkTextBuffer *buffer,
|
||||
self->node = gsk_render_node_deserialize (bytes, deserialize_error_func, self);
|
||||
|
||||
scale = gtk_scale_button_get_value (GTK_SCALE_BUTTON (self->scale_scale));
|
||||
if (self->node && scale != 0.)
|
||||
if (self->node && scale != 1.0)
|
||||
{
|
||||
scale = pow (2., scale);
|
||||
big_node = gsk_transform_node_new (self->node, gsk_transform_scale (NULL, scale, scale));
|
||||
}
|
||||
else if (self->node)
|
||||
{
|
||||
big_node = gsk_render_node_ref (self->node);
|
||||
}
|
||||
else
|
||||
{
|
||||
big_node = NULL;
|
||||
GskRenderNode *node;
|
||||
|
||||
node = gsk_transform_node_new (self->node, gsk_transform_scale (NULL, scale, scale));
|
||||
gsk_render_node_unref (self->node);
|
||||
self->node = node;
|
||||
}
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
@@ -211,27 +199,18 @@ text_changed (GtkTextBuffer *buffer,
|
||||
graphene_rect_t bounds;
|
||||
guint i;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gsk_render_node_get_bounds (big_node, &bounds);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
|
||||
gtk_snapshot_append_node (snapshot, big_node);
|
||||
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
|
||||
g_clear_object (&paintable);
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gsk_render_node_get_bounds (self->node, &bounds);
|
||||
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (- bounds.origin.x, - bounds.origin.y));
|
||||
gtk_snapshot_append_node (snapshot, self->node);
|
||||
paintable = gtk_snapshot_free_to_paintable (snapshot, &bounds.size);
|
||||
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->picture), paintable);
|
||||
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (self->renderers)); i++)
|
||||
{
|
||||
gpointer item = g_list_model_get_item (G_LIST_MODEL (self->renderers), i);
|
||||
gtk_renderer_paintable_set_paintable (item, paintable);
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
g_clear_object (&paintable);
|
||||
}
|
||||
else
|
||||
@@ -239,8 +218,6 @@ text_changed (GtkTextBuffer *buffer,
|
||||
gtk_picture_set_paintable (GTK_PICTURE (self->picture), NULL);
|
||||
}
|
||||
|
||||
g_clear_pointer (&big_node, gsk_render_node_unref);
|
||||
|
||||
gtk_text_buffer_get_start_iter (self->text_buffer, &iter);
|
||||
|
||||
while (!gtk_text_iter_is_end (&iter))
|
||||
@@ -545,14 +522,12 @@ node_editor_window_load (NodeEditorWindow *self,
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
g_clear_object (&self->file);
|
||||
g_clear_object (&self->file_monitor);
|
||||
|
||||
if (!load_file_contents (self, file))
|
||||
return FALSE;
|
||||
|
||||
self->file = g_object_ref (file);
|
||||
self->file_monitor = g_file_monitor_file (self->file, G_FILE_MONITOR_NONE, NULL, &error);
|
||||
self->file_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
@@ -589,21 +564,13 @@ static void
|
||||
show_open_filechooser (NodeEditorWindow *self)
|
||||
{
|
||||
GtkFileDialog *dialog;
|
||||
GFile *cwd;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (dialog, "Open node file");
|
||||
if (self->file)
|
||||
{
|
||||
gtk_file_dialog_set_initial_file (dialog, self->file);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFile *cwd;
|
||||
cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
g_object_unref (cwd);
|
||||
}
|
||||
|
||||
cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
g_object_unref (cwd);
|
||||
gtk_file_dialog_open (dialog, GTK_WINDOW (self),
|
||||
NULL, open_response_cb, self);
|
||||
g_object_unref (dialog);
|
||||
@@ -661,21 +628,14 @@ save_cb (GtkWidget *button,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GtkFileDialog *dialog;
|
||||
GFile *cwd;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (dialog, "Save node");
|
||||
if (self->file)
|
||||
{
|
||||
gtk_file_dialog_set_initial_file (dialog, self->file);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFile *cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
gtk_file_dialog_set_initial_name (dialog, "demo.node");
|
||||
g_object_unref (cwd);
|
||||
}
|
||||
|
||||
cwd = g_file_new_for_path (".");
|
||||
gtk_file_dialog_set_initial_folder (dialog, cwd);
|
||||
gtk_file_dialog_set_initial_name (dialog, "demo.node");
|
||||
g_object_unref (cwd);
|
||||
gtk_file_dialog_save (dialog,
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
NULL,
|
||||
@@ -683,34 +643,23 @@ save_cb (GtkWidget *button,
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
create_node (NodeEditorWindow *self)
|
||||
static GdkTexture *
|
||||
create_texture (NodeEditorWindow *self)
|
||||
{
|
||||
GdkPaintable *paintable;
|
||||
GtkSnapshot *snapshot;
|
||||
GskRenderer *renderer;
|
||||
GskRenderNode *node;
|
||||
GdkTexture *texture;
|
||||
|
||||
paintable = gtk_picture_get_paintable (GTK_PICTURE (self->picture));
|
||||
if (paintable == NULL ||
|
||||
gdk_paintable_get_intrinsic_width (paintable) <= 0 ||
|
||||
gdk_paintable_get_intrinsic_height (paintable) <= 0)
|
||||
return NULL;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
gdk_paintable_snapshot (paintable, snapshot, gdk_paintable_get_intrinsic_width (paintable), gdk_paintable_get_intrinsic_height (paintable));
|
||||
node = gtk_snapshot_free_to_node (snapshot);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
create_texture (NodeEditorWindow *self)
|
||||
{
|
||||
GskRenderer *renderer;
|
||||
GskRenderNode *node;
|
||||
GdkTexture *texture;
|
||||
|
||||
node = create_node (self);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -721,58 +670,6 @@ create_texture (NodeEditorWindow *self)
|
||||
return texture;
|
||||
}
|
||||
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
static cairo_status_t
|
||||
cairo_serializer_write (gpointer user_data,
|
||||
const unsigned char *data,
|
||||
unsigned int length)
|
||||
{
|
||||
g_byte_array_append (user_data, data, length);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
create_svg (GskRenderNode *node,
|
||||
GError **error)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_t *cr;
|
||||
graphene_rect_t bounds;
|
||||
GByteArray *array;
|
||||
|
||||
gsk_render_node_get_bounds (node, &bounds);
|
||||
array = g_byte_array_new ();
|
||||
|
||||
surface = cairo_svg_surface_create_for_stream (cairo_serializer_write,
|
||||
array,
|
||||
bounds.size.width,
|
||||
bounds.size.height);
|
||||
cairo_svg_surface_set_document_unit (surface, CAIRO_SVG_UNIT_PX);
|
||||
cairo_surface_set_device_offset (surface, -bounds.origin.x, -bounds.origin.y);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
gsk_render_node_draw (node, cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
cairo_surface_destroy (surface);
|
||||
return g_byte_array_free_to_bytes (array);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"%s", cairo_status_to_string (cairo_surface_status (surface)));
|
||||
cairo_surface_destroy (surface);
|
||||
g_byte_array_unref (array);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static GdkTexture *
|
||||
create_cairo_texture (NodeEditorWindow *self)
|
||||
{
|
||||
@@ -805,140 +702,50 @@ create_cairo_texture (NodeEditorWindow *self)
|
||||
}
|
||||
|
||||
static void
|
||||
export_image_saved_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_file_replace_contents_finish (G_FILE (source), result, NULL, &error))
|
||||
{
|
||||
GtkAlertDialog *alert;
|
||||
|
||||
alert = gtk_alert_dialog_new ("Exporting to image failed");
|
||||
gtk_alert_dialog_set_detail (alert, error->message);
|
||||
gtk_alert_dialog_show (alert, NULL);
|
||||
g_object_unref (alert);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
export_image_response_cb (GObject *source,
|
||||
export_image_response_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
void *user_data)
|
||||
void *user_data)
|
||||
{
|
||||
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
|
||||
GskRenderNode *node = user_data;
|
||||
GdkTexture *texture = user_data;
|
||||
GFile *file;
|
||||
char *uri;
|
||||
GBytes *bytes;
|
||||
|
||||
file = gtk_file_dialog_save_finish (dialog, result, NULL);
|
||||
if (file == NULL)
|
||||
if (file)
|
||||
{
|
||||
gsk_render_node_unref (node);
|
||||
return;
|
||||
}
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
#ifdef CAIRO_HAS_SVG_SURFACE
|
||||
if (g_str_has_suffix (uri, "svg"))
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
bytes = create_svg (node, &error);
|
||||
if (bytes == NULL)
|
||||
if (!gdk_texture_save_to_png (texture, g_file_peek_path (file)))
|
||||
{
|
||||
GtkAlertDialog *alert;
|
||||
|
||||
alert = gtk_alert_dialog_new ("Exporting to image failed");
|
||||
gtk_alert_dialog_set_detail (alert, error->message);
|
||||
gtk_alert_dialog_show (alert, NULL);
|
||||
gtk_alert_dialog_show (alert, GTK_WINDOW (gtk_window_get_transient_for (GTK_WINDOW (dialog))));
|
||||
g_object_unref (alert);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GskRenderer *renderer;
|
||||
|
||||
renderer = gsk_gl_renderer_new ();
|
||||
if (!gsk_renderer_realize (renderer, NULL, NULL))
|
||||
{
|
||||
g_object_unref (renderer);
|
||||
renderer = gsk_cairo_renderer_new ();
|
||||
if (!gsk_renderer_realize (renderer, NULL, NULL))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
texture = gsk_renderer_render_texture (renderer, node, NULL);
|
||||
gsk_renderer_unrealize (renderer);
|
||||
g_object_unref (renderer);
|
||||
|
||||
if (g_str_has_suffix (uri, "tiff"))
|
||||
bytes = gdk_texture_save_to_tiff_bytes (texture);
|
||||
else
|
||||
bytes = gdk_texture_save_to_png_bytes (texture);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (file);
|
||||
}
|
||||
g_free (uri);
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
g_file_replace_contents_bytes_async (file,
|
||||
bytes,
|
||||
NULL,
|
||||
FALSE,
|
||||
0,
|
||||
NULL,
|
||||
export_image_saved_cb,
|
||||
NULL);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
gsk_render_node_unref (node);
|
||||
g_object_unref (file);
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
export_image_cb (GtkWidget *button,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GskRenderNode *node;
|
||||
GdkTexture *texture;
|
||||
GtkFileDialog *dialog;
|
||||
GtkFileFilter *filter;
|
||||
GListStore *filters;
|
||||
|
||||
node = create_node (self);
|
||||
if (node == NULL)
|
||||
texture = create_texture (self);
|
||||
if (texture == NULL)
|
||||
return;
|
||||
|
||||
filters = g_list_store_new (GTK_TYPE_FILE_FILTER);
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_add_mime_type (filter, "image/png");
|
||||
g_list_store_append (filters, filter);
|
||||
g_object_unref (filter);
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_add_mime_type (filter, "image/svg+xml");
|
||||
g_list_store_append (filters, filter);
|
||||
g_object_unref (filter);
|
||||
filter = gtk_file_filter_new ();
|
||||
gtk_file_filter_add_mime_type (filter, "image/tiff");
|
||||
g_list_store_append (filters, filter);
|
||||
g_object_unref (filter);
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_title (dialog, "");
|
||||
gtk_file_dialog_set_initial_name (dialog, "example.png");
|
||||
gtk_file_dialog_set_filters (dialog, G_LIST_MODEL (filters));
|
||||
gtk_file_dialog_save (dialog,
|
||||
GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (button))),
|
||||
NULL,
|
||||
export_image_response_cb, node);
|
||||
g_object_unref (filters);
|
||||
export_image_response_cb, texture);
|
||||
g_object_unref (dialog);
|
||||
}
|
||||
|
||||
@@ -1052,19 +859,6 @@ testcase_save_clicked_cb (GtkWidget *button,
|
||||
}
|
||||
|
||||
text = get_current_text (self->text_buffer);
|
||||
{
|
||||
GBytes *bytes;
|
||||
GskRenderNode *node;
|
||||
gsize size;
|
||||
|
||||
bytes = g_bytes_new_take (text, strlen (text) + 1);
|
||||
node = gsk_render_node_deserialize (bytes, NULL, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
bytes = gsk_render_node_serialize (node);
|
||||
gsk_render_node_unref (node);
|
||||
text = g_bytes_unref_to_data (bytes, &size);
|
||||
}
|
||||
|
||||
if (!g_file_set_contents (node_file, text, -1, &error))
|
||||
{
|
||||
gtk_label_set_label (GTK_LABEL (self->testcase_error_label), error->message);
|
||||
@@ -1109,8 +903,6 @@ node_editor_window_finalize (GObject *object)
|
||||
|
||||
g_clear_pointer (&self->node, gsk_render_node_unref);
|
||||
g_clear_object (&self->renderers);
|
||||
g_clear_object (&self->file_monitor);
|
||||
g_clear_object (&self->file);
|
||||
|
||||
G_OBJECT_CLASS (node_editor_window_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -1190,362 +982,11 @@ node_editor_window_unrealize (GtkWidget *widget)
|
||||
GTK_WIDGET_CLASS (node_editor_window_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NodeEditorWindow *self;
|
||||
GtkTextIter start, end;
|
||||
} Selection;
|
||||
|
||||
static void
|
||||
color_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkColorDialog *dialog = GTK_COLOR_DIALOG (source);
|
||||
Selection *selection = data;
|
||||
NodeEditorWindow *self = selection->self;
|
||||
GdkRGBA *color;
|
||||
char *text;
|
||||
GError *error = NULL;
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
color = gtk_color_dialog_choose_rgba_finish (dialog, result, &error);
|
||||
if (!color)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_free (selection);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
|
||||
text = gdk_rgba_to_string (color);
|
||||
gtk_text_buffer_delete (buffer, &selection->start, &selection->end);
|
||||
gtk_text_buffer_insert (buffer, &selection->start, text, -1);
|
||||
|
||||
g_free (text);
|
||||
gdk_rgba_free (color);
|
||||
g_free (selection);
|
||||
}
|
||||
|
||||
static void
|
||||
font_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFontDialog *dialog = GTK_FONT_DIALOG (source);
|
||||
Selection *selection = data;
|
||||
NodeEditorWindow *self = selection->self;
|
||||
GError *error = NULL;
|
||||
PangoFontDescription *desc;
|
||||
GtkTextBuffer *buffer;
|
||||
char *text;
|
||||
|
||||
desc = gtk_font_dialog_choose_font_finish (dialog, result, &error);
|
||||
if (!desc)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_free (selection);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
|
||||
text = pango_font_description_to_string (desc);
|
||||
gtk_text_buffer_delete (buffer, &selection->start, &selection->end);
|
||||
gtk_text_buffer_insert (buffer, &selection->start, text, -1);
|
||||
|
||||
g_free (text);
|
||||
pango_font_description_free (desc);
|
||||
g_free (selection);
|
||||
}
|
||||
|
||||
static void
|
||||
file_cb (GObject *source,
|
||||
GAsyncResult *result,
|
||||
gpointer data)
|
||||
{
|
||||
GtkFileDialog *dialog = GTK_FILE_DIALOG (source);
|
||||
Selection *selection = data;
|
||||
NodeEditorWindow *self = selection->self;
|
||||
GError *error = NULL;
|
||||
GFile *file;
|
||||
GtkTextBuffer *buffer;
|
||||
char *text;
|
||||
|
||||
file = gtk_file_dialog_open_finish (dialog, result, &error);
|
||||
if (!file)
|
||||
{
|
||||
g_print ("%s\n", error->message);
|
||||
g_error_free (error);
|
||||
g_free (selection);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
|
||||
text = g_file_get_uri (file);
|
||||
gtk_text_buffer_delete (buffer, &selection->start, &selection->end);
|
||||
gtk_text_buffer_insert (buffer, &selection->start, text, -1);
|
||||
|
||||
g_free (text);
|
||||
g_object_unref (file);
|
||||
g_free (selection);
|
||||
}
|
||||
|
||||
static void
|
||||
key_pressed (GtkEventControllerKey *controller,
|
||||
unsigned int keyval,
|
||||
unsigned int keycode,
|
||||
GdkModifierType state,
|
||||
gpointer data)
|
||||
{
|
||||
GtkWidget *dd = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (controller));
|
||||
Selection *selection = data;
|
||||
NodeEditorWindow *self = selection->self;
|
||||
unsigned int selected;
|
||||
GtkStringList *strings;
|
||||
GtkTextBuffer *buffer;
|
||||
const char *text;
|
||||
|
||||
if (keyval != GDK_KEY_Escape)
|
||||
return;
|
||||
|
||||
strings = GTK_STRING_LIST (gtk_drop_down_get_model (GTK_DROP_DOWN (dd)));
|
||||
selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dd));
|
||||
text = gtk_string_list_get_string (strings, selected);
|
||||
|
||||
gtk_text_view_remove (GTK_TEXT_VIEW (self->text_view), dd);
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
gtk_text_iter_backward_search (&selection->start, "mode:", 0, NULL, &selection->start, NULL);
|
||||
gtk_text_iter_forward_search (&selection->start, ";", 0, &selection->end, NULL, NULL);
|
||||
gtk_text_buffer_delete (buffer, &selection->start, &selection->end);
|
||||
gtk_text_buffer_insert (buffer, &selection->start, " ", -1);
|
||||
gtk_text_buffer_insert (buffer, &selection->start, text, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_edit (NodeEditorWindow *self,
|
||||
GtkTextIter *iter)
|
||||
{
|
||||
GtkTextIter start, end;
|
||||
GtkTextBuffer *buffer;
|
||||
Selection *selection;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
|
||||
gtk_text_iter_set_line_offset (iter, 0);
|
||||
|
||||
if (gtk_text_iter_forward_search (iter, ";", 0, &end, NULL, NULL) &&
|
||||
gtk_text_iter_forward_search (iter, "color:", 0, NULL, &start, &end))
|
||||
{
|
||||
GtkColorDialog *dialog;
|
||||
GdkRGBA color;
|
||||
char *text;
|
||||
|
||||
while (g_unichar_isspace (gtk_text_iter_get_char (&start)))
|
||||
gtk_text_iter_forward_char (&start);
|
||||
|
||||
gtk_text_buffer_select_range (buffer, &start, &end);
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
|
||||
gdk_rgba_parse (&color, text);
|
||||
g_free (text);
|
||||
|
||||
selection = g_new0 (Selection, 1);
|
||||
selection->self = self;
|
||||
selection->start = start;
|
||||
selection->end = end;
|
||||
|
||||
dialog = gtk_color_dialog_new ();
|
||||
gtk_color_dialog_choose_rgba (dialog, GTK_WINDOW (self), &color, NULL, color_cb, selection);
|
||||
}
|
||||
else if (gtk_text_iter_forward_search (iter, ";", 0, &end, NULL, NULL) &&
|
||||
gtk_text_iter_forward_search (iter, "font:", 0, NULL, &start, &end))
|
||||
{
|
||||
GtkFontDialog *dialog;
|
||||
PangoFontDescription *desc;
|
||||
char *text;
|
||||
|
||||
while (g_unichar_isspace (gtk_text_iter_get_char (&start)))
|
||||
gtk_text_iter_forward_char (&start);
|
||||
|
||||
/* Skip the quotes */
|
||||
gtk_text_iter_forward_char (&start);
|
||||
gtk_text_iter_backward_char (&end);
|
||||
|
||||
gtk_text_buffer_select_range (buffer, &start, &end);
|
||||
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
|
||||
desc = pango_font_description_from_string (text);
|
||||
g_free (text);
|
||||
|
||||
selection = g_new0 (Selection, 1);
|
||||
selection->self = self;
|
||||
selection->start = start;
|
||||
selection->end = end;
|
||||
|
||||
dialog = gtk_font_dialog_new ();
|
||||
gtk_font_dialog_choose_font (dialog, GTK_WINDOW (self), desc, NULL, font_cb, selection);
|
||||
pango_font_description_free (desc);
|
||||
}
|
||||
else if (gtk_text_iter_forward_search (iter, ";", 0, &end, NULL, NULL) &&
|
||||
gtk_text_iter_forward_search (iter, "mode:", 0, NULL, &start, &end))
|
||||
{
|
||||
/* Assume we have a blend node, for now */
|
||||
GEnumClass *class;
|
||||
GtkStringList *strings;
|
||||
GtkWidget *dd;
|
||||
GtkTextChildAnchor *anchor;
|
||||
unsigned int selected = 0;
|
||||
GtkEventController *key_controller;
|
||||
gboolean is_blend_mode = FALSE;
|
||||
char *text;
|
||||
|
||||
while (g_unichar_isspace (gtk_text_iter_get_char (&start)))
|
||||
gtk_text_iter_forward_char (&start);
|
||||
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
|
||||
|
||||
strings = gtk_string_list_new (NULL);
|
||||
class = g_type_class_ref (GSK_TYPE_BLEND_MODE);
|
||||
for (unsigned int i = 0; i < class->n_values; i++)
|
||||
{
|
||||
if (strcmp (class->values[i].value_nick, text) == 0)
|
||||
is_blend_mode = TRUE;
|
||||
}
|
||||
g_type_class_unref (class);
|
||||
|
||||
if (is_blend_mode)
|
||||
class = g_type_class_ref (GSK_TYPE_BLEND_MODE);
|
||||
else
|
||||
class = g_type_class_ref (GSK_TYPE_MASK_MODE);
|
||||
|
||||
for (unsigned int i = 0; i < class->n_values; i++)
|
||||
{
|
||||
if (i == 0 && is_blend_mode)
|
||||
gtk_string_list_append (strings, "normal");
|
||||
else
|
||||
gtk_string_list_append (strings, class->values[i].value_nick);
|
||||
|
||||
if (strcmp (class->values[i].value_nick, text) == 0)
|
||||
selected = i;
|
||||
}
|
||||
g_type_class_unref (class);
|
||||
|
||||
gtk_text_buffer_delete (buffer, &start, &end);
|
||||
|
||||
anchor = gtk_text_buffer_create_child_anchor (buffer, &start);
|
||||
dd = gtk_drop_down_new (G_LIST_MODEL (strings), NULL);
|
||||
gtk_drop_down_set_selected (GTK_DROP_DOWN (dd), selected);
|
||||
gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (self->text_view), dd, anchor);
|
||||
|
||||
selection = g_new0 (Selection, 1);
|
||||
selection->self = self;
|
||||
selection->start = start;
|
||||
selection->end = end;
|
||||
|
||||
key_controller = gtk_event_controller_key_new ();
|
||||
g_signal_connect (key_controller, "key-pressed", G_CALLBACK (key_pressed), selection);
|
||||
gtk_widget_add_controller (dd, key_controller);
|
||||
}
|
||||
else if (gtk_text_iter_forward_search (iter, ";", 0, &end, NULL, NULL) &&
|
||||
gtk_text_iter_forward_search (iter, "texture:", 0, NULL, &start, &end))
|
||||
{
|
||||
GtkFileDialog *dialog;
|
||||
GtkTextIter skip;
|
||||
char *text;
|
||||
GFile *file;
|
||||
|
||||
while (g_unichar_isspace (gtk_text_iter_get_char (&start)))
|
||||
gtk_text_iter_forward_char (&start);
|
||||
|
||||
skip = start;
|
||||
gtk_text_iter_forward_chars (&skip, strlen ("url(\""));
|
||||
text = gtk_text_iter_get_text (&start, &skip);
|
||||
if (strcmp (text, "url(\"") != 0)
|
||||
{
|
||||
g_free (text);
|
||||
return;
|
||||
}
|
||||
g_free (text);
|
||||
start = skip;
|
||||
|
||||
skip = end;
|
||||
gtk_text_iter_backward_chars (&skip, strlen ("\")"));
|
||||
text = gtk_text_iter_get_text (&skip, &end);
|
||||
if (strcmp (text, "\")") != 0)
|
||||
{
|
||||
g_free (text);
|
||||
return;
|
||||
}
|
||||
g_free (text);
|
||||
end = skip;
|
||||
|
||||
gtk_text_buffer_select_range (buffer, &start, &end);
|
||||
|
||||
text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE);
|
||||
file = g_file_new_for_uri (text);
|
||||
g_free (text);
|
||||
|
||||
selection = g_new0 (Selection, 1);
|
||||
selection->self = self;
|
||||
selection->start = start;
|
||||
selection->end = end;
|
||||
|
||||
dialog = gtk_file_dialog_new ();
|
||||
gtk_file_dialog_set_initial_file (dialog, file);
|
||||
gtk_file_dialog_open (dialog, GTK_WINDOW (self), NULL, file_cb, selection);
|
||||
g_object_unref (file);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
click_gesture_pressed (GtkGestureClick *gesture,
|
||||
int n_press,
|
||||
double x,
|
||||
double y,
|
||||
NodeEditorWindow *self)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
int bx, by, trailing;
|
||||
GdkModifierType state;
|
||||
|
||||
state = gtk_event_controller_get_current_event_state (GTK_EVENT_CONTROLLER (gesture));
|
||||
if ((state & GDK_CONTROL_MASK) == 0)
|
||||
return;
|
||||
|
||||
gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (self->text_view), GTK_TEXT_WINDOW_TEXT, x, y, &bx, &by);
|
||||
gtk_text_view_get_iter_at_position (GTK_TEXT_VIEW (self->text_view), &iter, &trailing, bx, by);
|
||||
|
||||
node_editor_window_edit (self, &iter);
|
||||
}
|
||||
|
||||
static void
|
||||
edit_action_cb (GtkWidget *widget,
|
||||
const char *action_name,
|
||||
GVariant *parameter)
|
||||
{
|
||||
NodeEditorWindow *self = NODE_EDITOR_WINDOW (widget);
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter start, end;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->text_view));
|
||||
gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
|
||||
|
||||
node_editor_window_edit (self, &start);
|
||||
}
|
||||
|
||||
static void
|
||||
node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GtkShortcutTrigger *trigger;
|
||||
GtkShortcutAction *action;
|
||||
GtkShortcut *shortcut;
|
||||
|
||||
object_class->dispose = node_editor_window_dispose;
|
||||
object_class->finalize = node_editor_window_finalize;
|
||||
@@ -1576,14 +1017,6 @@ node_editor_window_class_init (NodeEditorWindowClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, dark_mode_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drag_prepare_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_picture_drop_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, click_gesture_pressed);
|
||||
|
||||
gtk_widget_class_install_action (widget_class, "smart-edit", NULL, edit_action_cb);
|
||||
|
||||
trigger = gtk_keyval_trigger_new (GDK_KEY_e, GDK_CONTROL_MASK);
|
||||
action = gtk_named_action_new ("smart-edit");
|
||||
shortcut = gtk_shortcut_new (trigger, action);
|
||||
gtk_widget_class_add_shortcut (widget_class, shortcut);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@@ -1701,13 +1134,6 @@ node_editor_window_init (NodeEditorWindow *self)
|
||||
" }\n"
|
||||
" transform: translate(0, 140);\n"
|
||||
"}", -1);
|
||||
|
||||
if (g_getenv ("GSK_RENDERER"))
|
||||
{
|
||||
char *new_title = g_strdup_printf ("GTK Node Editor - %s", g_getenv ("GSK_RENDERER"));
|
||||
gtk_window_set_title (GTK_WINDOW (self), new_title);
|
||||
g_free (new_title);
|
||||
}
|
||||
}
|
||||
|
||||
NodeEditorWindow *
|
||||
|
@@ -16,14 +16,6 @@
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
<menu id="extra_menu">
|
||||
<section>
|
||||
<item>
|
||||
<attribute name="label" translatable="yes">Assisted _Edit</attribute>
|
||||
<attribute name="action">smart-edit</attribute>
|
||||
</item>
|
||||
</section>
|
||||
</menu>
|
||||
|
||||
<object class="GtkPopover" id="testcase_popover">
|
||||
<child>
|
||||
@@ -171,9 +163,9 @@
|
||||
<property name="valign">center</property>
|
||||
<property name="adjustment">
|
||||
<object class="GtkAdjustment">
|
||||
<property name="lower">-4</property>
|
||||
<property name="value">0</property>
|
||||
<property name="upper">4</property>
|
||||
<property name="lower">1</property>
|
||||
<property name="value">1</property>
|
||||
<property name="upper">10</property>
|
||||
<property name="step-increment">0.1</property>
|
||||
<property name="page-increment">0.5</property>
|
||||
</object>
|
||||
@@ -203,17 +195,10 @@
|
||||
<property name="right-margin">6</property>
|
||||
<property name="bottom-margin">6</property>
|
||||
<property name="has-tooltip">1</property>
|
||||
<property name="extra-menu">extra_menu</property>
|
||||
<signal name="query-tooltip" handler="text_view_query_tooltip_cb"/>
|
||||
<style>
|
||||
<class name="editor" />
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkGestureClick">
|
||||
<property name="button">1</property>
|
||||
<signal name="pressed" handler="click_gesture_pressed"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -2,29 +2,19 @@
|
||||
|
||||
GSK render nodes can be serialized and deserialized using APIs such as `gsk_render_node_serialize()` and `gsk_render_node_deserialize()`. The intended use for this is development - primarily the development of GTK - by allowing things such as creating testsuites and benchmarks, exchanging nodes in bug reports. GTK includes the `gtk4-node-editor` application for creating such test files.
|
||||
|
||||
The format is a text format that follows the [CSS syntax rules](https://drafts.csswg.org/css-syntax-3/). In particular, this means that every array of bytes will produce a render node when parsed, as there is a defined error recovery method. For more details on error handling, please refer to the documentation of the parsing APIs.
|
||||
The format is a text format that follows the [CSS syntax rules](https://drafts.csswg.org/css-syntax-3/). In particular, this means that every array of bytes will produce a render node when parsed, as there is a defined error recovery method. For more details on error handling, please refer to the documentation of the aprsing APIs.
|
||||
|
||||
The grammar of a node text representation using [the CSS value definition syntax](https://drafts.csswg.org/css-values-3/#value-defs) looks like this:
|
||||
**document**: `<node>\*`
|
||||
**node**: container [ "name" ] { <document> } | `<node-type> [ "name" ] { <property>* }` | "name"
|
||||
**node**: container { <document> } | `<node-name> { <property>* }`
|
||||
**property**: `<property-name>: <node> | <value> ;`
|
||||
|
||||
Each node has its own `<node-type>` and supports a custom set of properties, each with their own `<property-name>` and syntax. The following paragraphs document each of the nodes and their properties.
|
||||
Each node has its own `<node-name>` and supports a custom set of properties, each with their own `<property-name>` and syntax. The following paragraphs document each of the nodes and their properties.
|
||||
|
||||
When serializing and the value of a property equals the default value, this value will not be serialized. Serialization aims to produce an output as small as possible.
|
||||
|
||||
To embed newlines in strings, use \A. To break a long string into multiple lines, escape the newline with a \.
|
||||
|
||||
# Names
|
||||
|
||||
### Nodes
|
||||
|
||||
Nodes can be given a name by adding a string after the `<node-type>` in their definition. That same node can then be used further down in the document by specifying just the name identifying the node.
|
||||
|
||||
### Textures
|
||||
|
||||
Just like nodes, textures can be referenced by name. When defining a named texture, the name has to be placed in front of the URL.
|
||||
|
||||
# Nodes
|
||||
|
||||
### container
|
||||
@@ -193,7 +183,7 @@ Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| source | `<node>` | color { } | always |
|
||||
| mode | `<mask-mode>` | alpha | non-default |
|
||||
| mode | `<blend-mode>` | alpha | non-default |
|
||||
| mask | `<node>` | color { } | always |
|
||||
|
||||
Creates a node like `gsk_mask_node_new()` with the given properties.
|
||||
|
@@ -69,7 +69,7 @@ if not meson.is_cross_build() and build_machine.cpu_family() != 'arm' and build_
|
||||
else
|
||||
widgetfactory_resources = gnome.compile_resources('widgetfactory_resources',
|
||||
'widget-factory.gresource.xml',
|
||||
source_dir: meson.current_source_dir(),
|
||||
source_dir: '.',
|
||||
)
|
||||
endif
|
||||
|
||||
|
@@ -1210,12 +1210,12 @@ typedef struct {
|
||||
static void
|
||||
add_background (GtkWidget *flowbox,
|
||||
const char *filename,
|
||||
GdkTexture *texture,
|
||||
GdkPixbuf *pixbuf,
|
||||
gboolean is_resource)
|
||||
{
|
||||
GtkWidget *child;
|
||||
|
||||
child = gtk_picture_new_for_paintable (GDK_PAINTABLE (texture));
|
||||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||||
gtk_widget_set_size_request (child, 110, 70);
|
||||
gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), child, -1);
|
||||
child = gtk_widget_get_parent (child);
|
||||
@@ -1231,7 +1231,6 @@ background_loaded_cb (GObject *source,
|
||||
{
|
||||
BackgroundData *bd = data;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
pixbuf = gdk_pixbuf_new_from_stream_finish (res, &error);
|
||||
@@ -1242,11 +1241,8 @@ background_loaded_cb (GObject *source,
|
||||
return;
|
||||
}
|
||||
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
add_background (bd->flowbox, bd->filename, texture, FALSE);
|
||||
add_background (bd->flowbox, bd->filename, pixbuf, FALSE);
|
||||
|
||||
g_object_unref (texture);
|
||||
g_object_unref (pixbuf);
|
||||
g_free (bd->filename);
|
||||
g_free (bd);
|
||||
}
|
||||
@@ -1263,10 +1259,7 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
GInputStream *stream;
|
||||
BackgroundData *bd;
|
||||
GdkPixbuf *pixbuf;
|
||||
GdkTexture *texture;
|
||||
GtkWidget *child;
|
||||
guchar *data;
|
||||
GBytes *bytes;
|
||||
int i;
|
||||
const char *resources[] = {
|
||||
"sunset.jpg", "portland-rose.jpg", "beach.jpg", "nyc.jpg"
|
||||
@@ -1277,14 +1270,9 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
|
||||
g_object_set_data (G_OBJECT (flowbox), "populated", GUINT_TO_POINTER (1));
|
||||
|
||||
data = g_malloc (4 * 110 * 70);
|
||||
memset (data, 0xff, 4 * 110 * 70);
|
||||
bytes = g_bytes_new_take (data, 4 * 110 * 70);
|
||||
texture = gdk_memory_texture_new (110, 70, GDK_MEMORY_DEFAULT, bytes, 4 * 110);
|
||||
child = gtk_picture_new_for_paintable (GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 110, 70);
|
||||
gdk_pixbuf_fill (pixbuf, 0xffffffff);
|
||||
child = gtk_picture_new_for_pixbuf (pixbuf);
|
||||
gtk_widget_add_css_class (child, "frame");
|
||||
gtk_flow_box_insert (GTK_FLOW_BOX (flowbox), child, -1);
|
||||
|
||||
@@ -1292,10 +1280,7 @@ populate_flowbox (GtkWidget *flowbox)
|
||||
{
|
||||
filename = g_strconcat ("/org/gtk/WidgetFactory4/", resources[i], NULL);
|
||||
pixbuf = gdk_pixbuf_new_from_resource_at_scale (filename, 110, 110, TRUE, NULL);
|
||||
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
||||
add_background (flowbox, filename, texture, TRUE);
|
||||
g_object_unref (texture);
|
||||
g_object_unref (pixbuf);
|
||||
add_background (flowbox, filename, pixbuf, TRUE);
|
||||
}
|
||||
|
||||
location = "/usr/share/backgrounds/gnome";
|
||||
|
@@ -2244,24 +2244,20 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="lockbox">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="open_menubutton">
|
||||
<property name="halign">3</property>
|
||||
<property name="popover">open_popover</property>
|
||||
<property name="label">Open</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="record_button">
|
||||
<property name="halign">3</property>
|
||||
<property name="valign">center</property>
|
||||
<signal name="toggled" handler="on_record_button_toggled"/>
|
||||
<style>
|
||||
<class name="text-button"/>
|
||||
@@ -2271,19 +2267,16 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="valign">4</property>
|
||||
<property name="icon-name">media-record-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="valign">4</property>
|
||||
<property name="label">Record</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -2292,7 +2285,6 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="linked"/>
|
||||
</style>
|
||||
@@ -2300,14 +2292,12 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
<object class="GtkToggleButton" id="grid_button">
|
||||
<property name="active">1</property>
|
||||
<property name="icon-name">view-grid-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="list_button">
|
||||
<property name="group">grid_button</property>
|
||||
<property name="icon-name">view-list-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -2315,7 +2305,6 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="circular_button">
|
||||
<property name="icon-name">emblem-system-symbolic</property>
|
||||
<property name="valign">center</property>
|
||||
<style>
|
||||
<class name="circular"/>
|
||||
</style>
|
||||
@@ -2324,15 +2313,12 @@ microphone-sensitivity-medium-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLockButton" id="lockbutton">
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
<object class="GtkLockButton" id="lockbutton"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton">
|
||||
<property name="icon-name">view-more-symbolic</property>
|
||||
<property name="menu-model">new_style_menu_model</property>
|
||||
<property name="valign">center</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
@@ -500,9 +500,8 @@ Public headers should never be included directly:
|
||||
Private headers should include the public header first, if one exists:
|
||||
|
||||
```c
|
||||
#pragma once
|
||||
|
||||
/* gtkfooprivate.h */
|
||||
#ifndef __GTK_FOO_PRIVATE_H__
|
||||
#define __GTK_FOO_PRIVATE_H__
|
||||
|
||||
#include "gtkfoo.h"
|
||||
|
||||
@@ -511,8 +510,18 @@ Private headers should include the public header first, if one exists:
|
||||
#endif /* __GTK_FOO_PRIVATE_H__ */
|
||||
```
|
||||
|
||||
All headers should use the `once` pragma to prevent multiple inclusion,
|
||||
instead of the classic pre-processor guards:
|
||||
All headers should have inclusion guards:
|
||||
|
||||
```c
|
||||
#ifndef __GTK_FOO_H__
|
||||
#define __GTK_FOO_H__
|
||||
|
||||
...
|
||||
|
||||
#endif /* __GTK_FOO_H__ */
|
||||
```
|
||||
|
||||
You can also use the `once` pragma instead of the classic pre-processor guard:
|
||||
|
||||
```c
|
||||
#pragma once
|
||||
@@ -544,8 +553,6 @@ the source file, either the public installed header, or the private header, if
|
||||
it exists.
|
||||
|
||||
```c
|
||||
/* gtkfoo.c */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfoo.h"
|
||||
@@ -587,8 +594,8 @@ Finally, source files should include the system headers last:
|
||||
#include <string.h>
|
||||
```
|
||||
|
||||
Cyclic dependencies should be avoided if at all possible;
|
||||
for instance, you could use additional headers to break cycles.
|
||||
Cyclic dependencies should be avoided if at all possible; for instance, you
|
||||
could use additional headers to break cycles.
|
||||
|
||||
### GObject
|
||||
|
||||
@@ -629,8 +636,7 @@ Instance structures should only contain the parent type:
|
||||
```
|
||||
|
||||
You should use the `G_DECLARE_DERIVABLE_TYPE()` and `G_DECLARE_FINAL_TYPE()`
|
||||
macros in newly written headers. There is also a `GDK_DECLARE_INTERNAL_TYPE()`
|
||||
for declaring types that can be derived inside GTK, but not in 3rd party code.
|
||||
macros in newly written headers.
|
||||
|
||||
Inside your source file, always use the `G_DEFINE_TYPE()`,
|
||||
`G_DEFINE_TYPE_WITH_PRIVATE()`, and `G_DEFINE_TYPE_WITH_CODE()` macros, or their
|
||||
@@ -670,20 +676,13 @@ Interfaces must have the following macros:
|
||||
| `GTK_IS_<iface_name>` | `G_TYPE_CHECK_INSTANCE_TYPE` |
|
||||
| `GTK_<iface_name>_GET_IFACE` | `G_TYPE_INSTANCE_GET_INTERFACE` |
|
||||
|
||||
The `G_DECLARE` macros define these as static inline functions instead.
|
||||
|
||||
### Memory allocation
|
||||
|
||||
When dynamically allocating data on the heap use `g_new()`.
|
||||
When dynamically allocating data on the heap either use `g_new()` or,
|
||||
if allocating multiple small data structures, `g_slice_new()`.
|
||||
|
||||
Public structure types should always be returned after being zero-ed,
|
||||
either explicitly for each member, or by using `g_new0()`. Do not use
|
||||
`g_slice` in new code.
|
||||
|
||||
Memory that is only needed within the scope of a function can be
|
||||
stack-allocated using `g_newa()` or `g_alloca()`. But limit the amount
|
||||
of stack memory that you consume this way, in particular in recursive
|
||||
functions.
|
||||
either explicitly for each member, or by using `g_new0()` or `g_slice_new0()`.
|
||||
|
||||
### Macros
|
||||
|
||||
|
@@ -220,6 +220,6 @@ clipboard.cut, clipboard.copy, clipboard.paste
|
||||
selection.delete, selection.select-all
|
||||
: Selection operations on entries, text view and labels
|
||||
|
||||
color.select, color.customize
|
||||
color.select, color.customize:
|
||||
: Operate on colors in a `GtkColorChooserWidget`. These actions are
|
||||
unusual in that they have the non-trivial parameter type (dddd).
|
||||
unusual in that they have the non-trivial parameter type (dddd):
|
||||
|
@@ -6,15 +6,22 @@ Slug: broadway
|
||||
The GDK Broadway backend provides support for displaying GTK applications in
|
||||
a web browser, using HTML5 and web sockets.
|
||||
|
||||
To run your application in this way, first run the broadway server,
|
||||
`gtk-broadwayd`, that ships with GTK:
|
||||
To run your application in this way, select the Broadway backend by setting
|
||||
`GDK_BACKEND=broadway`. Then you can make your application appear in a web
|
||||
browser by pointing it at `http://127.0.0.1:8080`. Note that you need to
|
||||
enable web sockets in your web browser.
|
||||
|
||||
You can choose a different port from the default 8080 by setting the
|
||||
`BROADWAY_DISPLAY` environment variable to the port that you want to use.
|
||||
|
||||
It is also possible to use multiple GTK applications in the same web browser
|
||||
window, by using the Broadway server, `gtk4-broadwayd`, that ships with GTK.
|
||||
To start the Broadway server use:
|
||||
|
||||
```
|
||||
gtk4-broadwayd :5
|
||||
```
|
||||
|
||||
The server expects the colon-prefixed display number as a commandline argument.
|
||||
|
||||
Then point your web browser at `http://127.0.0.1:8085`.
|
||||
|
||||
Once the Broadway server is running, you can start your applications like
|
||||
@@ -24,8 +31,6 @@ this:
|
||||
GDK_BACKEND=broadway BROADWAY_DISPLAY=:5 gtk4-demo
|
||||
```
|
||||
|
||||
Multiple applications can be presented in the same web browser window.
|
||||
|
||||
## Broadway-specific environment variables
|
||||
|
||||
### `BROADWAY_DISPLAY`
|
||||
|
@@ -288,7 +288,7 @@ support.
|
||||
If you want to run the testsuite to ensure that your GTK build
|
||||
works, you should enable it with this option.
|
||||
|
||||
### `build-tests`, `build-examples`, `build-demos`
|
||||
### `build-tests`, `build-examples`, `demos`
|
||||
|
||||
By default, GTK will build quite a few tests, examples and demos.
|
||||
While these are useful on a developer system, they are not
|
||||
|
@@ -1,84 +0,0 @@
|
||||
Title: Coordinate systems
|
||||
Slug: gtk-coordinates
|
||||
|
||||
## Coordinate systems in GTK
|
||||
|
||||
All coordinate systems in GTK have the origin at the top left, with the X axis
|
||||
pointing right, and the Y axis pointing down. This matches the convention used
|
||||
in X11, Wayland and cairo, but differs from OpenGL and PostScript, where the origin
|
||||
is in the lower left, and the Y axis is pointing up.
|
||||
|
||||
Every widget in a window has its own coordinate system that it uses to place its
|
||||
child widgets and to interpret events. Most of the time, this fact can be safely
|
||||
ignored. The section will explain the details for the few cases when it is important.
|
||||
|
||||
## The box model
|
||||
|
||||
When it comes to rendering, GTK follows the CSS box model as far as practical.
|
||||
|
||||
<picture>
|
||||
<source srcset="box-model-dark.png" media="(prefers-color-scheme: dark)">
|
||||
<img alt="Box Model" src="box-model-light.png">
|
||||
</picture>
|
||||
|
||||
The CSS stylesheet that is in use determines the sizes (and appearance) of the
|
||||
margin, border and padding areas for each widget. The size of the content area
|
||||
is determined by GTKs layout algorithm using each widgets [vfunc@Gtk.Widget.measure]
|
||||
and [vfunc@Gtk.Widget.size_allocate] vfuncs.
|
||||
|
||||
You can learn more about the CSS box model by reading the
|
||||
[CSS specification](https://www.w3.org/TR/css-box-3/#box-model) or the
|
||||
Mozilla [documentation](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model).
|
||||
|
||||
To learn more about where GTK CSS differs from CSS on the web, see the
|
||||
[CSS overview](css-overview.html).
|
||||
|
||||
## Widgets
|
||||
|
||||
The content area in the CSS box model is the region that the widget considers its own.
|
||||
|
||||
The origin of the widgets coordinate system is the top left corner of the content area,
|
||||
and its size is the widgets size. The size can be queried with [method@Gtk.Widget.get_width]
|
||||
and [method@Gtk.Widget.get_height]. GTK allows general 3D transformations to position
|
||||
widgets (although most of the time, the transformation will be a simple 2D translation).
|
||||
The transform to go from one widgets coordinate system to another one can be obtained
|
||||
with [method@Gtk.Widget.compute_transform].
|
||||
|
||||
In addition to a size, widgets can optionally have a **_baseline_** to position text on.
|
||||
Containers such as [class@Gtk.Box] may position their children to match up their baselines.
|
||||
[method@Gtk.Widget.get_baseline] returns the y position of the baseline in widget coordinates.
|
||||
|
||||
When widget APIs expect positions or areas, they need to be expressed in this coordinate
|
||||
system, typically called **_widget coordinates_**. GTK provides a number of APIs to translate
|
||||
between different widgets' coordinate systems, such as [method@Gtk.Widget.compute_point]
|
||||
or [method@Gtk.Widget.compute_bounds]. These methods can fail (either because the widgets
|
||||
don't share a common ancestor, or because of a singular transformation), and callers need
|
||||
to handle this eventuality.
|
||||
|
||||
Another area that is occasionally relevant are the widgets **_bounds_**, which is the area
|
||||
that a widgets rendering is typically confined to (technically, widgets can draw outside
|
||||
of this area, unless clipping is enforced via the [property@Gtk.Widget:overflow] property).
|
||||
In CSS terms, the bounds of a widget correspond to the border area.
|
||||
|
||||
During GTK's layout algorithm, a parent widget needs to measure each visible child and
|
||||
allocate them at least as much size as measured. These functions take care of respecting
|
||||
the CSS box model and widget properties such as align and margin. This happens in the
|
||||
parent's coordinate system.
|
||||
|
||||
Note that the **_text direction_** of a widget does not influence its coordinate
|
||||
system, but simply determines whether text flows in the direction of increasing
|
||||
or decreasing X coordinates.
|
||||
|
||||
## Events
|
||||
|
||||
Event controllers and gestures report positions in the coordinate system of the widget
|
||||
they are attached to.
|
||||
|
||||
If you are dealing with raw events in the form of [class@Gdk.Event] that have positions
|
||||
associated with them (e.g. the pointer position), such positions are expressed in
|
||||
**_surface coordinates_**, which have their origin at the top left corner of the
|
||||
[class@Gdk.Surface].
|
||||
|
||||
To translate from surface to widget coordinates, you have to apply the offset from the
|
||||
top left corner of the surface to the top left corner of the topmost widget, which can
|
||||
be obtained with [method@Gtk.Native.get_surface_transform].
|
@@ -68,7 +68,7 @@ in a selector, widget names must be prefixed with a # character.
|
||||
| E:focus-within | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on all ancestors of the focus widget, unlike CSS |
|
||||
| E:focus-visible | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on focus widget and all ancestors, unlike CSS |
|
||||
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_INSENSITIVE |
|
||||
| E:checked | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
|
||||
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
|
||||
| E:indeterminate | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#indeterminate) | Corresponds to GTK_STATE_FLAG_INCONSISTENT |
|
||||
| E:backdrop, E:selected | | Corresponds to GTK_STATE_FLAG_BACKDROP, GTK_STATE_FLAG_SELECTED |
|
||||
| E:not(selector) | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#negation) | |
|
||||
|
@@ -66,10 +66,6 @@ You can compile the program above with GCC using:
|
||||
gcc $( pkg-config --cflags gtk4 ) -o example-0 example-0.c $( pkg-config --libs gtk4 )
|
||||
```
|
||||
|
||||
**Note**: If the above compilation does not work due to an error regarding `G_APPLICATION_DEFAULT_FLAGS`
|
||||
this could be due to your OS providing an older version of GLib. For GLib versions older than 2.74 you
|
||||
will need to replace `G_APPLICATION_DEFAULT_FLAGS` with `G_APPLICATION_FLAGS_NONE` in this example, and
|
||||
others in this documentation.
|
||||
For more information on how to compile a GTK application, please
|
||||
refer to the [Compiling GTK Applications](compiling.html)
|
||||
section in this reference.
|
||||
|
@@ -68,7 +68,6 @@ content_files = [
|
||||
"input-handling.md",
|
||||
"drag-and-drop.md",
|
||||
"drawing-model.md",
|
||||
"coordinates.md",
|
||||
"css-overview.md",
|
||||
"css-properties.md",
|
||||
"section-accessibility.md",
|
||||
@@ -242,7 +241,5 @@ content_images = [
|
||||
"images/rich-list.png",
|
||||
"images/data-table.png",
|
||||
"images/navigation-sidebar.png",
|
||||
"images/box-model-light.png",
|
||||
"images/box-model-dark.png",
|
||||
]
|
||||
urlmap_file = "urlmap.js"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 23 KiB |
@@ -1,193 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="box-model.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.84096521"
|
||||
inkscape:cx="265.76605"
|
||||
inkscape:cy="312.14133"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1123"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Arrow2"
|
||||
markerWidth="7.6999998"
|
||||
markerHeight="5.5999999"
|
||||
viewBox="0 0 7.7 5.6"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid">
|
||||
<path
|
||||
transform="scale(0.7)"
|
||||
d="M -2,-4 9,0 -2,4 c 2,-2.33 2,-5.66 0,-8 z"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
|
||||
id="arrow2L" />
|
||||
</marker>
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="Arrow2-4"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto-start-reverse"
|
||||
inkscape:stockid="Arrow2"
|
||||
markerWidth="7.6999998"
|
||||
markerHeight="5.5999999"
|
||||
viewBox="0 0 7.7 5.6"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="xMidYMid">
|
||||
<path
|
||||
transform="scale(0.7)"
|
||||
d="M -2,-4 9,0 -2,4 c 2,-2.33 2,-5.66 0,-8 z"
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:none"
|
||||
id="arrow2L-7" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:10.58333333;stroke-dasharray:none"
|
||||
id="rect234-0"
|
||||
width="112.51476"
|
||||
height="70.089249"
|
||||
x="38.634876"
|
||||
y="49.512993" />
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:0.487868;stroke-dasharray:none"
|
||||
id="rect234"
|
||||
width="146.21118"
|
||||
height="103.37679"
|
||||
x="21.283342"
|
||||
y="33.173706" />
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:0.54387;stroke-dasharray:none"
|
||||
id="rect234-3"
|
||||
width="79.543648"
|
||||
height="37.520485"
|
||||
x="55.724121"
|
||||
y="65.367287" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5834px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none"
|
||||
x="76.878265"
|
||||
y="100.819"
|
||||
id="text3935"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3933"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5834px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="76.878265"
|
||||
y="100.819">content</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5834px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none"
|
||||
x="77.072464"
|
||||
y="111.58885"
|
||||
id="text4767"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4765"
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="77.072464"
|
||||
y="111.58885">padding</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
style="fill:#000000;fill-opacity:1;stroke-width:0.264583"
|
||||
x="77.072464"
|
||||
y="124.8181"
|
||||
id="tspan4769" /></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5834px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none"
|
||||
x="77.337868"
|
||||
y="133.01045"
|
||||
id="text4767-1"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8053"
|
||||
x="77.337868"
|
||||
y="133.01045">margin</tspan><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan8055"
|
||||
x="77.337868"
|
||||
y="146.2397"></tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.5834px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="77.311295"
|
||||
y="123.22021"
|
||||
id="text7028"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan7026"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="77.311295"
|
||||
y="123.22021">border</tspan></text>
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2)"
|
||||
d="M 58.115912,67.846321 71.79645,67.813301"
|
||||
id="path9563" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2-4)"
|
||||
d="m 58.054931,67.806272 -0.03031,13.680545"
|
||||
id="path9563-6"
|
||||
inkscape:transform-center-x="0.99122989"
|
||||
inkscape:transform-center-y="-10.282891" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52785px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="74.660751"
|
||||
y="69.01046"
|
||||
id="text10129"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan10127"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52785px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
|
||||
x="74.660751"
|
||||
y="69.01046">X</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52785px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="56.974892"
|
||||
y="86.498825"
|
||||
id="text10133"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan10131"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.52785px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
|
||||
x="56.974892"
|
||||
y="86.498825">Y</tspan></text>
|
||||
<circle
|
||||
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path10187"
|
||||
cx="58.076889"
|
||||
cy="67.895195"
|
||||
r="0.2" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 8.8 KiB |
@@ -68,7 +68,6 @@ ui_files = [
|
||||
'stackswitcher.ui',
|
||||
'statusbar.ui',
|
||||
'switch.ui',
|
||||
'switch-state.ui',
|
||||
'toggle-button.ui',
|
||||
'video.ui',
|
||||
'volumebutton.ui',
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<object class="GtkWindow">
|
||||
<property name="decorated">0</property>
|
||||
<property name="resizable">0</property>
|
||||
<property name="default-width">280</property>
|
||||
<property name="default-height">120</property>
|
||||
<style>
|
||||
<class name="nobackground"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
<class name="shadow"/>
|
||||
<class name="background"/>
|
||||
<class name="frame"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">3</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<child>
|
||||
<object class="GtkSwitch">
|
||||
<property name="active">1</property>
|
||||
<property name="state">0</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSwitch">
|
||||
<property name="active">0</property>
|
||||
<property name="state">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@@ -103,15 +103,14 @@ fields, but e.g. buttons can take the focus too.
|
||||
|
||||
Input widgets can be given the focus by clicking on them, but focus
|
||||
can also be moved around with certain key events (this is known as
|
||||
“keyboard navigation”).
|
||||
GTK reserves the <kbd>Tab</kbd> key to move the focus to the next location,
|
||||
and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous one.
|
||||
In addition many containers allow “directional navigation” with the arrow keys.
|
||||
“keyboard navigation”). GTK reserves the Tab key to move the focus
|
||||
to the next location, and Shift-Tab to move it back to the previous
|
||||
one. In addition many containers allow “directional navigation” with
|
||||
the arrow keys.
|
||||
|
||||
Many widgets can be “activated” to trigger and action.
|
||||
E.g., you can activate a button or switch by clicking on them,
|
||||
but you can also activate them with the keyboard,
|
||||
by using the <kbd>Enter</kbd> or <kbd>Space</kbd> keys.
|
||||
Many widgets can be “activated” to trigger and action. E.g., you can
|
||||
activate a button or switch by clicking on them, but you can also
|
||||
activate them with the keyboard, by using the Enter or Space keys.
|
||||
|
||||
Apart from keyboard navigation, activation and directly typing into
|
||||
entries or text views, GTK widgets can use key events for activating
|
||||
@@ -122,17 +121,15 @@ GTK has traditionally supported different kinds of shortcuts:
|
||||
|
||||
- Accelerators are any other shortcuts that can be activated regardless
|
||||
of where the focus is, and typically trigger global actions, such as
|
||||
<kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit an application.
|
||||
- Mnemonics are usually triggered using <kbd>Alt</kbd>
|
||||
as a modifier for a letter.
|
||||
Ctrl-Q to quit an application.
|
||||
- Mnemonics are usually triggered using Alt as a modifier for a letter.
|
||||
They are used in places where a label is associated with a control,
|
||||
and are indicated by underlining the letter in the label. As a special
|
||||
case, inside menus (i.e. inside `GtkPopoverMenu`), mnemonics can be
|
||||
triggered without the modifier.
|
||||
- Key bindings are specific to individual widgets,
|
||||
such as <kbd>Ctrl</kbd>+<kbd>C</kbd> or <kbd>Ctrl</kbd>+<kbd>V</kbd>
|
||||
in an entry copy to or paste from the clipboard.
|
||||
They are only triggered when the widget has focus.
|
||||
- Key bindings are specific to individual widgets, such as Ctrl-C or
|
||||
Ctrl-V in an entry copy to or paste from the clipboard. They are only
|
||||
triggered when the widget has focus.
|
||||
|
||||
GTK handles accelerators and mnemonics in a global scope, during the
|
||||
capture phase, and key bindings locally, during the target phase.
|
||||
@@ -211,4 +208,4 @@ sequence, so setting the state on one does transfer the state to
|
||||
the others. They also are mutually exclusive, within a widget
|
||||
where may be only one gesture group claiming a given sequence.
|
||||
If another gesture group claims later that same sequence, the
|
||||
first group will deny the sequence.
|
||||
first group will deny the sequence:
|
||||
|
@@ -17,7 +17,6 @@ expand_content_md_files = [
|
||||
'actions.md',
|
||||
'input-handling.md',
|
||||
'drawing-model.md',
|
||||
'coordinates.md',
|
||||
'css-overview.md',
|
||||
'css-properties.md',
|
||||
'section-accessibility.md',
|
||||
|
@@ -258,7 +258,7 @@ Instead of implementing GtkWidget.destroy, you can implement GObject.dispose.
|
||||
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
|
||||
replace many uses of `gtk_container_add()` with equivalent container-specific
|
||||
APIs such as `gtk_grid_attach()`, and thereby reduce
|
||||
APIs such as `gtk_box_pack_start()` or `gtk_grid_attach()`, and thereby reduce
|
||||
the amount of work you have to do at the time of the switch.
|
||||
|
||||
### Review your use of icon resources
|
||||
@@ -402,9 +402,9 @@ is open, use the [property@Gtk.Window:modal] property of the dialog.
|
||||
|
||||
### Adapt to coordinate API changes
|
||||
|
||||
A number of coordinate APIs in GTK 3 had variants taking `int` arguments:
|
||||
A number of coordinate APIs in GTK 3 had `double` variants:
|
||||
`gdk_device_get_surface_at_position()`, `gdk_surface_get_device_position()`.
|
||||
These have been changed to use `double` arguments, and the `int` variants
|
||||
These have been changed to use doubles, and the `double` variants
|
||||
have been removed. Update your code accordingly.
|
||||
|
||||
Any APIs that deal with global (or root) coordinates have been
|
||||
@@ -875,10 +875,10 @@ reference.
|
||||
### Adapt to coordinate API changes
|
||||
|
||||
A number of APIs that are accepting or returning coordinates have
|
||||
been changed from `int`s to `double`s: `gtk_widget_translate_coordinates()`,
|
||||
been changed from ints to doubles: `gtk_widget_translate_coordinates()`,
|
||||
`gtk_fixed_put()`, `gtk_fixed_move()`. This change is mostly transparent,
|
||||
except for cases where out parameters are involved: you need to
|
||||
pass `double*` now, instead of `int*`.
|
||||
pass double* now, instead of int*.
|
||||
|
||||
### Adapt to GtkStyleContext API changes
|
||||
|
||||
|
@@ -119,23 +119,3 @@ it no longer has a resize handle for the window.
|
||||
|
||||
These are very specialized widgets that should better live with the application
|
||||
where they are used.
|
||||
|
||||
## Widget size api changes
|
||||
|
||||
The functions gtk_widget_get_allocated_width() and gtk_widget_get_allocated_height()
|
||||
are going away. In most cases, [method@Gtk.Widget.get_width] and [method@Gtk.Widget.get_height]
|
||||
are suitable replacements. Note that the semantics are slightly different though:
|
||||
the old functions return the size of the CSS border area, while the new functions return
|
||||
the size of the widgets content area. In places where this difference matters, you can
|
||||
use `gtk_widget_compute_bounds (widget, widget, &bounds)` instead.
|
||||
|
||||
The function gtk_widget_get_allocation() is also going away. It does not have a direct
|
||||
replacement, but the previously mentioned alternatives can be used for it too.
|
||||
|
||||
The function gtk_widget_get_allocated_baseline() has been renamed to [method@Gtk.Widget.get_baseline].
|
||||
|
||||
## Stop using GdkPixbuf
|
||||
|
||||
GTK is moving away from GdkPixbuf as the primary API for transporting image data, in favor
|
||||
of GdkTexture. APIs that are accepting or returning GdkPixbufs are being replaced by equivalent
|
||||
APIs using GdkTexture or GdkPaintable objects.
|
||||
|
@@ -263,13 +263,10 @@ the question you have, this list is a good place to start.
|
||||
* How do I load an image or animation from a file?
|
||||
|
||||
To load an image file straight into a display widget, use
|
||||
[ctor@Gtk.Picture.new_for_file] or [ctor@Gtk.Picture.new_for_filename].
|
||||
[ctor@Gtk.Picture.new_for_file] or [ctor@GTk.Picture.new_for_filename].
|
||||
To load an image for another purpose, use [ctor@Gdk.Texture.new_from_file].
|
||||
To load a video from a file, use [ctor@Gtk.MediaFile.new_for_file].
|
||||
|
||||
Note that [class@Gtk.Image] is meant for fixed-size icons. For arbitrary
|
||||
image files, you should use [class@Gtk.Picture].
|
||||
|
||||
* How do I draw text?
|
||||
|
||||
If you just want to put text into your user interface somewhere, it is
|
||||
@@ -286,8 +283,8 @@ the question you have, this list is a good place to start.
|
||||
pango_font_description_free (fontdesc);
|
||||
g_object_unref (layout);
|
||||
|
||||
See also the [Cairo Rendering](https://docs.gtk.org/PangoCairo/pango_cairo.html)
|
||||
section of the [Pango documentation](https://docs.gtk.org/Pango/).
|
||||
See also the [Cairo Rendering](https://developer.gnome.org/pango/stable/pango-Cairo-Rendering.html)
|
||||
section of the [Pango documentation](https://developer.gnome.org/pango/stable/).
|
||||
|
||||
To draw a piece of text in a widget [vfunc@Gtk.Widget.snapshot] implementation,
|
||||
use [method@Gtk.Snapshot.append_layout].
|
||||
@@ -304,8 +301,8 @@ the question you have, this list is a good place to start.
|
||||
pango_font_description_free (fontdesc);
|
||||
g_object_unref (layout);
|
||||
|
||||
See also the [Layout Objects](https://docs.gtk.org/Pango/class.Layout.html)
|
||||
section of the [Pango documentation](https://docs.gtk.org/Pango/).
|
||||
See also the [Layout Objects](https://developer.gnome.org/pango/stable/pango-Layout-Objects.html)
|
||||
section of the [Pango documentation](https://developer.gnome.org/pango/stable/).
|
||||
|
||||
* Why are types not registered if I use their `GTK_TYPE_BLAH` macro?
|
||||
|
||||
|
@@ -211,9 +211,6 @@ A number of options affect behavior instead of logging:
|
||||
`gl-disable`
|
||||
: Disable OpenGL support
|
||||
|
||||
`gl-fractional`
|
||||
: Enable fractional scaling for OpenGL. This is experimental
|
||||
|
||||
`gl-legacy`
|
||||
: Use a legacy OpenGL context
|
||||
|
||||
@@ -371,13 +368,6 @@ to rememdy this on the GTK side; the best bet before trying the above
|
||||
workarounds is to try to update your graphics drivers and Nahimic
|
||||
installation.
|
||||
|
||||
### `GSK_MAX_TEXTURE_SIZE`
|
||||
|
||||
Limit texture size to the minimum of this value and the OpenGL limit
|
||||
for texture sizes. This can be used to debug issues with texture slicing
|
||||
on systems where the OpenGL texture size limit would otherwise make
|
||||
texture slicing difficult to test.
|
||||
|
||||
### `GTK_CSD`
|
||||
|
||||
The default value of this environment variable is `1`. If changed
|
||||
|
@@ -128,7 +128,6 @@ Each state name is part of the `GtkAccessibleState` enumeration.
|
||||
| %GTK_ACCESSIBLE_STATE_INVALID | “aria-invalid” | `GtkAccessibleInvalidState` | Set when a widget is showing an error |
|
||||
| %GTK_ACCESSIBLE_STATE_PRESSED | “aria-pressed” | `GtkAccessibleTristate` | Indicates the current state of a [class@Gtk.ToggleButton] |
|
||||
| %GTK_ACCESSIBLE_STATE_SELECTED | “aria-selected” | boolean or undefined | Set when a widget is selected |
|
||||
| %GTK_ACCESSIBLE_STATE_VISITED | N/A | boolean or undefined | Set when a link-like widget is visited |
|
||||
|
||||
#### List of accessible properties
|
||||
|
||||
|
@@ -9,9 +9,9 @@ Lists are intended to be used whenever developers want to display many objects
|
||||
in roughly the same way.
|
||||
|
||||
Lists are perfectly fine to be used for very short list of only 2 or 3 elements,
|
||||
but generally scale to millions of items. Of course, the larger the list grows,
|
||||
the more care needs to be taken to choose the right data structures to keep things
|
||||
running well.
|
||||
but generally scale fine to millions of items. Of course, the larger the list
|
||||
grows, the more care needs to be taken to choose the right data structures to
|
||||
keep things running well.
|
||||
|
||||
Lists are meant to be used with changing data, both with the items itself changing
|
||||
as well as the list adding and removing items. Of course, they work just as well
|
||||
@@ -26,14 +26,12 @@ have a specific meaning in this context.
|
||||
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists.
|
||||
Examples of these widgets would be [`class@Gtk.ListView`] or [`class@Gtk.GridView`].
|
||||
|
||||
Views display data from a **_model_**. Models implement the [`iface@Gio.ListModel`]
|
||||
interface and can be provided in a variety of ways:
|
||||
Views display data from a **_model_**. A model is a [`iface@Gio.ListModel`] and
|
||||
models can be provided in 3 ways or combinations thereof:
|
||||
|
||||
* List model implementations for many specific types of data already exist, for
|
||||
example `GtkDirectoryList` or `GtkStringList`.
|
||||
|
||||
* There are generic list model implementations like`GListStore` that allow building
|
||||
lists of arbitrary objects.
|
||||
* Many list models implementations already exist. There are models that provide
|
||||
specific data, like `GtkDirectoryList`. And there are models like `GListStore`
|
||||
that allow building lists manually.
|
||||
|
||||
* Wrapping list models like `GtkFilterListModel` or `GtkSortListModel`
|
||||
modify, adapt or combine other models.
|
||||
@@ -49,8 +47,8 @@ The elements in a model are called **_items_**. All items are
|
||||
|
||||
Every item in a model has a **_position_** which is the unsigned integer that
|
||||
describes where in the model the item is located. The first item in a model is
|
||||
at position 0. The position of an item can change as other items are added or
|
||||
removed from the model.
|
||||
at position 0. The position of an item can of course change as other items are
|
||||
added or removed from the model.
|
||||
|
||||
It is important to be aware of the difference between items and positions
|
||||
because the mapping from position to item is not permanent, so developers
|
||||
@@ -73,10 +71,10 @@ with the item managed by the listitem. Finding a suitable factory implementation
|
||||
for the data displayed, the programming language and development environment
|
||||
is an important task that can simplify setting up the view tremendously.
|
||||
|
||||
Views support selections via a **_selection model_**. A selection model is
|
||||
an implementation of the [`iface@Gtk.SelectionModel`] interface on top of the
|
||||
[`iface@Gio.ListModel`] interface that allows marking each item in a model as
|
||||
either selected or not selected. Just like regular models, this can be implemented
|
||||
Views support selections via a **_selection model_**. A selection model is an
|
||||
implementation of the [`iface@Gtk.SelectionModel`] interface on top of the
|
||||
[`iface@Gio.ListModel`] interface that allows marking each item in a model as either
|
||||
selected or not selected. Just like regular models, this can be implemented
|
||||
either by implementing `GtkSelectionModel` directly or by wrapping a model with
|
||||
one of the GTK models provided for this purposes, such as [`class@Gtk.NoSelection`]
|
||||
or [`class@Gtk.SingleSelection`].
|
||||
@@ -89,18 +87,19 @@ item is exposed in the listitem via the [`property@Gtk.ListItem:selected`] prope
|
||||
|
||||
Views and listitems also support activation. Activation means that double
|
||||
clicking or pressing enter while inside a focused row will cause the view
|
||||
to emit a signal such as [`signal@Gtk.ListView::activate`]. This provides an
|
||||
easy way to set up lists, but can also be turned off on listitems if undesired.
|
||||
to emit and activation signal such as [`signal@Gtk.ListView::activate`]. This
|
||||
provides an easy way to set up lists, but can also be turned off on listitems
|
||||
if undesired.
|
||||
|
||||
Both selections and activation are supported among other things via widget
|
||||
[actions](#actions-overview). This allows developers to add widgets to their
|
||||
lists that cause selections to change or to trigger activation via the
|
||||
[`iface@Gtk.Actionable`] interface. For a list of all supported actions
|
||||
see the relevant documentation.
|
||||
lists that cause selections to change or to trigger activation via
|
||||
the [`iface@Gtk.Actionable`] interface. For a list of all supported actions see
|
||||
the relevant documentation.
|
||||
|
||||
## Behind the scenes
|
||||
|
||||
While it is not a problem for short lists to instantiate widgets for every
|
||||
While for short lists it is not a problem to instantiate widgets for every
|
||||
item in the model, once lists grow to thousands or millions of elements, this
|
||||
gets less feasible. Because of this, the views only create a limited amount of
|
||||
listitems and recycle them by binding them to new items. In general, views try
|
||||
@@ -108,7 +107,7 @@ to keep listitems available only for the items that can actually be seen on
|
||||
screen.
|
||||
|
||||
While this behavior allows views to scale effortlessly to huge lists, it has a
|
||||
few implications for what can be done with views. For example, it is not possible
|
||||
few implication on what can be done with views. For example, it is not possible
|
||||
to query a view for a listitem used for a certain position - there might not be
|
||||
one and even if there is, that listitem might soon be recycled for a new
|
||||
position.
|
||||
@@ -162,9 +161,9 @@ in particular `GListModel` do not. This was a design choice because the common
|
||||
use case is displaying lists and not trees and it greatly simplifies the API
|
||||
interface provided.
|
||||
|
||||
However, GTK provides functionality to make lists look and behave like trees
|
||||
for use cases that require trees. This is achieved by using the
|
||||
[`class@Gtk.TreeListModel`] model to flatten a tree into a list. The
|
||||
However, GTK provides functionality to make trees look and behave like lists
|
||||
for the people who still want to display lists. This is achieved by using
|
||||
the [`class@Gtk.TreeListModel`] model to flatten a tree into a list. The
|
||||
[`class@Gtk.TreeExpander`] widget can then be used inside a listitem to allow
|
||||
users to expand and collapse rows and provide a similar experience to
|
||||
`GtkTreeView`.
|
||||
@@ -175,35 +174,26 @@ on the topic.
|
||||
## List styles
|
||||
|
||||
One of the advantages of the new list widgets over `GtkTreeView` and cell
|
||||
renderers is that they are styleable using GTK CSS. This provides a lot of
|
||||
flexibility. The themes that ship with GTK provide a few predefined list
|
||||
styles that can be used in many situations:
|
||||
renderers is that they are fully themable using GTK CSS. This provides a
|
||||
lot of flexibility. The themes that ship with GTK provide a few predefined
|
||||
list styles that can be used in many situations:
|
||||
|
||||

|
||||
|
||||
This _rich list_ style is low density, spacious and uses an outline focus
|
||||
ring. It is suitable for lists of controls, e.g. in preference dialogs or
|
||||
This style of list is low density, spacious and uses an outline focus ring.
|
||||
It is suitable for lists of controls, e.g. in preference dialogs or
|
||||
settings panels. Use the `.rich-list` style class.
|
||||
|
||||

|
||||
|
||||
The _sidebar_ style of list is medium density, using a full background to
|
||||
indicate focus and selection. Use the `.navigation-sidebar` style class.
|
||||
This style of list is medium density, using a full background to indicate
|
||||
focus and selection. Use the `.navigation-sidebar` style class.
|
||||
|
||||

|
||||
|
||||
The _data table_ style of list is a high density table, similar in style to a
|
||||
traditional treeview. Individual cells can be selectable and editable. Use
|
||||
the `.data-table` style class.
|
||||
|
||||
## Sections
|
||||
|
||||
List models can optionally group their items into **_sections_**, by implementing
|
||||
the `GtkSectionModel` interface. Both `GtkListView` and `GtkGridView` can
|
||||
display headers for sections, by installing a separate **_header factory_**.
|
||||
|
||||
Many GTK list models support section inherently, or they pass through the
|
||||
section of a model they are wrapping.
|
||||
This style of list is a high density table, similar in style to a traditional
|
||||
treeview. Individual cells can be selectable and editable. Use the `.data-table`
|
||||
style class.
|
||||
|
||||
## Comparison to GtkTreeView
|
||||
|
||||
@@ -212,19 +202,20 @@ compares to the way they know. This section will try to outline the similarities
|
||||
and differences between the two.
|
||||
|
||||
This new approach tries to provide roughly the same functionality as the old
|
||||
approach but often uses a very different way to achieve these goals.
|
||||
approach but often uses a very different approach to achieve these goals.
|
||||
|
||||
The main difference and one of the primary reasons for this new development is
|
||||
that items can be displayed using regular widgets and the separate cell renderer
|
||||
machinery is no longer necessary. This allows all benefits that widgets provide,
|
||||
such as complex layout, animations and CSS styling.
|
||||
that items can be displayed using regular widgets and `GtkCellRenderer` is no
|
||||
longer necessary. This allows all benefits that widgets provide, such as complex
|
||||
layout and animating widgets and not only makes cell renderers obsolete, but
|
||||
also `GtkCellArea`.
|
||||
|
||||
The other big difference is the massive change to the data model. `GtkTreeModel`
|
||||
was a rather complex interface for a tree data structure. `GListModel` is
|
||||
deliberately designed to be a very simple data structure for lists only. (See
|
||||
was a rather complex interface for a tree data structure and `GListModel` was
|
||||
deliberately designed to be a simple data structure for lists only. (See
|
||||
[above](#displaying-trees)) for how to still do trees with this new model.)
|
||||
Another big change is that the new model allows for bulk changes via the
|
||||
`GListModel::items-changed` signal while `GtkTreeModel` only allows a single
|
||||
Another big change is that the new model allows for bulk changes via
|
||||
the `GListModel::items-changed` signal while `GtkTreeModel` only allows a single
|
||||
item to change at once. The goal here is of course to encourage implementation
|
||||
of custom list models.
|
||||
|
||||
@@ -240,8 +231,8 @@ via custom code in each widget, selection state is now meant to be managed by
|
||||
the selection models. In particular this allows for complex use cases with
|
||||
specialized requirements.
|
||||
|
||||
Finally here's a quick comparison chart of equivalent functionality to look for
|
||||
when transitioning code:
|
||||
Finally here's a quick list of equivalent functionality to look for when
|
||||
transitioning code for easy lookup:
|
||||
|
||||
| Old | New |
|
||||
| -------------------- | ------------------------------------------------------- |
|
||||
|
@@ -1,4 +1,4 @@
|
||||
Title: Using GTK with X11
|
||||
Title: GTK for the X Window System
|
||||
Slug: gtk-x11
|
||||
|
||||
On UNIX, the X backend is enabled by default, so you don't need to do anything
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app2_resources = gnome.compile_resources('exampleapp2_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
executable('exampleapp2',
|
||||
'exampleapp.c', 'exampleappwin.c', 'main.c', app2_resources,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app3_resources = gnome.compile_resources('exampleapp3_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
executable('exampleapp3',
|
||||
'exampleapp.c', 'exampleappwin.c', 'main.c', app3_resources,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app4_resources = gnome.compile_resources('exampleapp4_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
executable('exampleapp4',
|
||||
'exampleapp.c', 'exampleappwin.c', 'main.c', app4_resources,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app5_resources = gnome.compile_resources('exampleapp5_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
app5_schemas = gnome.compile_schemas()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app6_resources = gnome.compile_resources('exampleapp6_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
app6_schemas = gnome.compile_schemas()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app7_resources = gnome.compile_resources('exampleapp7_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
app7_schemas = gnome.compile_schemas()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app8_resources = gnome.compile_resources('exampleapp8 resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
app8_schemas = gnome.compile_schemas()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
app9_resources = gnome.compile_resources('exampleapp9_resources',
|
||||
'exampleapp.gresource.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
app9_schemas = gnome.compile_schemas()
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
bp_resources = gnome.compile_resources('bloatpad_resources',
|
||||
'bloatpad.gresources.xml',
|
||||
source_dir: meson.current_source_dir())
|
||||
source_dir: '.')
|
||||
|
||||
executable('bloatpad', 'bloatpad.c', bp_resources, dependencies: libgtk_dep, c_args: common_cflags)
|
||||
|
@@ -31,9 +31,10 @@ resize_cb (GtkWidget *widget,
|
||||
|
||||
if (gtk_native_get_surface (gtk_widget_get_native (widget)))
|
||||
{
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget));
|
||||
surface = gdk_surface_create_similar_surface (gtk_native_get_surface (gtk_widget_get_native (widget)),
|
||||
CAIRO_CONTENT_COLOR,
|
||||
gtk_widget_get_width (widget),
|
||||
gtk_widget_get_height (widget));
|
||||
|
||||
/* Initialize the surface to white */
|
||||
clear_surface ();
|
||||
|
@@ -1,7 +0,0 @@
|
||||
A trivial example
|
||||
=================
|
||||
|
||||
This is a very minimal example of an app that can be built against GTK.
|
||||
We use this in CI to test that building against the installed GTK works.
|
||||
|
||||
That is why there is a standalone meson.build in this subdirectory.
|
@@ -57,7 +57,7 @@ window_paste (GSimpleAction *action,
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (user_data);
|
||||
GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text");
|
||||
|
||||
|
||||
gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
|
||||
gtk_widget_get_clipboard (GTK_WIDGET (text)),
|
||||
NULL,
|
||||
@@ -221,7 +221,7 @@ plugin_action (GAction *action,
|
||||
g_message ("Color: %s", g_action_get_name (action));
|
||||
|
||||
css_provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_string (css_provider, css_to_load);
|
||||
gtk_css_provider_load_from_data (css_provider, css_to_load, -1);
|
||||
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
|
||||
GTK_STYLE_PROVIDER (css_provider),
|
||||
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#ifndef __BROADWAY_H__
|
||||
#define __BROADWAY_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
@@ -73,3 +74,4 @@ void broadway_output_pong (BroadwayOutput *output);
|
||||
void broadway_output_set_show_keyboard (BroadwayOutput *output,
|
||||
gboolean show);
|
||||
|
||||
#endif /* __BROADWAY_H__ */
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#ifndef __BROADWAY_PROTOCOL_H__
|
||||
#define __BROADWAY_PROTOCOL_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
@@ -369,3 +370,4 @@ typedef union {
|
||||
BroadwayReplyUngrabPointer ungrab_pointer;
|
||||
} BroadwayReply;
|
||||
|
||||
#endif /* __BROADWAY_PROTOCOL_H__ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user